El siguiente escenario me sucedió varias veces.
Programé un algoritmo que resuelve un cierto problema. Funciona bien y encuentra las soluciones correctas. Ahora, quiero tener una opción para decirle al algoritmo "escribe una explicación completa de cómo llegaste a la solución". Mi objetivo es poder usar el algoritmo en demostraciones en línea, clases de tutoría, etc. Todavía quiero tener una opción para ejecutar el algoritmo en tiempo real, sin las explicaciones. ¿Cuál es un buen patrón de diseño para usar?
EJEMPLO: Supongamos que implemento este método para encontrar el máximo divisor común . El método implementado actual devuelve la respuesta correcta, pero sin explicaciones. Quiero tener una opción para que el método explique sus acciones, como:
Initially, a=6 and b=4. The number of 2-factors, d, is initialized to 0.
a and b are both even, so we divide them by 2 and increment d by 1.
Now, a=3 and b=2.
a is odd but b is even, so we divide b by 2.
Now, a=3 and b=1.
a and b are both odd, so we replace a by (a-b)/2 = 1.
Now, a=1 and b=1.
a=b, so the GCD is a*2^d = 2.
La salida debe devolverse de modo que pueda mostrarse fácilmente tanto en la consola como en aplicaciones basadas en la web.
¿Cuál es un buen patrón para proporcionar explicaciones cuando sea necesario, sin dañar el rendimiento en tiempo real del algoritmo cuando no se necesitan explicaciones?
fuente
Un buen patrón es el observador. https://en.wikipedia.org/wiki/Observer_pattern
En su algoritmo, en cada punto donde desea generar algo, notifica a algunos observadores. Luego deciden qué hacer, ya sea para generar su texto en la consola, o enviarlo al motor HTML / Apache, etc.
Dependiendo de su lenguaje de programación, puede haber diferentes formas de acelerarlo. Por ejemplo, en Java (trátelo como pseudocódigo, por brevedad; dejarlo al lector "correcto", con getters, setters):
Esto es un poco detallado, pero la verificación
==null
debe ser lo más rápida posible.(Tenga en cuenta que en el caso general,
observer
probablemente sería unVector observers
lugar para permitir más de un observador; esto, por supuesto, también es posible y no generará más sobrecarga; aún puede poner la optimización que establezca enobservers=null
lugar de tener un vacíoVector
)Por supuesto, implementaría diferentes tipos de observadores dependiendo de lo que quiera lograr. También puede poner estadísticas de tiempo, etc. allí, o hacer otras cosas elegantes.
fuente
Como una ligera mejora al registro directo, cree algún tipo de objeto que modele una ejecución del algoritmo. Agregue un "paso" a este objeto contenedor cada vez que su código haga algo interesante. Al final del algoritmo, registre los pasos acumulados desde el contenedor.
Esto tiene algunas ventajas:
EDITAR: Como comentaron otros, las lambdas tienen sobrecarga, por lo que tendría que comparar para asegurarse de que esta sobrecarga sea menor que la evaluación innecesaria del código requerido para construir la cadena de registro (las entradas de registro a menudo no son simples literales, sino que implican obtener información contextual de objetos participantes).
fuente
Normalmente busco la ramificación, lo que significa que busco declaraciones if. Debido a que estos indican que evalúo un valor, eso controlará el flujo del algoritmo. En cada uno de estos casos (cada condición), puedo registrar el camino elegido y por qué fue elegido.
Entonces, básicamente, registraría los valores de entrada (estado inicial), cada rama elegida (condicionales) y los valores al ingresar a la rama elegida (estado temporal).
fuente