Primero un poco de historia. Estoy codificando una búsqueda de Age -> Rate. Hay 7 corchetes de edad, por lo que la tabla de búsqueda es de 3 columnas (de | a | tasa) con 7 filas. Los valores rara vez cambian: son tasas legisladas (primera y tercera columnas) que han permanecido igual durante 3 años. Pensé que la forma más fácil de almacenar esta tabla sin codificarla es en la base de datos en una tabla de configuración global, como un único valor de texto que contiene un CSV (así que "65,69,0.05,70,74,0.06" es cómo se almacenarían los niveles 65-69 y 70-74). Relativamente fácil de analizar y luego usar.
Luego me di cuenta de que para implementar esto, tendría que crear una nueva tabla, un repositorio para envolverlo, pruebas de capa de datos para el repositorio, pruebas unitarias alrededor del código que desencadena el CSV en la tabla y pruebas alrededor de la búsqueda en sí. El único beneficio de todo este trabajo es evitar codificar la tabla de búsqueda.
Cuando se habla con los usuarios (que actualmente usan la tabla de búsqueda directamente, mirando una copia impresa), la opinión es más o menos que "las tasas nunca cambian". Obviamente, eso no es realmente correcto: las tasas solo se crearon hace tres años y en el pasado las cosas que "nunca cambian" han tenido la costumbre de cambiar, por lo que para programar defensivamente esto definitivamente no debería almacenar la tabla de búsqueda en la aplicación.
Excepto cuando pienso en YAGNI . La función que estoy implementando no especifica que las tarifas cambiarán. Si las tarifas cambian, todavía cambiarán tan raramente que el mantenimiento ni siquiera es una consideración, y la función no es lo suficientemente crítica como para que algo se vea afectado si hubiera un retraso entre el cambio de la tarifa y la aplicación actualizada.
Casi he decidido que no perderé nada de valor si codifico la búsqueda, y no estoy demasiado preocupado por mi enfoque de esta característica en particular. Mi pregunta es, como profesional, ¿he justificado adecuadamente esa decisión? La codificación de valores es un mal diseño, pero ir a la molestia de eliminar los valores de la aplicación parece violar el principio YAGNI.
EDITAR Para aclarar la pregunta, no me preocupa la implementación real. Me preocupa que pueda hacer algo rápido y malo y justificarlo diciendo YAGNI, o puedo adoptar un enfoque más defensivo y de alto esfuerzo, que incluso en el mejor de los casos tiene beneficios bajos. Como programador profesional, ¿mi decisión de implementar un diseño que sé que es defectuoso simplemente se reduce a un análisis de costo / beneficio?
EDITAR Si bien todas las respuestas fueron muy interesantes, ya que creo que esto se reduce a las opciones de diseño de un individuo, creo que las mejores respuestas fueron @ Corbin y @EZ Hart, ya que traen a colación cosas que no había considerado en la pregunta:
- la falsa dicotomía de "eliminar correctamente los valores codificados" moviéndolo a la base de datos versus "aplicar eficientemente YAGNI" utilizando codificación rígida. Había una tercera opción de poner la tabla de búsqueda en la configuración de la aplicación, que no incurre en la sobrecarga de la manera correcta y sin la eficiencia de YAGNI. Por lo general, no estamos limitados a ninguna de las decisiones, y luego se reduce a una decisión de costo / beneficio.
- la generación de código puede reducir la sobrecarga de mover los valores codificados a la base de datos, y de una manera que también elimina mi decisión de ingeniería excesiva de procesar un CSV en la tabla. Potencialmente, esto también agrega un problema de mantenimiento a largo plazo con el código generado si los requisitos básicos cambian para el método de búsqueda. Todo esto solo afecta el análisis de costo / beneficio, y es probable que si hubiera tenido esa automatización disponible, ni siquiera hubiera considerado codificar algo como esto.
Estoy marcando la respuesta de @ Corbin como correcta porque cambia mis supuestos del costo de desarrollo, y probablemente agregaré algunas herramientas de generación de código a mi arsenal en el futuro cercano.
Respuestas:
Encontraste una falla en tu proceso de desarrollo. Cuando es difícil hacer lo correcto (crear la tabla, el repositorio, las pruebas de repositorio, las pruebas de aplanamiento ...), los desarrolladores encontrarán una forma de evitarlo. Esto generalmente implica hacer lo incorrecto. En este caso, es tentador tratar los datos de la aplicación como lógica de la aplicación. No lo hagas En cambio, agregue automatizaciones útiles a su proceso de desarrollo. Usamos CodeSmith para generar el código aburrido y repetitivo que nadie quiere escribir. Después de crear una tabla, ejecutamos CodeSmith y genera los DAO, DTO y elimina las pruebas unitarias para cada uno.
Dependiendo de las tecnologías que esté utilizando, debería tener opciones similares. Muchas herramientas ORM generarán modelos a partir de un esquema existente. Las migraciones de rieles funcionan en la dirección opuesta: tablas de modelos. La metaprogramación en lenguajes dinámicos es particularmente fuerte para eliminar el código repetitivo. Tendrá que trabajar un poco más para generar todo lo que necesita si tiene una aplicación compleja de varios niveles, pero vale la pena. No dejes que la sensación, "wow, esto es un dolor en el cuello" te impida hacer lo correcto.
Ah, y no almacene sus datos en un formato que requiera procesamiento adicional (CSV). Eso solo agrega pasos adicionales que requieren su atención y pruebas.
fuente
Para desconectar y ampliar la respuesta de @ Thorbjørn Ravn Andersen: Mantener el cálculo / búsqueda en un lugar es un buen comienzo.
Su proceso de pensamiento de defensa frente a YAGNI es un problema común. En este caso, sugeriría que sea informado por dos cosas más.
En primer lugar, ¿cómo se presentaron los requisitos del usuario? ¿Especificaron la editabilidad de las tarifas? Si no es así, ¿la complejidad adicional es parte de algo por lo que puede facturar o no? (o si está en el personal, ¿puede pasar su tiempo haciendo otro trabajo en su lugar?) Si es así, definitivamente continúe y entregue lo que razonablemente se le pidió.
En segundo lugar, y quizás lo más importante, es improbable que la simple editabilidad cumpla un requisito real ante un cambio legislativo. Si las tarifas cambian, es probable que haya una fecha límite y algún procesamiento antes y después que tenga que suceder. Además, si esa misma interfaz tiene que hacer algún tipo de procesamiento de reclamos con fecha anterior, entonces la tasa correcta debería buscarse en función de la fecha efectiva de la entrada, en lugar de la fecha real.
En resumen, estoy señalando que un requisito editable real puede ser bastante complejo, por lo que, a menos o hasta que se desarrolle, lo simple probablemente sea mejor.
Buena suerte
fuente
Haga que la búsqueda real sea una función de biblioteca. Luego puede ver todo el código usando esa búsqueda en su repositorio de origen, para que sepa qué programas deben actualizarse cuando cambian las tarifas.
fuente
PensionRateLookup
clase tal vez) que luego se usa globalmente. Lo haría independientemente de si está almacenado fuera de la aplicación o codificado, de esa manera solo sePensionRateLookup
necesita mantener la implementación de la clase. Mi problema es cómo he usado YAGNI para llegar a la conclusión de que codificar la tabla de búsqueda es aceptable.Déjame ver si tengo tu pregunta correcta. Tiene 2 opciones para implementar una función: o codifica un valor y su función es fácil de implementar (pero no le gusta la parte del código) o tiene un gran esfuerzo para "rehacer" muchas cosas que se hacen para que pueda desarrollar su función de manera limpia. ¿Es eso correcto?
Lo primero que se me ocurre es "Lo más importante acerca de conocer las buenas prácticas es saber cuándo estás mejor sin ellas".
En este caso, el esfuerzo es muy alto, por lo que puede hacerlo de manera limpia, las posibilidades de efecto colateral de este cambio son grandes y el rendimiento que obtendría es pequeño (como explicó, es probable que no lo haga) cambio).
Usaría el enfoque de código duro (pero prepárelo para que sea flexible en el futuro) y, en caso de cambio de esta tasa en el futuro, aproveche la oportunidad para refactorizar toda esta sección de mal diseño del código. Por lo tanto, el tiempo y el costo podrían estimarse correctamente y el costo de cambiar su valor codificado sería mínimo.
Este sería mi enfoque :)
fuente
Este es un elemento que "no cambiará" hasta que lo haga. Es inevitable que cambie, pero ese tiempo puede estar un poco lejos.
Tu justificación es correcta. En este momento, el cliente no solicitó la capacidad de cambiar fácilmente esas tarifas. Como tal, YAGNI.
Sin embargo, lo que no desea es el código que accede a sus tarifas e interpreta los resultados dispersos por toda la base de código. Un buen diseño de OO le permitiría encapsular la representación interna de sus tarifas en una clase, y solo exponer uno o dos métodos necesarios para usar los datos.
Necesitará esa encapsulación para evitar errores de copiar y pegar, o tendrá que realizar una refactorización en todo el código que usa las tasas cuando necesite hacer un cambio en la representación interna. Cuando tomas esa precaución inicial, el enfoque más complicado puede ser un simple intercambio y reemplazo por la versión más destacada.
Además, llame al cliente la limitación del diseño actual. Dígales que para mantener el cronograma codificó los valores, lo que requiere un cambio de codificación para actualizarlos. De esa manera, cuando se dan cuenta de los cambios en las tasas pendientes debido a la nueva legislación, pueden elegir simplemente actualizar la tabla de búsqueda o realizar el cambio más complicado en ese momento. Pero pon esa decisión en su regazo.
fuente
Divida la diferencia y coloque los datos de velocidad en una configuración. Puede usar el formato CSV que ya tiene, evitar la sobrecarga innecesaria de la base de datos, y si el cambio es necesario, será un cambio que el cliente debería poder hacer sin tener que recompilar / reinstalar y sin desordenar en la base de datos: solo pueden editar el archivo de configuración.
Por lo general, cuando se trata de elegir entre dos extremos (violar YAGNI frente a los datos dinámicos de codificación rígida), la mejor respuesta está en algún punto intermedio. Cuidado con las falsas dicotomías.
Esto supone que toda su configuración está en archivos; Si es un lugar difícil como el registro, probablemente deberías ignorar este consejo :)
fuente
Acabo de crear una tabla DB. (¿Pensabas en almacenar una mesa entera en una, te has vuelto loco?)
La tabla necesita 2 campos NO 3. Edad y tasa. ¡La siguiente fila contiene el valor superior! ¡Estás desnormalizando sin siquiera saberlo!
Aquí está el Sql para obtener la tarifa para alguien de edad que tiene 67 años.
No se moleste en hacer una pantalla de mantenimiento ya que está fuera del alcance. Si lo solicitan más tarde, emita una solicitud de cambio y hágalo.
EDITAR: Como otros han dicho, mantenga el código para obtener la tasa centralizada, en caso de que cambie toda la estructura de la Tarifa.
fuente
Estoy de acuerdo con la mayoría de las respuestas dadas. También agregaría que la consistencia con el resto de la aplicación es importante. Si este es el único lugar en el código que tiene valores codificados, probablemente sorprenderá a los encargados del mantenimiento. Esto es especialmente cierto si se trata de una base de código grande y estable. Si es un programa pequeño mantenido por usted, la decisión es menos importante.
Tengo un recuerdo lejano de leer a un conocido tipo ágil / OOP (como Dave Thomas o Kent Beck o alguien) que dice que su regla general para la duplicación de código fue dos y solo dos veces: no refactorice la primera vez que duplica algo desde es posible que solo lo escriba dos veces en su vida. Pero la tercera vez ...
Eso no responde exactamente a la pregunta, ya que estás cuestionando a YAGNI, pero creo que habla de la flexibilidad general de las reglas ágiles. El punto ágil es adaptarse a la situación y avanzar.
fuente
Código duro en una función.
fuente