Diseñe para cambios futuros o resuelva el problema en cuestión [cerrado]

37

Mientras escribe el código o durante el diseño, intenta generalizar el problema en primera instancia o intenta resolver ese problema muy específico.

Pregunto esto porque intentar generalizar el problema tiende a complicar las cosas (lo que puede no ser necesario) y, por otro lado, será muy difícil extender la solución específica si hay un cambio en el requisito.

Supongo que la solución es encontrar el camino intermedio que sea más fácil decirlo que hacerlo. ¿Cómo abordas este tipo de problema? Si comienza a generalizarlo, ¿en qué momento sabe que tanta generalización es suficiente?

Naveen
fuente
Esto plantea una pregunta muy importante: ¿realmente puede predecir cómo cambiarán los requisitos?
usuario16764
Mucha gente te dirá YAGNI. Esas son las personas que desprecia cuando tiene que hacerse cargo de su trabajo.
Martin Maat

Respuestas:

60

Con demasiada frecuencia, cuando intenta diseñar para el futuro, sus predicciones sobre las necesidades futuras resultan ser erróneas. Por lo general, es mejor refactorizar cuando realmente sabe cómo han cambiado las necesidades que sobre diseñar su sistema desde el primer día. Al mismo tiempo, tampoco te dispares en el pie. Ciertamente hay un término medio, y saber dónde está eso es más arte que ciencia.

Para reducirlo a una regla general: menos es más.


fuente
17
+1 "El futuro no es lo que solía ser".
Dan Lyons
19

¿Conoces Agile? Uno de los grandes principios de Agile es YAGNI . Creo que esa es la mejor manera de abordar las cosas.

"No lo vas a necesitar" ... es un principio de programación extrema (XP) que establece que un programador no debe agregar funcionalidad hasta que se considere necesario. Ron Jeffries escribe: "Siempre implemente las cosas cuando realmente las necesite, nunca cuando prevea que las necesita".

... YAGNI es un principio detrás de la práctica de XP de "hacer lo más simple que pueda funcionar" (DTSTTCPW). Está destinado a usarse en combinación con varias otras prácticas, como la refactorización continua, las pruebas unitarias automáticas continuas y la integración continua . Utilizado sin refactorización continua, podría conducir a un código desordenado y un trabajo masivo. La refactorización continua a su vez se basa en pruebas unitarias automatizadas como una red de seguridad (para detectar errores imprevistos) y una integración continua para evitar problemas de integración más amplios ...

YAGNI no se acepta universalmente como un principio válido, incluso en combinación con las prácticas de apoyo. La necesidad de combinarlo con las prácticas de soporte, en lugar de usarlo de forma independiente, es parte de la definición original de XP ...

Matt Grande
fuente
3
Si bien estoy más o menos de acuerdo con YAGNI, no puedo encontrarlo en los principios ágiles: agilemanifesto.org/principles.html
Jens Schauder el
"La simplicidad, el arte de maximizar la cantidad de trabajo no realizado, es esencial", se aplicaría a YAGNI y algunas otras prácticas ágiles.
tvanfosson
1
Si bien no dice específicamente "YAGNI" en el manifiesto, creo que están muy en línea entre sí.
2
@Jens y @Matt, YAGNI, están en Agile por medio de XP incluido como una metodología "ágil". Como se menciona en el artículo de Wikipedia, el principio YAGNI fue desarrollado por Ron Jeffries como parte de las prácticas básicas de XP.
1
Puede ser cierto que YAGNI es el idioma de los desarrolladores, pero TDD es el que aplica este dilema bastante bien. En el paso donde dice que solo debe escribir suficiente código para pasar la prueba y no más. Y TDD es parte de ágil.
Robert Koritnik
12

Esta es probablemente una de las partes más difíciles del desarrollo de software porque necesita caminar por la línea entre "YAGNI" y "PYIAC" (Paint Yourself Into A Corner).

Es bastante fácil decir "no escriba una función a menos que la necesite". La parte difícil es diseñar su código para que pueda agregar fácilmente características más adelante cuando las necesite.

La clave es poder diseñar una arquitectura extensible donde no escriba más código del que necesita actualmente. La capacidad de hacerlo bien realmente proviene de mucha experiencia (y dolor).

17 de 26
fuente
7

Paso un tiempo por adelantado pensando en la dirección general del diseño, no demasiado, pero lo suficiente como para esbozar básicamente una descripción general de alto nivel. Luego sigo una metodología ágil basada en historias usando TDD para desarrollar soluciones para historias individuales. Mientras estoy implementando a través de TDD, tengo en cuenta mi visión general de alto nivel y (a) dirijo mis implementaciones particulares para que sigan la descripción general de alto nivel o (b) refactorice (y mejore) mi comprensión / dirección de alto nivel basada en Lo que aprendo durante las pruebas / implementación.

