2009-06-05 9 views
6

A menudo tengo un código basado en un algoritmo específico bien definido. Esto se comenta bien y parece apropiado. Para la mayoría de los conjuntos de datos, el algoritmo funciona de maravilla.Cómo administrar casos especiales y heurística

Pero luego las cajas de borde, los casos especiales, la heurística se agregan para resolver problemas particulares con conjuntos de datos particulares. A medida que crece el número de casos especiales, los comentarios se vuelven cada vez más brumosos. Me temo volver y mirar este código dentro de un año e intentar recordar por qué se agregó cada caso especial o heurística.

A veces me gustaría poder insertar o vincular gráficos en el código fuente, así que podría decir con eficacia, "en el gráfico de este conjunto de datos, esta característica particular causaba que la rutina se disparara incorrectamente, así que por qué se añadió este fragmento de código ".

¿Cuáles son algunas de las mejores prácticas para manejar situaciones como esta?

Siempre se requieren casos especiales para manejar estos casos inusuales/de borde. ¿Cómo se las puede manejar para mantener el código relativamente legible y comprensible?

Considere un ejemplo relacionado con el reconocimiento de características de las fotos (no es exactamente en lo que estoy trabajando, pero la analogía parece apta). Cuando encuentro una imagen particular para la cual falla el algoritmo general y se necesita un caso especial, grabo lo mejor que puedo esa información en un comentario (o como alguien sugirió a continuación, un nombre de función descriptiva). Pero lo que a menudo falta es un enlace permanente al archivo de datos en particular que exhibe el comportamiento en cuestión. Si bien mi comentario debería describir el problema, y ​​probablemente diga "ver archivo foo.jp para obtener un ejemplo de este comportamiento", este archivo nunca se encuentra en el árbol de origen y puede perderse fácilmente.

En casos como este, ¿las personas agregan archivos de datos al árbol de fuentes como referencia?

+0

Si proporciona un ejemplo de código, apuesto a que podría obtener algunos consejos muy específicos de algunos de los expertos aquí. –

+0

No estoy seguro de que la programación integrada realmente importe aquí. Sugiero eliminar la etiqueta. – Aardvark

+0

¿Es posible eliminar el código de los casos especiales de su algoritmo y colocarlos en una estructura más genérica para que se puedan volver a agregar de una manera más limpia? Por ejemplo, ¿puedes usar funtores que se puedan modificar para diferentes conjuntos de datos (de forma parecida a como STL te permite especificar funtores de comparación)? Su explicación del problema es un poco vaga, por lo que es difícil hacerse una idea de cuál es el verdadero problema. –

Respuesta

2

Si tiene una base de conocimientos o una wiki para el proyecto, puede agregar el gráfico en ella, vinculándola en el método Matthew's Fowler quot ey también en el mensaje de confirmación de control de origen para el cambio de borde.

//See description at KB#2312 
private object SolveXAndYEdgeCase(object param) 
{ 
    //modify param to solve for edge case 
    return param; 
} 

Commit Message: Solution for X and Y edge case, see description at KB#2312 

Es más trabajo, pero una forma de documentar los casos más a fondo que los simples casos de prueba o comentarios. Aunque se podría argumentar que los casos de prueba deberían ser documentación suficiente, es posible que no desee almacenar todo el conjunto de datos que falla, por ejemplo.

Recuerde, los problemas vagos conducen a soluciones vagas.

+0

Tengo un wiki de proyecto y una base de datos de errores, pero en realidad no están vinculados. En 5 años, mientras puedo encontrar el código fuente. ¿Podré encontrar la base de datos de errores? Tal vez ese es mi problema. – loneRanger

+0

Realmente debería tener su KB o la herramienta de seguimiento de problemas y la wiki en el mismo régimen de copia de seguridad que su código fuente. No solo para resolver su caso particular, sino también por muchas otras razones, como si realmente deseara mantener el historial de errores, fechas de resolución, descripción, etc. para poder aprender de él y almacenar información relevante. Así que si no está seguro de que podrá encontrar la base de datos de errores o wiki en unos años, asegúrese de hacerlo. –

0

