¿Cuándo escribir código abstracto y cuándo ser más específico?

9

Estoy trabajando en una herramienta pequeña como un proyecto de juguete para mostrar la diferencia entre dos directorios, mostrando qué archivos / directorios se agregaron, eliminaron, modificaron, etc.

Intenté representar estos cambios simplemente como objetos 'ChangeItem', sin distinción entre si era un archivo o directorio. Sin embargo, eso creó muchos problemas, por ejemplo, cómo mostrarlos en un árbol, cómo saber quién es el padre de un niño, etc. Y tampoco fue muy intuitivo.

Luego dividí los cambios entre cambios de directorio y cambios de archivo. Eso inmediatamente hizo que sea muy fácil codificar y comprender lo que estaba sucediendo. Ahora es mucho más simple seleccionar todos los archivos en un directorio, etc.

Mi pregunta es, ¿cómo se puede saber si usar la abstracción o ser más específico en su código? ¿Cómo puedes saber si tienes demasiada o muy poca abstracción?

Haga clic en Upvote
fuente

Respuestas:

9

¿Cómo sabe un pintor si es demasiado o muy poco de púrpura?

Mezcla los colores, intenta un trazo, hace algunos bocetos y ve qué sucede. Luego ajusta las proporciones hasta que todo el dibujo se ve bien e irradia armonía.

Hacemos lo mismo con el código. Obtenemos una idea de implementación por primera vez, reflexionamos sobre ella, analizamos sus lados fuertes y semanales y luego la probamos para ver si funciona. Luego ajustamos la idea en un proceso iterativo para ajustar las proporciones de abstracción, encapsulación, polimorfismo y lo que sea hasta que se vea bien y funcione según sea necesario.


fuente
21

Primero escribes código concreto.

Usted escribe código abstracto cuando debe hacerlo porque simplifica el código concreto.

Es más fácil comenzar con el concreto y encontrar las abstracciones después de estudiar lo que es similar y diferente sobre el concreto.

S.Lott
fuente
13
Recuerde siempre la regla de los tres: una abstracción sin al menos tres clientes no es una abstracción. Es una ilusión. Por lo general mal. Se extraen buenas abstracciones , no se diseñan.
Jörg W Mittag
3

Escribe código abstracto cuando escribe bibliotecas y debe generalizar la funcionalidad para que funcione en una amplia variedad de condiciones.

Pero escribir bibliotecas de esta manera es difícil. En una aplicación normal (por ejemplo, una aplicación de línea de negocio), este tipo de generalización se considera una forma de "optimización prematura", generalmente caracterizada como "No la va a necesitar" (YAGNI).

Hay un punto de inflexión en el que el código repetitivo exige que se diseñe una solución más generalizada. Pero, por lo general, este tipo de refactorización para eliminar la redundancia es mucho más simple que escribir una biblioteca generalizada.

Al final, la complejidad adicional requerida para implementar soluciones abstractas debe estar justificada por la flexibilidad que ofrecen.

Robert Harvey
fuente
3

La regla general que sigo, que es bastante común, es que no debes tratar de abstraer algo hasta que te encuentres escribiendo por tercera vez.

La primera vez que simplemente no entiendes el dominio del problema y terminarás sobre-diseñando todas las piezas equivocadas. La segunda vez, estará perfectamente posicionado para crear la solución ideal para su último problema. La tercera vez que finalmente esté en una buena posición para encontrar abstracciones apropiadas que lo ayudarán en las cosas que deben cambiar y no se interpondrá en su camino para hacer las cosas simples.

btilly
fuente
1
La tercera vez es una buena regla general. Me resulta raro generalizar mucho antes de la tercera vez que escribo algo.
quentin-starin
1
¿No depende también de qué tan grande sea el código similar? No copiarías ni pegarías dos páginas de código que solo fueran diferentes por dos líneas, solo porque no habías tocado el mágico "3 veces" todavía.
Scott Whitlock
@ scott-whitlock: Obviamente. Por eso es una regla de oro. Ignórelo según corresponda. Además, hay una diferencia entre las abstracciones orgánicas (p. Ej., "Necesitaba que la barra fuera casi exactamente perfecta, por lo que acabo de agregar un parámetro opcional a las características") y las abstracciones que forman parte de su diseño inicial.
btilly
1
@Scott Whitlock: "No copiarías ni pegarías dos páginas de código que solo fueran diferentes por dos líneas". Eso no es un llamado a la abstracción. Eso sigue siendo un buen diseño. La regla 3x debe mantenerse muy, muy estrictamente para evitar diseños abstractos prematuros.
S.Lott
"Según corresponda" es la frase clave aquí. Mis dos centavos, a menudo se aplica la "composición preferida a la herencia". A veces un problema que algunos resuelven con una abstracción sería mejor ya que if (cond) { //use one object} else {// use the other object }, especialmente. cuando es un conjunto de decisiones binarias.
Michael K
2

Al leer la pregunta, diría que puedes ser abstracto y específico. Es solo una cuestión de contexto, use la representación más abstracta posible en cada contexto.

Para su aplicación de juguete específica, ChangeItemes la representación más abstracta de los cambios. Entonces te vuelves más específico con DirectoryChangeItemy FileChangeItem, a través de la herencia. Puede usar un patrón compuesto para modelar el árbol. Cuando desee mostrarlo, puede usar las representaciones específicas y al recorrerlo puede usar la representación abstracta.

Y para dar una respuesta concreta a la pregunta: sea lo más específico posible hasta que sienta que necesita otra capa debajo de eso.

Victor Hurdugaci
fuente
1

Por lo general, la abstracción es útil para combatir cosas como la Complejidad, la Entropía, para hacer que su código sea Cibernético, e incluso en un nivel de legibilidad bajo. Primero codificaría, SOLO si la abstracción no es obvia por adelantado. La mayor parte de la abstracción ocurre cuando más de una implementación comparte el mismo patrón.

Piense en la abstracción como la congruencia o unidad de 2 o más Conjuntos. Tome un diagrama de Venn como modelo simplista: la parte donde se superponen los círculos, o en otras palabras, los conjuntos se fusionan.

Si tengo dos conjuntos: A: {a, b, c, d, e} y B: {d, e, f, g, h}. El punto donde comenzaría a buscar abstraer es la unidad de A + B; {d, e} es dónde abstraer. Del mismo modo, si los que están en la diferencia de A y B (AB o BA) son isomorfos entre sí, lo que significa su bajo costo para crear a, b o c a partir de f, g o h (y viceversa), entonces mantendría la abstracción En el fondo de mi mente.

Cody
fuente