Creo que es un error no planificar por adelantado, pero probablemente sea más grande hacer demasiado. En la medida de lo posible, me gusta dejar que la experiencia me guíe en el panorama general y luego dejar que el diseño crezca orgánicamente según las líneas que he establecido en mi mente sobre cómo se va a desarrollar la aplicación. Al usar TDD, encuentro que el diseño en sí mismo se ve forzado a mejores principios de diseño (desacoplado, responsabilidad única, etc.) y es más maleable con respecto a los cambios que si intento preconcebir el conjunto y adaptarlo al desarrollo.

tvanfosson
fuente
3

Un buen diseño se adapta a los cambios futuros y definitivamente vale la pena hacerlo. Considere el sistema operativo UNIX y su "todo es una filosofía de archivo". Esa decisión de diseño se tomó no para satisfacer alguna necesidad inmediata, sino con vistas a los requisitos futuros. Uno se estremece al pensar cómo sería un sistema operativo basado en un diseño "ágil".


fuente
2

Lo que está tratando de tratar tiene que ver con la reutilización (es decir, la generalización de un problema que está tratando ahora para que pueda reutilizar el trabajo (código) en el futuro). Lo dije antes y lo vincularé nuevamente.

Creo que he escuchado a otras personas decir algo en el sentido de:

Resuelvo el problema la primera vez. Cuando repito mi solución la primera vez, lo noto. Cuando lo repito nuevamente, refactorizo.

Jason Punyon
fuente
2

Diseño para "ahora + 1". Eso significa, resuelva el problema inmediato y cree suficiente funcionalidad para que la próxima vez que soliciten un cambio, ya lo haya hecho a la mitad (o más) y tenga la opción de a) resolverlo de inmediato y refactorizando más tarde, o b) resolviendo "ahora + 1" nuevamente (con la mitad "ahora" hecha)

Esto depende del proyecto y, en resumen, la experiencia le enseñará qué es el "+1".

Richard Levasseur
fuente
1

La filosofía de YAGNI , No lo vas a necesitar, se puede resumir con (del artículo):

Según quienes abogan por el enfoque YAGNI, la tentación de escribir código que no es necesario en este momento, pero podría serlo en el futuro, tiene las siguientes desventajas:

  • El tiempo empleado se toma agregando, probando o mejorando la funcionalidad necesaria.
  • Las nuevas funciones se deben depurar, documentar y admitir.
  • Cualquier característica nueva impone restricciones sobre lo que se puede hacer en el futuro, por lo que una característica innecesaria ahora puede impedir la implementación de una característica necesaria más adelante.
  • Hasta que la característica sea realmente necesaria, es difícil definir completamente lo que debe hacer y probarla. Si la nueva característica no se define y prueba correctamente, puede que no funcione correctamente, incluso si finalmente se necesita.
  • Conduce a la hinchazón de código; El software se hace más grande y más complicado.
  • A menos que haya especificaciones y algún tipo de control de revisión, la función puede no ser conocida por los programadores que podrían utilizarla.
  • Agregar la nueva función puede sugerir otras funciones nuevas. Si estas nuevas características también se implementan, esto puede dar como resultado un efecto de bola de nieve hacia un movimiento lento.
JeffH
fuente
0

Soy un gran creyente de diseñar para el problema en cuestión y no soplar su diseño al tratar de adivinar todos los casos que tiene que atender porque "algún día podríamos necesitarlo".

Básicamente, dada una lista de requisitos específicos, el diseño contra eso, sin embargo, esto no significa que no debas:

  • haga que los aspectos de su diseño sean configurables en lugar de codificarlos en su solución. Ya sea a través de parámetros pasados ​​en tiempo de ejecución o mediante una configuración externa leída al inicio (o después de HUP'ing).
  • ate su código con números mágicos,
  • evite echar un vistazo para ver si ya hay algo escrito que pueda reutilizar, tal vez después de adaptar la solución existente para proporcionar un enfoque adecuado para la situación existente, así como para los nuevos requisitos.

El principal problema con el diseño de "futuros posibles" es que siempre estás adivinando. Posiblemente haciendo conjeturas educadas, pero "cuando se trata de empujar" sigue siendo solo una serie de conjeturas.

Al hacer esto, también tiene la posibilidad muy real de exprimir su solución para que se ajuste a los casos generales en lugar de resolver el problema específico en cuestión según lo definido por sus requisitos conocidos.

¿Qué dice eso? "Cuando todo lo que tienes es un martillo, todo comienza a parecerse a un clavo".

Desearía tener una libra por cada vez que escuche a alguien decir: "Pero es una solución más adaptable para esos casos generales que podríamos ver en el futuro".

Rob Wells
fuente