¿Cómo sigue estrictamente la regla "Ciclo sin dependencia" (NDepend)

10

Un poco de antecedentes: como líder del equipo, uso NDepend aproximadamente una vez por semana para verificar la calidad de nuestro código. Especialmente la cobertura de prueba, las líneas de código y las métricas de complejidad ciclomática son invaluables para mí. Pero cuando se trata de ciclos de nivelación y dependencia, estoy un poco ... muy preocupado. Patrick Smacchia tiene una buena publicación de blog que describe el objetivo de la nivelación.

Para ser claros: en "ciclo de dependencia" entiendo una referencia circular entre dos espacios de nombres.

Actualmente estoy trabajando en un marco GUI basado en Windows CE para instrumentos integrados, solo piense en la plataforma gráfica de Android pero para instrumentos de muy bajo nivel. El marco es un conjunto único con aproximadamente 50,000 líneas de código (pruebas excluidas). El marco se divide en los siguientes espacios de nombres:

  • Navegación principal y subsistema de menú
  • Subsistema de pantalla (Presentadores / Vistas / ...)
  • Controles / capa de widgets

Hoy pasé medio día tratando de llevar el código a los niveles adecuados [gracias a Resharper, no hay problema en general], pero en todos los casos existen algunos ciclos de dependencia.

Entonces mi pregunta: ¿Cómo sigue estrictamente la regla del "Ciclo sin dependencia"? ¿Es realmente tan importante la nivelación?

olifante
fuente
2
Si "sin ciclo de dependencia" significa que no hay referencias circulares, entonces, no hay excusas. Esos son pura maldad.
Arnis Lapsa
@ollifant: define lo que quieres decir exactamente cuando escribes "Sin ciclo de dependencia". ¿Entre capas o entre clases dentro de una capa?
Doc Brown

Respuestas:

9

Recientemente escribí 2 libros blancos, publicados en Simple-Talk sobre el tema de la arquitectura de código .NET (el primer libro trata sobre ensamblados .NET, el segundo sobre espacios de nombres y nivelación):

Particionar su base de código a través de ensamblados .NET y proyectos de Visual Studio

Definición de componentes .NET con espacios de nombres

¿Es realmente tan importante la nivelación?

¡Sí lo es!

Cita del segundo libro blanco:

Si el gráfico de dependencias entre componentes contiene un ciclo, los componentes involucrados en el ciclo no se pueden desarrollar y probar de forma independiente. Debido a esto, el ciclo de componentes representa un supercomponente, con una entropía más alta que la suma de las entropías de sus componentes contenidos.

(...)

Mientras se respete continuamente la restricción de los componentes acíclicos, la base del código seguirá siendo muy fácil de aprender y mantener.

  • En la arquitectura tradicional de los edificios, la fuerza de la gravedad ejerce presión sobre los artefactos de bajo nivel. Esto los hace más estables: 'estables' en el sentido de que son difíciles de mover.
  • En la arquitectura de software, cumplir con la idea del componente acíclico ejerce presión sobre los componentes de bajo nivel. Esto los hace más estables, en el sentido de que es doloroso refactorizarlos. Las abstracciones empíricas están menos frecuentemente sujetas a refactorización que las implementaciones. Por esta razón, es una buena idea que los componentes de bajo nivel contengan principalmente abstracciones (interfaces y enumeraciones) para evitar una refactorización dolorosa.
Patrick Smacchia - NDepend dev
fuente
6

Nunca permito dependencias circulares entre clases o espacios de nombres. En C #, Java y C ++, siempre puede romper una dependencia de clase circular mediante la introducción de una interfaz.

La codificación test-first hace que sea difícil introducir dependencias circulares.

Kevin Cline
fuente
4

Siempre es un oficio: debe comprender el costo de las dependencias para comprender por qué deben evitarse las dependencias. Del mismo modo, si comprende el costo de una dependencia, puede decidir mejor si vale la pena en su caso específico.

Por ejemplo, en los videojuegos de consola, a menudo confiamos en dependencias donde se necesitan relaciones cercanas de información, principalmente por razones de rendimiento. Eso está bien siempre que no tengamos que ser tan flexibles como una herramienta de edición, por ejemplo.

Si comprende las restricciones en las que su software tiene que ejecutarse (ya sea hardware, sistema operativo o simplemente diseño (como "la interfaz de usuario más simple que podemos")), debería ser fácil seleccionar qué dependencias no deberían hacerse y cuáles son Okay.

Pero si no tiene una razón buena y clara, evite cualquier dependencia que pueda. El código dependiente es el infierno de la sesión de depuración.

Klaim
fuente
2

Cada vez que se discute este tema, los participantes generalmente pierden de vista la distinción entre ciclos de tiempo de construcción y tiempo de ejecución. El primero es lo que John Lakos abordó como "diseño físico", mientras que el segundo es básicamente irrelevante para la discusión (no se obsesione con los ciclos de tiempo de ejecución, como los creados por devoluciones de llamada).

Dicho esto, John Lakos fue muy estricto al eliminar todos los ciclos (tiempo de construcción). Sin embargo, Bob Martin adoptó la actitud de que solo los ciclos entre binarios (por ejemplo, archivos DLL, ejecutables) eran significativos y deberían evitarse; él creía que los ciclos entre clases dentro de un binario no son terriblemente importantes.

Personalmente sostengo el punto de vista de Bob Martin sobre esto. Sin embargo, sigo prestando atención a los ciclos entre clases porque la ausencia de tales ciclos hace que el código sea más fácil de leer y aprender para otros.

Sin embargo, debe señalarse que cualquier código que cree con Visual Studio no es capaz de tener dependencias circulares entre binarios (ya sea código nativo o administrado). Por lo tanto, el problema más grave con los ciclos se ha resuelto para usted. :)

Brent Arias
fuente
0

Casi totalmente, porque los ciclos de dependencia de tipo de compilación son inconvenientes en Haskell e imposibles en Agda y Coq, y esos son los lenguajes que uso habitualmente.

Robin Green
fuente