Sin saber la naturaleza específica de su problema no es fácil dar una respuesta, pero en mi propia experiencia, se debe evitar el manejo de casos especiales en el código. ¿No has pensado en implementar un motor de reglas o algo así para manejar casos especiales fuera de tu algoritmo de procesamiento principal?

6

Martin Fowler dijo en su libro de refactorización que cuando sienta la necesidad de agregar un comentario a su código, primero vea si puede encapsular ese código en un método y darle un nombre al método que reemplace el comentario.

por lo que como resumen puede crear un método llamado.

private bool ConditionXAndYHaveOccurred(object param) 
{ 
    // code to check for conditions x and y 
    return result; 
} 

private object ApplySolutionForEdgeCaseWhenXAndYHappen(object param) 
{ 
    //modify param to solve for edge case 
    return param; 
} 

A continuación, puede escribir código como

if(ConditionXAndYHaveOccurred(myObject)) 
{ 
    myObject = ApplySolutionForEdgeCaseWhenXAndYHappen(myObject); 
} 

No es un ejemplo concreto duro y rápido, pero sería ayudar con la lectura en un año o dos.

+0

Si bien creo que los nombres de las funciones descriptivas son geniales, y trato de hacerlos siempre que sea posible, no creo que sea posible reemplazar un párrafo de texto descriptivo con un nombre de función. – loneRanger

+1

El otro lado de eso es que los Comentarios a menudo no se mantienen actualizados con el código.Así que ese párrafo de comentarios puede terminar siendo lo más confuso sobre tu código cuando vuelvas a él más tarde después de algunas revisiones. Lo ideal sería que comentas por qué escribiste el código, no lo que estás haciendo. En ese caso, siéntase libre de etiquetar sus funciones descriptivas con la narración que explica exactamente por qué existe. –

+0

Desafortunadamente cierto, sobre comentarios desactualizados. – loneRanger

4

Las pruebas unitarias pueden ayudar aquí. Las pruebas que realmente simulan los casos especiales a menudo pueden servir como documentación sobre por qué el código hace lo que hace. Esto a menudo puede ser mejor que simplemente describir el problema en un comentario.

No es que esto sustituye a mover el manejo de sus propias funciones y comentarios decentes caso especial ...

1

normalmente no soy un defensor del desarrollo basado en pruebas y estilos similares que hacen hincapié en las pruebas demasiado, pero esto parece para ser un caso perfecto donde un montón de pruebas de unidad puede ayudar mucho.Y ni siquiera en primer lugar para detectar errores de cambios posteriores, sino simplemente para documentar todos los casos especiales que deben abordarse.

Algunas buenas pruebas de unidad con comentarios en ellas son en sí mismas la mejor descripción de los casos especiales. Y el comentario del código en sí también es más fácil. Uno puede simplemente señalar algunas pruebas unitarias que ilustran el problema que se está resolviendo en ese punto del código.

0

Parece que necesita una documentación más completa que los comentarios del código. De esa forma, alguien podría buscar la función en cuestión en la documentación y recibir una imagen de ejemplo que requiera un caso especial.

1

Sobre el

a veces me gustaría que hubiera una manera de incrustar o gráficos de enlace en el código fuente, así que podría decir de manera efectiva "en el gráfico de este conjunto de datos, esta característica particular aquí estaba causando que la rutina se disparara incorrectamente, por eso se agregó esta pieza del código ".

parte:

Si el "gráfico" que desea incrustar es un gráfico, y si se utiliza Doxygen, puede incrustar dot comandos en su comentario para generar un gráfico en la documentación:

/** 
If we have a subgraph looking like this: 
\dot 
digraph g{ 
A->B; 
A->C; 
B->C; 
} 
\enddot 
the usual method does not work well and we use this heuristic instead. 
*/ 
1

Don Knuth inventó literate programming para que la documentación de su programa incluya gráficas, gráficos, tablas, ecuaciones matemáticas y todo lo que necesite para que se entienda. Un programa de alfabetización es una excelente manera de explicar por qué algo es como es y cómo se hizo de esa manera con el tiempo. Hay muchas, muchas herramientas de programación literaria; la herramienta "noweb" es una de las más simples y se envía con algunas distribuciones de Linux.

Cuestiones relacionadas