Estoy considerando construir una aplicación, que, en esencia, consistiría en miles de declaraciones ... si ... más El propósito de la aplicación es poder predecir cómo se mueven las vacas en cualquier paisaje. Se ven afectados por cosas como el sol, el viento, la fuente de alimentos, los eventos repentinos, etc.
¿Cómo se puede gestionar una aplicación de este tipo? Me imagino que después de unos cientos de declaraciones IF, sería tan impredecible cómo reaccionaría el programa y depurar lo que llevaría a una cierta reacción significaría que uno tendría que atravesar todo el árbol de declaraciones IF cada vez.
He leído un poco sobre los motores de reglas, pero no veo cómo resolverían esta complejidad.
Respuestas:
El lenguaje de programación lógica Prolog puede ser lo que estás buscando. Su enunciado del problema no es lo suficientemente específico para que yo pueda evaluar si se ajusta bien, pero es bastante similar a lo que usted dice.
Un programa Prolog consta de hechos y reglas que se aplican. Aquí hay una regla de ejemplo simple que dice "Una vaca se mueve a una ubicación si tiene hambre y hay más comida en la nueva ubicación que en la antigua":
Todas las cosas en mayúsculas son variables, cosas de las que no sabes el valor. Prolog intenta encontrar valores para estas variables que satisfagan todas las condiciones. Este proceso se realiza con un poderoso algoritmo llamado unificación que es el corazón de Prolog y entornos de programación lógica similares.
Además de las reglas, se proporciona una base de datos de hechos. Un ejemplo simple que funciona con las reglas anteriores podría ser algo como:
Observe que white_cow y pasture, etc. no están escritos en mayúsculas. No son variables, son átomos.
Finalmente haces una consulta y preguntas qué va a pasar.
La primera consulta pregunta dónde se moverá la vaca blanca. Dadas las reglas y los hechos anteriores, la respuesta es No. Esto puede interpretarse como "No sé" o "No se mueve" dependiendo de lo que desee.
La segunda consulta pregunta dónde se mueve la vaca negra. Se mueve al pasto para comer.
La consulta final pregunta dónde se mueven todas las vacas. Como resultado, obtienes todo lo posible (Vaca, Destino) que tiene sentido. En este caso, el toro negro se mueve al pasto como se esperaba. Sin embargo, el toro enojado tiene dos opciones que satisfacen las reglas: puede moverse al pasto o al establo.
Nota: Han pasado años desde la última vez que escribí Prolog, todos los ejemplos pueden no ser sintácticamente válidos, pero la idea debería ser correcta.
fuente
Al abordar el problema de si web , puede crear un motor de reglas donde cada regla específica se codifique de forma independiente. Una mejora adicional para esto sería crear un lenguaje específico de dominio (DSL) para crear las reglas, sin embargo, un DSL solo desplaza el problema de una base de código (principal) a otra (DSL). Sin estructura, el DSL no funcionará mejor que el lenguaje nativo (Java, C #, etc.), por lo que volveremos a él después de encontrar un enfoque estructural mejorado.
El problema fundamental es que tiene un problema de modelización. Siempre que se encuentre con situaciones combinatorias como esta, es una señal clara de que la abstracción de su modelo que describe la situación es demasiado burda. Lo más probable es que combine elementos que deberían pertenecer a diferentes modelos en una sola entidad.
Si sigue desglosando su modelo, eventualmente disolverá por completo este efecto combinatorio. Sin embargo, al tomar este camino es fácil perderse en su diseño creando un desastre aún mayor, el perfeccionismo aquí no es necesariamente su amigo.
Las máquinas de estados finitos y los motores de reglas son solo un ejemplo de cómo este problema puede desglosarse y hacerse más manejable. La idea principal aquí es que una buena manera de deshacerse de un problema combinatorio como este es a menudo crear un diseño y repetirlo ad-nauseam en niveles anidados de abstracción hasta que su sistema funcione satisfactoriamente. Similar a cómo se usan los fractales para crear patrones intrincados. Las reglas siguen siendo las mismas sin importar si miras tu sistema con un microscopio o desde una vista panorámica.
Ejemplo de aplicar esto a su dominio.
Estás intentando modelar cómo se mueven las vacas por un terreno. Aunque su pregunta carece de detalles, supongo que su gran cantidad de ifs incluye un fragmento de decisión como, por ejemplo,
if cow.isStanding then cow.canRun = true
que se atasca a medida que agrega detalles del terreno. Por lo tanto, para cada acción que desee tomar, debe verificar todos los aspectos que pueda pensar y repetir estas verificaciones para la próxima acción posible.Primero necesitamos nuestro diseño repetible, que en este caso será un FSM para modelar los estados cambiantes de la simulación. Entonces, lo primero que haría es implementar un FSM de referencia, definir una interfaz de estado , una interfaz de transición y quizás un contexto de transiciónque puede contener información compartida que se pondrá a disposición de los otros dos. Una implementación básica de FSM cambiará de una transición a otra independientemente del contexto, aquí es donde entra en juego un motor de reglas. El motor de reglas encapsula limpiamente las condiciones que deben cumplirse para que la transición tenga lugar. Un motor de reglas aquí puede ser tan simple como una lista de reglas, cada una con una función de evaluación que devuelve un valor booleano. Para verificar si se debe realizar una transición, iteremos la lista de reglas y si alguna de ellas se evalúa como falsa, la transición no tiene lugar. La transición en sí contendrá el código de comportamiento para modificar el estado actual del FSM (y otras tareas posibles).
Ahora, si empiezo a implementar la simulación como un solo FSM grande en el nivel de DIOS, termino con MUCHOS estados posibles, transiciones, etc. Parece que el lío if-else está solucionado, pero en realidad solo se extiende: cada IF es ahora una regla que realiza una prueba contra una información específica del contexto (que en este punto contiene casi todo) y cada cuerpo IF está en algún lugar del código de transición.
Ingrese el desglose de fractales: el primer paso sería crear un FSM para cada vaca donde los estados son los propios estados internos de la vaca (de pie, correr, caminar, pastar, etc.) y las transiciones entre ellas se verían afectadas por el medio ambiente. Es posible que el gráfico no esté completo, por ejemplo, el pastoreo solo es accesible desde el estado de reposo, cualquier otra transición se descarta porque simplemente está ausente del modelo. Aquí separa efectivamente los datos en dos modelos diferentes, la vaca y el terreno. Cada uno con su propio conjunto de propiedades. Este desglose le permitirá simplificar el diseño general del motor. Ahora, en lugar de tener un único motor de reglas que decida todo lo que tiene, tiene motores de reglas múltiples y más simples (uno para cada transición) que deciden detalles muy específicos.
Debido a que estoy reutilizando el mismo código para el FSM, esta es básicamente una configuración del FSM. ¿Recuerdas cuando mencionamos DSL antes? Aquí es donde el DSL puede hacer mucho bien si tiene muchas reglas y transiciones para escribir.
Yendo más profundo
Ahora DIOS ya no tiene que lidiar con toda la complejidad en el manejo de los estados internos de la vaca, pero podemos impulsarlo aún más. Todavía hay mucha complejidad involucrada en la gestión del terreno, por ejemplo. Aquí es donde decides dónde es suficiente el desglose. Si, por ejemplo, en su DIOS termina manejando la dinámica del terreno (pasto largo, barro, barro seco, pasto corto, etc.) podemos repetir el mismo patrón. No hay nada que le impida incorporar tal lógica en el terreno mismo extrayendo todos los estados del terreno (hierba larga, hierba corta, fangosa, seca, etc.) en un nuevo FSM de terreno con transiciones entre los estados y quizás reglas simples. Por ejemplo, para llegar al estado fangoso, el motor de reglas debe verificar el contexto para encontrar líquidos, de lo contrario no es posible. Ahora Dios se volvió más simple aún.
Puede completar el sistema de FSM haciéndolos autónomos y dándoles un hilo a cada uno. Este último paso no es necesario, pero le permite cambiar dinámicamente la interacción del sistema al ajustar cómo delega su toma de decisiones (iniciar un FSM especializado o simplemente devolver un estado predeterminado).
¿Recuerdas cómo mencionamos que las transiciones también podrían hacer "otras tareas posibles"? Exploremos eso agregando la posibilidad de que diferentes modelos (FSM) se comuniquen entre sí. Puede definir un conjunto de eventos y permitir que cada FSM registre la escucha de estos eventos. Por lo tanto, si, por ejemplo, una vaca entra en un hex de terreno, el hex puede registrar oyentes para los cambios de transición. Aquí se vuelve un poco complicado porque cada FSM se implementa a un nivel muy alto sin ningún conocimiento del dominio específico que alberga. Sin embargo, puede lograr esto haciendo que la vaca publique una lista de eventos y la celda puede registrarse si ve eventos a los que puede reaccionar. Una buena jerarquía de eventos familiares aquí es una buena inversión.
Puede profundizar aún más modelando los niveles de nutrientes y el ciclo de crecimiento de la hierba, con ... lo adivinó ... un FSM de hierba incrustado en el modelo del parche de terreno.
Si llevas la idea lo suficientemente lejos, DIOS tiene muy poco que hacer, ya que todos los aspectos son casi autogestionados, liberando tiempo para gastar en cosas más piadosas.
Resumen
Como se indicó anteriormente, el FSM aquí no es la solución, solo un medio para ilustrar que la solución a dicho problema no se encuentra en el código por ejemplo, sino en cómo modela su problema. Lo más probable es que haya otras soluciones posibles y mucho mejores que mi propuesta FSM. Sin embargo, el enfoque de "fractales" sigue siendo una buena forma de manejar esta dificultad. Si se hace correctamente, puede asignar dinámicamente niveles más profundos donde sea importante y, al mismo tiempo, proporcionar modelos más simples donde sea menos importante. Puede poner en cola los cambios y aplicarlos cuando los recursos estén más disponibles. En una secuencia de acción, puede no ser tan importante calcular la transferencia de nutrientes de la vaca al parche de hierba. Sin embargo, puede registrar estas transiciones y aplicar los cambios en un momento posterior o simplemente aproximarse con una suposición educada simplemente reemplazando los motores de reglas o quizás reemplazando la implementación FSM por una versión ingenua más simple para los elementos que no están en el campo directo de interés (esa vaca en el otro extremo del campo) para permitir interacciones más detalladas para obtener el foco y una mayor parte de los recursos. Todo esto sin volver a visitar el sistema en su conjunto; Como cada parte está bien aislada, resulta más fácil crear un reemplazo directo que limite o extienda la profundidad de su modelo. Al usar un diseño estándar, puede aprovechar eso y maximizar las inversiones realizadas en herramientas ad-hoc como un DSL para definir reglas o un vocabulario estándar para eventos, comenzando nuevamente a un nivel muy alto y agregando refinamientos según sea necesario. Como cada parte está bien aislada, se hace más fácil crear un reemplazo directo que limite o extienda la profundidad de su modelo. Al usar un diseño estándar, puede aprovechar eso y maximizar las inversiones realizadas en herramientas ad-hoc como un DSL para definir reglas o un vocabulario estándar para eventos, comenzando nuevamente a un nivel muy alto y agregando refinamientos según sea necesario. Como cada parte está bien aislada, se hace más fácil crear un reemplazo directo que limite o extienda la profundidad de su modelo. Al usar un diseño estándar, puede aprovechar eso y maximizar las inversiones realizadas en herramientas ad-hoc como un DSL para definir reglas o un vocabulario estándar para eventos, comenzando nuevamente a un nivel muy alto y agregando refinamientos según sea necesario.
Proporcionaría un ejemplo de código, pero esto es todo lo que puedo permitirme ahora.
fuente
Parece que todas estas declaraciones condicionales de las que estás hablando realmente deberían ser datos que configuran tu programa en lugar de ser parte de tu propio programa. Si puede tratarlos de esa manera, podrá modificar la forma en que funciona su programa simplemente cambiando su configuración en lugar de tener que modificar su código y volver a compilar cada vez que desee mejorar su modelo.
Hay muchas formas diferentes de modelar el mundo real, dependiendo de la naturaleza de su problema. Sus diversas condiciones pueden convertirse en reglas o restricciones que se aplican a la simulación. En lugar de tener un código similar al siguiente:
en su lugar, puede tener un código similar al siguiente:
O, si puede desarrollar un programa lineal que modele el comportamiento de la vaca dada una cantidad de entradas, cada restricción podría convertirse en una línea en un sistema de ecuaciones. Luego puede convertirlo en un modelo de Markov que puede iterar.
Es difícil decir cuál es el enfoque correcto para su situación, pero creo que será mucho más fácil si considera que sus restricciones son entradas a su programa y no código.
fuente
Nadie ha mencionado esto, así que pensé que lo diría explícitamente:
Miles de reglas "If .. Then .. Else" son un signo de una aplicación mal diseñada.
Si bien la representación de datos específica del dominio podría parecerse a estas reglas, ¿está absolutamente seguro de que su implementación debe parecerse a la representación específica del dominio?
fuente
Utilice los lenguajes de software / computadora que sean adecuados para la tarea. Matlab se usa muy a menudo para modelar sistemas complejos, donde puede tener literalmente miles de condiciones. No utilizando las cláusulas if / then / else, sino mediante análisis numérico. R es un lenguaje de computadora de código abierto que está lleno de herramientas y paquetes para hacer lo mismo. Pero esto significa que también debe reformular su modelo en términos más matemáticos, de modo que pueda incluir tanto las influencias principales como las interacciones entre las influencias en los modelos.
Si aún no lo hizo, siga un curso sobre modelado y simulación. Lo último que debe hacer es considerar escribir un modelo como ese en términos de if - then - else. Tenemos cadenas de Monte Carlo Markov, máquinas de vectores de soporte, redes neuronales, análisis de variables latentes, ... Por favor, no retrocedas 100 años ignorando la riqueza de las herramientas de modelado que tienes disponibles.
fuente
Los motores de reglas pueden ayudar porque si hay tantas reglas if / then, podría ser útil tenerlas todas en un lugar fuera del programa donde los usuarios puedan editarlas sin necesidad de conocer un lenguaje de programación. Además, las herramientas de visualización pueden estar disponibles.
También puede buscar soluciones de programación lógica (como Prolog). Puede modificar rápidamente la lista de sentencias if / then y hacer que haga cosas como ver si cualquier combinación de entradas conduciría a ciertos resultados, etc. También podría ser más limpio en la lógica de predicados de primer orden que como código de procedimiento (o como código orientado a objetos).
fuente
De repente me di cuenta:
Debe usar un árbol de aprendizaje de decisiones (algoritmo ID3).
Es muy probable que alguien lo haya implementado en su idioma. Si no, podría portar una biblioteca existente
fuente
Esta es más una respuesta wiki comunitaria, agregando las diversas herramientas de modelado sugeridas por otras respuestas, acabo de agregar enlaces adicionales a los recursos.
No creo que sea necesario reafirmar que debería usar un enfoque diferente para miles de declaraciones if / else codificadas.
fuente
Cada aplicación grande contiene miles de
if-then-else
declaraciones, sin contar otros controles de flujo, y esas aplicaciones aún se depuran y mantienen, a pesar de su complejidad.Además, el número de declaraciones no hace que el flujo sea impredecible . La programación asincrónica sí. Si usa algoritmos deterministas sincrónicamente, tendrá un comportamiento 100% predecible, siempre.
Probablemente debería explicar mejor qué está tratando de hacer en Stack Overflow o Code Review para que las personas puedan sugerirle las técnicas de refactorización precisas que debe usar. También es posible que desee hacer preguntas más precisas, como "¿Cómo evito anidar demasiadas
if
declaraciones <dado un código>?".fuente
if
En el mejor de los casos, enormes grupos anidados de declaraciones se vuelven difíciles de manejar, por lo que se requiere un mejor enfoque.Haga que su aplicación sea manejable diseñándola bien. Diseñe su aplicación dividiendo las diversas lógicas comerciales en clases / módulos separados. Escriba pruebas unitarias que prueben cada una de estas clases / módulos individualmente. Esto es crucial y lo ayudará a garantizar que la lógica empresarial se implemente como se espera.
fuente
Probablemente no haya una sola forma de diseñar su solución a su problema, pero puede manejar la complejidad de la misma pieza por pieza si intenta separar las diferentes áreas donde se encuentra escribiendo grandes bloques de declaraciones if y aplicando soluciones a cada uno de esos pequeños problemas.
Busque técnicas como las reglas de las que se habló en Refactorización para encontrar formas de dividir grandes condicionales en fragmentos manejables: por ejemplo, varias clases con una interfaz común pueden reemplazar una declaración de caso.
Salir temprano también es de gran ayuda. Si tiene condiciones de error, elimínelas al comienzo de la función lanzando una excepción o regresando en lugar de dejar que se aniden.
Si divide sus condiciones en funciones de predicado, puede ser más fácil hacer un seguimiento de ellas. Además, si puede obtenerlos en un formato estándar, podría ser posible obtenerlos en una estructura de datos construida dinámicamente, en lugar de una codificada.
fuente
Te sugiero que uses un motor de reglas. En el caso de Java, jBPM u Oracle BPM pueden ser útiles. Los motores de reglas básicamente le permiten configurar la aplicación a través de XML.
fuente
El problema no está bien resuelto por las "reglas", ya sea descrito por el código de procedimiento "si-entonces" o por las numerosas soluciones de reglas diseñadas para aplicaciones comerciales. El aprendizaje automático proporciona una serie de mecanismos para modelar tales escenarios.
Fundamentalmente, uno tiene que formular algún esquema para la representación discreta de los factores (p. Ej., Sol, viento, fuente de alimento, eventos repentinos, etc.) que influyen en el "sistema" (es decir, las vacas en un potrero). A pesar de la creencia equivocada de que uno puede crear una representación funcional valorada real, en lugar de discreta, ninguna computadora en el mundo real (incluido el sistema nervioso humano) se basa en valores reales o se basa en valores reales.
Una vez que tenga su representación numérica para los factores relevantes, puede construir cualquiera de varios modelos matemáticos. Sugeriría un gráfico bipartito donde un conjunto de nodos representa vacas y el otro un área unitaria de pasto. Una vaca en cualquier caso ocupa una unidad de área de pasto. Para cada vaca existe un valor de utilidad asociado con la actual y todas las demás unidades de pasto. Si el modelo presupone que la vaca busca optimizar (lo que sea que signifique para la vaca) el valor de utilidad de su unidad de pasto, entonces las vacas se moverán de una unidad a otra en un esfuerzo por optimizar.
Un autómata celular funciona bien para ejecutar el modelo. La matemática subyacente en el mundo matemático realmente valioso que motiva el movimiento de las vacas es un modelo de gradiente de campo. Las vacas se mueven de posiciones de menor valor de utilidad percibido a posiciones de mayor valor de utilidad percibido.
Si se inyecta un cambio ambiental en el sistema, entonces no se moverá a una solución de estado estable de posicionamiento de vacas. También se convertirá en un modelo al que se podrían aplicar aspectos de la teoría de juegos; no es que eso necesariamente agregaría mucho a este caso.
La ventaja aquí es la matanza de vacas o la adquisición de nuevas vacas se puede manejar fácilmente restando y agregando celdas de "vaca" al gráfico bipartito, mientras el modelo se está ejecutando.
fuente
No creo que deba definir tantas declaraciones if-else. Desde mi punto de vista, su problema tiene múltiples componentes:
Debe ser asíncrono o multiproceso, porque tiene varias vacas con diferentes personalidades, diferentes configuraciones. Cada vaca se pregunta en qué dirección ir antes de su próximo movimiento. En mi opinión, un código de sincronización es una herramienta pobre para este problema.
La configuración del árbol de decisión cambia constantemente. Depende de la posición de la vaca real, el clima, el tiempo, el terreno, etc. En lugar de construir un árbol complejo si no, creo que deberíamos reducir el problema a una rosa de los vientos o una dirección - función de peso : figura 1 - dirección - funciones de peso para algunas de las reglas
La vaca siempre debe ir en la dirección que tenga el mayor peso total. Entonces, en lugar de construir un gran árbol de decisión, puede agregar un conjunto de reglas (con diferentes direcciones - funciones de peso) a cada vaca, y simplemente procesar el resultado cada vez que pregunte la dirección. Puede reconfigurar esas reglas por cada cambio de posición, o al pasar el tiempo, o puede agregar estos detalles como parámetros, cada regla debería obtener. Es una decisión de implementación. La forma más sencilla de obtener una dirección es agregar un bucle simple de 0 ° a 360 ° con un paso de 1 °. Después de eso, puede contar el peso de la suma de cada dirección 360 y ejecutar una función max () para obtener la dirección correcta.
No necesariamente necesita una red neuronal para hacer esto, solo una clase para cada regla, una clase para las vacas, tal vez para el terreno, etc. y una clase para el escenario (por ejemplo, 3 vacas con diferentes reglas y 1 terreno específico). figura 2: conexiones y nodos de decisión asíncronos de aplicaciones de vaca
nota: probablemente necesitará un marco de mensajería para implementar algo como esto
Entonces, si hacer vacas de aprendizaje no es parte de su problema, no necesita una red neuronal o algoritmos genéticos. No soy un experto en IA, pero supongo que si desea adaptar sus vacas a las reales, puede hacerlo simplemente con un algoritmo genético y el conjunto adecuado de reglas. Si entiendo bien, necesita una población de vacas con configuraciones de reglas aleatorias. Después de eso, puede comparar el comportamiento de las vacas reales con el comportamiento de su población modelo y mantener el 10% que recorre el camino más cercano a las reales. Después de eso, puede agregar nuevas restricciones de configuración de reglas a su fábrica de vacas en función del 10% que mantuvo, y agregar nuevas vacas aleatorias a la población, y así sucesivamente, hasta que obtenga una vaca modelo que se comporte como las reales ...
fuente
Añadiría que podría ser el caso de que si realmente tienes miles de reglas IF ... LUEGO, podrías estar especificando en exceso. Por lo que vale, las charlas de modelado de redes neuronales a las que he asistido a menudo comienzan afirmando cómo con "un simple conjunto de reglas" pueden generar un comportamiento bastante complejo y razonablemente coincidente con la realidad (de, en esos casos, neuronas reales en acción). Entonces, ¿estás seguro?necesitas miles de condiciones? Quiero decir, además de 4-5 aspectos del clima, la ubicación de las fuentes de alimentos, los eventos repentinos, el pastoreo y el terreno, ¿realmente van a tener muchas más variables? Claro, si trataste de hacer todas las permutaciones posibles de combinar esas condiciones, entonces fácilmente podrías tener muchos miles de reglas, pero ese no es el enfoque correcto. Quizás un enfoque de estilo de lógica difusa en el que los diversos factores introducen un sesgo en la ubicación de cada vaca que se combinan con una decisión general le permitiría hacer esto en muchas menos reglas.
También estoy de acuerdo con todos los demás en que el conjunto de reglas debe estar separado del flujo general de código, para que pueda modificarlo fácilmente sin cambiar el programa. Incluso podría crear conjuntos de reglas de la competencia y ver cómo funcionan contra los datos reales del movimiento de las vacas. Suena divertido.
fuente
Se han mencionado sistemas expertos, que son un área de IA. Para ampliar un poco sobre estos, leer sobre motores de inferencia puede ayudarlo con esto. Una búsqueda en Google podría ser más útil: escribir el DSL es la parte fácil, puede hacerlo trivialmente con un analizador como Gold Parser. La parte difícil proviene de construir su árbol de decisiones y ejecutarlas de manera eficiente.
Muchos sistemas médicos ya utilizan estos motores, por ejemplo, el sitio web NHS Direct del Reino Unido .
Si eres un .NET'er, entonces Infer.NET puede ser útil para ti.
fuente
Debido a que observa el movimiento de la vaca, están atrapados en una dirección de 360 grados (las vacas no pueden volar). También tiene una tarifa que está viajando. Esto se puede definir como un vector.
Ahora, ¿cómo lidias con cosas como la posición del sol, la pendiente de la colina, el ruido fuerte?
Cada uno de los grados sería una variable que significaría el deseo de ir en esa dirección. Digamos que una ramita se rompe a la derecha de la vaca a 90 grados (suponiendo que la vaca mire 0 grados). El deseo de ir a la derecha disminuirá y el deseo de ir a 270 (izquierda) aumentará. Revisa todos los estímulos sumando o restando su influencia en el deseo de las vacas de ir en una dirección. Una vez que se aplican todos los estímulos, la vaca irá en la dirección del deseo más elevado.
También puede aplicar gradientes para que los estímulos no tengan que ser binarios. Por ejemplo, una colina no está recta en una dirección. Tal vez la vaca está en un valle o en una carretera en una colina donde estaba completamente recta, a 45 * cuesta arriba leve a 90 * colina abajo levemente. A 180 * cuesta arriba empinada.
Luego puede ajustar el peso de un evento y su dirección de influencia. En lugar de una lista de if thens, tienes una prueba buscando el máximo. Además, cuando desee agregar un estímulo, simplemente puede aplicarlo antes de la prueba y no tiene que lidiar con agregar más y más complejidad.
En lugar de decir que la vaca irá en cualquier dirección 360, vamos a dividirla en 36 direcciones. Cada uno de 10 grados
En lugar de decir que la vaca irá en cualquier dirección 360, vamos a dividirla en 36 direcciones. Cada uno de 10 grados. Dependiendo de cuán específico debes ser.
fuente
Usa POO. ¿Qué tal crear un grupo de clases que manejen las condiciones básicas y ejecuten métodos aleatorios para simular lo que está haciendo?
Consigue un programador para que te ayude.
fuente
COW_METHODS
parece no ser más que una colección de métodos poco relacionados. ¿Dónde está la separación de las preocupaciones? Relacionado con la pregunta, ¿cómo ayuda esto al autor de la pregunta?