Arquitectura PHP pura. ¿Cómo medirlo y controlarlo?

Prefacio


Como ya entendiste por el nombre, aquí voy a hablar sobre la arquitectura más "alta" - Pura. Y el ímpetu para el desarrollo de toda esta historia fue el libro de Robert Martin "Arquitectura pura". Si aún no lo he leído, ¡me atrevo a recomendarlo! El autor revela muchos temas importantes, comparte activamente su rica experiencia de vida (desde un campo profesional, por supuesto) y las conclusiones hechas sobre su base, ocasionalmente entreteje en los capítulos de la historia cuán magistralmente tontos (y no solo, por supuesto) nuestros padres y abuelos En los años 60, 70, 80 e incluso en los elegantes años 90, como los granos de grano, se recopilaron los principios favoritos de SOLID y sus análogos en el mundo de los componentes, y lo que aprendieron durante el último medio siglo. En el proceso de leer el libro, la línea de desarrollo de la industria de desarrollo de software está bien trazada, los problemas típicos que los niños tuvieron que enfrentar,y métodos para resolverlos.

No pienses, volver a contar el resumen del libro no es el propósito de esta publicación.
A continuación, hablaremos sobre ideas que me impulsaron a desarrollar una herramienta (determinaré el grado de su utilidad para usted y estaré esperando comentarios, sugerencias y críticas constructivas con gran interés).

Me parece que el artículo será útil para todos. Aquellos que ya estén familiarizados con el libro podrán actualizar algunos de sus momentos en su memoria, o simplemente omitir la primera parte e inmediatamente comenzar a familiarizarse con la herramienta. Quienes no hayan leído el libro antes, tal vez encuentren algo nuevo para ellos en la primera parte.

Por conveniencia, el artículo está dividido en 2 partes.

En el primero hablaré sobre las ideas clave que generaron en mi cabeza el deseo de automatizar todo esto, ¿somos programadores o quién al final? Aquí citaré mucho del autor, así como insertaré activamente extractos e ilustraciones de diferentes capítulos del libro.

La segunda parte, casi por completo, estará dedicada a describir la herramienta que ha aparecido, revelando sus capacidades y orientación paso a paso.

Si te consideras una categoría de personas que toman todo demasiado cerca de tu corazón, te aconsejo que comiences a leer el Afterword .



Parte 1


¿Qué es la arquitectura de software?


Por desgracia, el autor del libro no da una sola definición. Hay una gran cantidad de formulaciones diferentes, y todas son correctas a su manera.
Sin embargo, podemos ir desde el otro lado ...

¿Cuál es el propósito de la arquitectura?


Solo hay una respuesta:

el objetivo de la arquitectura de software es reducir el trabajo humano requerido para crear y mantener un sistema.

Un poco introductorio ...

¿Dónde comienzan muchos proyectos?


"Podremos restaurar el orden más tarde, ¡solo ingresaríamos al mercado!"
Como resultado, el orden no se ha restablecido, porque la presión de la competencia en el mercado nunca disminuye.

“La mayor mentira que muchos desarrolladores creen es que el código sucio los ayudará a ingresar rápidamente al mercado, pero en realidad disminuirá su movimiento a largo plazo. Los desarrolladores que creen en esta mentira muestran la arrogancia de Hare, creyendo que en el futuro podrán pasar de crear desorden a restaurar el orden, pero cometen un simple error. El hecho es que la creación de desorden es siempre más lenta que la constante observancia de la limpieza, independientemente de la escala de tiempo elegida ".

Dos valores de productos de software.


  1. Comportamiento (algo urgente pero no siempre importante)
  2. Arquitectura (algo importante, pero no siempre urgente)

Muchos a menudo se ahogan en el primero y descuidan completamente el segundo.

Tipo: "¿Por qué perder el tiempo pensando detenidamente en la arquitectura, lo principal es que funciona correctamente!" .

Pero pierden un punto importante: “Si un programa que funciona correctamente no permite la posibilidad de cambiarlo, dejará de funcionar correctamente cuando los requisitos cambien y no podrán hacerlo funcionar correctamente. Es decir, el programa se volverá inútil.

Si el programa no funciona correctamente, pero se puede modificar fácilmente, podrán hacerlo funcionar correctamente y mantener su rendimiento a medida que cambien los requisitos. Es decir, el programa siempre seguirá siendo útil ".

Me gustó esta declaración:"Si crees que una buena arquitectura es cara, prueba con una arquitectura pobre". (Brian Foote y Joseph Yoder)

Resulta que es importante prestar la debida atención a la limpieza del código y la arquitectura en general desde las primeras líneas. Pero, si todo está relativamente claro con la pureza del código (olfatea todo tipo de malos olores en el código y corrígelo, además de que las herramientas están llenas de IDEs inteligentes, analizadores estáticos y otra basura indudablemente importante), entonces con la arquitectura no es tan del todo (al menos menos yo)

¿Cómo puedes controlar algo tan vago que es difícil incluso definirlo con una sola frase que tenga una idea muy versátil y, cada segundo, maldita sea, la mierda lo ve e intenta interpretarlo a su manera, si no eres el nieto de Vanga, no ganaste el espectáculo "Intuición ¿Y no son particularmente sensibles el quinto punto? Luego, el autor del libro arroja un par de ideas valiosas para pensar ... Vamos a resolverlo.

¿Por qué se te ocurrió SOLID y por qué no es suficiente solo?


Probablemente todos conozcamos los principios de SOLID.

Su objetivo es crear estructuras de software de nivel medio que:

  • tolerante al cambio;
  • simple y comprensible;
  • forman la base de los componentes que se pueden usar en muchos sistemas de software.

Pero: "Al igual que los buenos ladrillos pueden hacer una pared inutilizable, los componentes bien diseñados del nivel promedio pueden crear un sistema inutilizable".
Por lo tanto, en el mundo de los componentes, existen análogos de principios SÓLIDOS, así como principios de alto nivel para crear arquitecturas.

Tocaré estos temas muy superficialmente, se pueden encontrar más detalles en el libro. ¡Vamonos!

Conectividad de componentes y sus principios determinantes.


“¿A qué componente pertenece esta o aquella clase? Esta importante decisión debe tomarse de acuerdo con los principios de desarrollo de software establecidos. Desafortunadamente, tales decisiones son de naturaleza especial y se toman casi exclusivamente sobre la base del contexto ".

REP: Principio de equivalencia de reutilización / liberación: el principio de equivalencia de reutilización y liberación.

En términos de arquitectura y diseño, este principio significa que las clases y módulos que componen un componente deben pertenecer a un grupo conectado. Un componente no puede incluir simplemente una mezcla aleatoria de clases y módulos; Debe haber algún tema u objetivo común a todos los módulos.

Las clases y los módulos combinados en un componente deben liberarse juntos.

PCC: Principio de cierre común: el principio de cambio constante.
Este es el principio de SRP (responsabilidad única) reformulado para componentes.

Las clases que cambian por las mismas razones y al mismo tiempo deben incluirse en un componente. Los diferentes componentes deben incluir clases que cambian en diferentes momentos y por varias razones.

CRP: Principio de reutilización común : el principio de reutilización compartida.
Este principio es similar al ISP (segregación de interfaz).

No obligue a los usuarios de componentes a depender de lo que no necesitan.

El principio indica que las clases que no están estrechamente relacionadas no deben incluirse en un componente.

“Quizás ya haya notado que los tres principios de los componentes conectados entran en conflicto entre sí. Los principios de equivalencia de reutilización (REP) y cambio constante (CCP) son inclusivos: ambos se esfuerzan por hacer que los componentes sean lo más grandes posible. El Principio de reutilización (CRP) es excepcional y se esfuerza por hacer que los componentes sean lo más pequeños posible. La tarea de un buen arquitecto es resolver esta contradicción ".

imagen

“En el pasado, analizamos la conectividad más fácilmente que lo que sugieren los principios de equivalencia de reutilización (REP), cambio constante (CCP) y reutilización compartida (CRP). Una vez que pensamos que la conectividad es solo un atributo, que un módulo realiza una y solo una función. Sin embargo, los tres principios de conectividad de componentes describen una variedad mucho más compleja. Al elegir clases para su inclusión en componentes, debe considerar las fuerzas opuestas asociadas con la facilidad de reutilización y desarrollo. Encontrar un equilibrio de estas fuerzas basado en las necesidades de la aplicación no es una tarea fácil. Además, el equilibrio casi siempre cambia constantemente. Es decir, la partición considerada exitosa hoy puede no tener éxito después de un año. Por consiguiente,es casi seguro que la composición de los componentes cambiará con el tiempo y el enfoque del proyecto pasará de la facilidad de desarrollo a la facilidad de reutilización ".

Compatibilidad de componentes


“Los siguientes tres principios definen las reglas para la relación entre componentes. Y nuevamente, nos enfrentamos a contradicciones entre la facilidad de desarrollo y la organización lógica. Las fuerzas que afectan la arquitectura de la estructura del componente son técnicas, políticas y volátiles ”.

ADP: Principio de dependencias acíclicas: el principio de aciclicidad de dependencias.
¡Los bucles en el gráfico de dependencia de componentes no están permitidos!

imagen

Desde cualquier componente que se muestre en el gráfico, comienza a moverse a lo largo de las flechas que indican la dirección de la dependencia, no podrá volver al punto original. Este es un gráfico orientado acíclico (DAG - Gráfico Acíclico Dirigido).

imagen

En esta imagen, tenemos una dependencia que conduce a la aparición de un ciclo. La dependencia cíclica resultante siempre se puede romper.

Métodos para romper dependencias cíclicas


1. Aplicando DIP (principio de inversión de dependencia)

imagen

2. Introducción del nuevo componente

imagen

“La segunda solución implica la dependencia de la estructura de los componentes de los requisitos cambiantes. De hecho, a medida que la aplicación crece, la estructura de las dependencias de los componentes crece y cambia. Por lo tanto, debe verificarse constantemente los ciclos. Cuando se forman ciclos, deben romperse de una forma u otra. A veces para esto es necesario crear nuevos componentes, lo que hace crecer la estructura de las dependencias ".

Diseño de arriba hacia abajo, o más bien su impracticabilidad


“La estructura de los componentes no se puede diseñar de arriba a abajo. Esta conclusión no se alcanza de inmediato tan pronto como comienzan a diseñar el sistema, pero esto sucede inevitablemente con el crecimiento y el cambio del sistema.

Considerando un gran diagrama de bloques, como la estructura de las dependencias de los componentes, creemos que los componentes deben representar de alguna manera las funciones del sistema. Pero en realidad, este no es un atributo indispensable de los diagramas de dependencia de componentes.

De hecho, los diagramas de dependencia de los componentes reflejan débilmente las funciones de la aplicación. En mayor medida, son un reflejo de la conveniencia del montaje y mantenimiento de la aplicación. Esta es la razón principal por la que no están diseñados al comienzo del desarrollo del proyecto. Durante este período, no hay ningún software que deba recopilarse y mantenerse, por lo que no es necesario elaborar un mapa de compilación y mantenimiento. Pero con la llegada de un número cada vez mayor de módulos en las primeras etapas de implementación y diseño, aumenta la necesidad de gestionar las dependencias ... Además, existe el deseo de limitar el impacto de los cambios tanto como sea posible, por lo que comenzamos a prestar atención a los principios de responsabilidad única (SRP) y cambio coordinado (CCP) y combinar clases, que probablemente cambiarán juntos.

Una de las tareas principales de dicha estructura de dependencia es el aislamiento de la variabilidad. No necesitamos componentes que a menudo cambian por las razones más pequeñas y afectan a otros componentes que de otro modo serían completamente estables. Por ejemplo, los cambios cosméticos en la GUI no deberían afectar las reglas de negocio. Agregar y modificar informes no debería afectar las políticas de alto nivel. En consecuencia, los arquitectos crean y crean un gráfico de dependencia de componentes para proteger componentes estables y valiosos de la influencia de componentes volátiles.

A medida que se desarrolla la aplicación, comenzamos a preocuparnos por crear elementos reutilizables. En esta etapa, el principio de reutilización compartida (CRP) comienza a influir en la composición de los componentes. Finalmente, con la llegada de los bucles, comenzamos a aplicar el principio de aciclicidad de dependencia (ADP), como resultado, el gráfico de dependencia de los componentes comienza a cambiar y crecer.

Es probable que falle un intento de diseñar la estructura de dependencia de los componentes antes que cualquier clase. En esta etapa, no sabemos casi nada sobre la reconciliación de los cambios, no imaginamos qué elementos se pueden usar repetidamente, y casi con seguridad crearemos componentes que formen dependencias cíclicas. Por lo tanto, la estructura de las dependencias de los componentes debería crecer y desarrollarse junto con el diseño lógico del sistema "

Oye, ¿sigues aquí? Hombre, esto es importante, debes saludar a esto al menos para ingresar el significado de la siguiente parte, habrá un tutorial en bruto sobre el uso de tulza.

SDP: Principio de dependencias estables: el principio de dependencias estables.
¡Las dependencias deben dirigirse hacia la estabilidad!

"¿Qué se entiende por" sostenibilidad "? Imagina una moneda parada en un borde. ¿Es estable su posición? Lo más probable es que responda "no". Sin embargo, si lo protege de la vibración y el viento, puede permanecer en esta posición durante un tiempo arbitrariamente largo. Es decir, la sostenibilidad no está directamente relacionada con la frecuencia de los cambios. La moneda no cambia, pero casi nadie dirá que, de pie en el borde, está en una posición estable.

El diccionario explicativo dice que la sostenibilidad es "la capacidad de mantener la condición de uno bajo influencias externas". La sostenibilidad está relacionada con la cantidad de trabajo que debe hacerse para cambiar de estado. Por un lado, una moneda que se encuentra en un borde está en un estado inestable porque requiere un pequeño esfuerzo para derribarla. Por otro lado, la mesa está en una condición muy estable, ya que requiere un esfuerzo mucho más sustancial para inclinarla.

¿Qué tiene que ver todo esto con el software? Hay muchos factores que complican el cambio de un componente, como su tamaño, complejidad y claridad. Pero dejaremos de lado todos estos factores y nos centraremos en otra cosa. Hay una manera segura de hacer que un componente de software sea difícil de cambiar mediante la creación de muchos otros componentes que dependen de él. Un componente con muchas dependencias entrantes es muy estable, porque la reconciliación de los cambios con todos los componentes dependientes requiere un esfuerzo considerable ".

imagen

imagen

¿Cómo evaluar la estabilidad del componente? El autor sugiere calcular el número de dependencias entrantes y salientes y, sobre la base de esto, calcular la medida de su estabilidad.

  • Fan-in ( ): . , .
  • Fan-out ( ): . , .
  • I: : I = Fan-out ÷ (Fan-in + Fan-out). [0, 1]. I = 0 , I = 1 – .

Entonces, este principio dice que la métrica del componente I debería ser más que la métrica de los componentes I que dependen de él. Es decir, las métricas que debo disminuir en la dirección de la dependencia.

Es importante tener en cuenta que si todos los componentes del sistema son lo más estables posible, dicho sistema no será posible cambiar. Por lo tanto, no todos los componentes deben ser estables.

Hombre, no te duermas, estoy cerca. ¡Solo queda un poco!

SAP: Principio de abstracciones estables: el principio de estabilidad de las abstracciones. La estabilidad de un componente es proporcional a su abstracción.

“Algunas partes de los sistemas de software deberían cambiar muy raramente. Estas piezas representan decisiones arquitectónicas de alto nivel y otras decisiones importantes. Nadie quiere que esas decisiones sean volátiles. Por lo tanto, el software que encapsula las reglas de alto nivel debe residir en componentes estables (I = 0). Volátil (I = 1) debe contener solo código mutable, un código que se puede cambiar fácil y rápidamente.

Pero si coloca reglas de alto nivel en componentes estables, esto complicará el cambio en el código fuente que los implementa. Esto puede hacer que toda la arquitectura sea inflexible. ¿Cómo hacer que un componente con la máxima estabilidad (I = 0) sea tan flexible que permanezca estable durante los cambios? La respuesta se encuentra en el principio de apertura / cierre (OCP). Este principio dice que es posible y necesario crear clases que sean lo suficientemente flexibles para que puedan heredarse (extenderse) sin cambios. ¿Qué clases cumplen con este principio? Resumen.

SAP (el principio de la estabilidad de las abstracciones) establece una conexión entre estabilidad y abstracción. Por un lado, dice que un componente estable también debe ser abstracto para que su estabilidad no impida la expansión, y por otro lado, dice que un componente inestable debe ser concreto, porque la inestabilidad hace que sea fácil cambiar su código.

Es decir, un componente estable debe consistir en interfaces y clases abstractas para que pueda ampliarse fácilmente. Los componentes resistentes disponibles para la expansión son lo suficientemente flexibles como para no restringir demasiado la arquitectura.

Los principios de estabilidad de abstracciones (SAP) y dependencias estables (SDP) juntos corresponden al principio de inversión de dependencia (DIP) para componentes. Esto es cierto porque el principio SDP requiere que las dependencias se dirijan hacia la sostenibilidad, y el principio SAP establece que la sostenibilidad implica abstracción. Es decir, las dependencias deben dirigirse hacia la abstracción.

Sin embargo, el principio DIP está formulado para las clases, y en el caso de las clases no hay medios tonos. La clase es abstracta o no. Los principios de SDP y SAP se aplican a los componentes y permiten una situación en la que un componente es parcialmente abstracto o parcialmente estable ".

¿Cómo medir la abstracción de un componente? Aquí, también, todo es muy simple.
El valor de la medida del componente abstracto está determinado por la relación del número de sus interfaces y clases abstractas con el número total de clases.

  • Nc: el número de clases en el componente.
  • Na: el número de clases abstractas e interfaces en el componente.
  • A: resumen. A = Na ÷ Nc .

El valor de la métrica A varía en el rango de 0 a 1. 0 significa la ausencia total de elementos abstractos en el componente, y 1 significa que el componente no contiene más que clases e interfaces abstractas.

Dependencia entre I y A

Si traza en el gráfico (Y - abstracción, X - inestabilidad) componentes "buenos" de ambos tipos: abstracto estable e inestable concreto, obtenemos esto:

imagen

Pero, porque los componentes tienen diferentes grados de abstracción y estabilidad, lejos de caer en estos 2 puntos (0, 1) o (1, 0), y dado que es imposible exigir que todos los componentes estén en ellos, debemos suponer que en el gráfico A / I hay algunos puntos que determinan las posiciones óptimas para los componentes.

Este conjunto puede derivarse definiendo áreas donde los componentes no deberían ubicarse, en otras palabras, definiendo zonas de exclusión.

imagen

Zona de dolor

Considere los componentes ubicados cerca del punto (0, 0).

Son muy estables y específicos. Tales componentes son indeseables ya que son demasiado duros No se pueden expandir porque no son abstractos y es muy difícil cambiarlos debido a su gran estabilidad. Cuanto más cambiamos el componente que ingresa a la zona de dolor, más dolor trae. Esto se debe a la complejidad de su cambio.

Los componentes diseñados correctamente generalmente no deben estar cerca del punto (0, 0).
Sin embargo, en realidad, hay entidades de software que entran en esta zona. Por ejemplo, el esquema de la base de datos es lo más específico posible y muchas dependencias se extienden hacia él. Esta es una de las razones por las cuales los cambios en el esquema de la base de datos generalmente están asociados con un gran dolor.

Zona inútil

Considere los componentes ubicados cerca del punto (1, 1).

Tales componentes también son indeseables, porque son lo más abstractos posible y no tienen dependencias. Son simplemente inútiles. A menudo, estas son clases abstractas que nunca se han implementado.

¿Cómo evitar entrar en zonas de exclusión?

Coloque los componentes cerca o sobre la secuencia principal. Dichos componentes no son "demasiado abstractos" para su estabilidad y no "demasiado inestables" para su abstracción. No son inútiles y no causan mucho dolor. Otros componentes dependen de ellos en la medida de su abstracción, y ellos mismos dependen de otros en la medida de su especificidad.
Las posiciones más deseables para los componentes son los puntos finales de la secuencia principal. Sin embargo, en sistemas grandes siempre habrá varios componentes que no son lo suficientemente abstractos y no lo suficientemente estables. Dichos componentes tienen excelentes características cuando se encuentran en o cerca de la secuencia principal.

La distancia a la secuencia principal

Dado que es deseable que el componente esté ubicado en o cerca de la secuencia principal, es posible determinar una métrica que exprese la distancia del componente desde el ideal.

  • D: distancia. D = | A + I - 1 | . Esta métrica toma valores del rango [0, 1]. Un valor de 0 indica que el componente está directamente en la secuencia principal. Un valor de 1 indica que el componente está ubicado a la distancia máxima de la secuencia principal.

Al adoptar esta métrica, puede explorar todo el diseño cerca de la secuencia principal. La métrica D se puede calcular para cualquier componente. Cualquier componente con un valor métrico D lejos de cero requiere revisión y reestructuración.

imagen

Conclusión del autor (Robert Martin)


“Las métricas de administración de dependencias descritas en este capítulo lo ayudan a cuantificar la consistencia de la estructura de dependencia y la abstracción del diseño con lo que yo llamo un diseño“ bueno ”. La experiencia muestra que hay buenas dependencias, hay malas. Esta evaluación refleja esta experiencia. Sin embargo, las métricas no son la verdad definitiva; Estas son solo mediciones basadas en un estándar arbitrario. Estas métricas son imperfectas, en el mejor de los casos, pero espero que les sean útiles ".

Hombre, me alegro si todavía estás conmigo. Eso es todo con la primera parte. Aunque todavía hay muchos temas, y los pensamientos detallados del autor no se vieron afectados. Aún así, el propósito principal de mi artículo no es volver a contar el libro, de lo contrario, definitivamente estaría más contento de leer el original. Yo, caminé, y así, específicamente, fui demasiado lejos con la cantidad de contenido, pero seré bastardo, traté de no inflarme como pude. ¡Redondo!

Segundo día. Umm, es decir Parte 2


Introducción


¿Qué he estado frotando por tanto tiempo allí? "Ah, sí ... Somos como arquitectos, o realmente queremos ser ellos, ¿verdad?"

¿Que tenemos? - Algún tipo de proyección miserable, o tal vez un sistema monstruoso, PROYECTO, su madre, bueno, o finalmente todavía no hay nada, pero simplemente nos frotamos las manos, miramos el calendario y descubrimos qué tan bien tendremos que hablar.

No somos nosotros, yo trabajo solo! O tal vez nosotros, con un compañero, en el garaje, íbamos a llenar una nueva Apple, ¿por qué no? Bueno, o somos el ejército y todos somos parte de una compañía fuerte, estamos trabajando duro, como los negros de los pobres en casa (es decir, los afroamericanos, por supuesto, entiendes), o tal vez estamos pateando en silencio para que no nos despidan. Por un sueldo gordo con un bono, galletas y una vista desde la ciudad de Moscú o por puro entusiasmo, por una idea y una participación en una startup que naturalmente es un infierno cuando despega.

De hecho, no importa. Lo importante es esto: todos nosotros, al final, simplemente queremos que nuestra creación no se doble prematuramente, bueno, al menos antes de nuestra partida, y hay muchas posibilidades para eso. Sí, sí ...

¿Y qué hacer ahora, preguntas? Entonces, si no tienes un hermano mayor en la oficina, entonces hermano no puede prescindir de un tercer ojo.

Resumen de la primera parte


En la última parte del artículo, hablamos un poco sobre las métricas que permiten a los arquitectos medir sus números en cifras para reflejar el grado de calidad de la arquitectura de su sistema.

A - abstracción del componente
I - inestabilidad del componente
D - distancia a la secuencia principal en el gráfico A / I Se

revelaron zonas erógenas de las zonas de dolor y futilidad .

Llegamos a la conclusión de que, idealmente, A debería aumentar y disminuir en proporción a una disminución y, en consecuencia, un aumento en I. Los componentes bien diseñados deben estar en o al menos cerca de la secuencia principal, es decir D debe estar lo más cerca posible de cero, y las dependencias entre los componentes deben ser acíclicas y dirigidas hacia la estabilidad.

También espero que todos entiendan que algunos componentes pueden saber acerca de muchos otros, mientras que otros no deberían saber nada. Al igual que en los estados esclavos antes de la llegada del buen tío Abraham, por el contrario, a los negros (en el sentido de los afroamericanos) no se les permitía el nicromo (en términos de conocimiento, y no solo), en nuestro caso los componentes más importantes del sistema deberían tener un mínimo de conocimiento, ellos debe ser autosuficiente y abstracto a partir de diferentes detalles.

¿Y qué hay del tercer ojo? Arquitectura limpia PHP- una herramienta que apareció como resultado de la lectura de un libro, gracias al tío Bob (Robert Martin) por sus valiosos pensamientos y su loco deseo de visualizar todo, para la conveniencia del análisis y la automatización, por la posibilidad de incluir varios controles en CI / CD (similar a PHPStan, Phan y otros, solo para identificar con precisión problemas arquitectónicos).

Herramienta y proyecto de prueba. Introducción al tema.


Fuf, todo parece ser una teoría ... Ahora incluso puedes ensuciarte las manos para obtener más detalles.
Y así, para mí ahora no tienen acerca de los caballos abstractos en un vacío para frotar, y usted tiene el final de la lectura fue menor razón para llamar mudiloy, debido a que la follan pasado tanto tiempo, había prosrat pasar un poco de él, y preparar una demo proyecto, que, sobstna, ahora vamos a hacer hara-kiri. Para los tipos "superdotados" que sin duda serán y quieren pasar el rato en los comentarios, con respecto a sus detalles, enfatizo: este es un proyecto DEMO .
Lo corté en aproximadamente medio día, más o menos, sobre la rodilla de mi novia. Después de todo, no puedo llevar y drenar al público en general los detalles de los proyectos de combate con los que tengo que trabajar ... Los muchachos en el naufragio no entenderán, me lo mostrarán, pero ¿lo necesito? Bueno, si eres un chico simple, no uno de los "particularmente sobresalientes", entonces soy un pésimo para una presentación tan larga, solo tuve que tomar los riesgos y reducir la amenaza potencial de reproducción en los comentarios de los bazares sobre nada.

Entonces, el proyecto en sí se encuentra aquí github.com/Chetkov/php-clean-architecture-example-project .

En el futuro, podría convertirse en una tienda en línea completa. Ciertamente soy un perfeccionista feroz, pero debes ser un completo sinsentidodevorador de sol y de hígado largo, además de sufrir insomnio, para pasar tanto tiempo en el "conejo experimental" y hacer dulces con él. Como comprenderá, este proyecto nunca llegará a su conclusión lógica , sin embargo, como todos los demás, incluso los proyectos de combate.

Aunque no es tan malo. Por el momento tiene: usuario, producto y pedido , así como escenarios: registro de usuario, cambio de contraseña, agregar un producto y reservar un pedido .

El proyecto está más o menos funcionando, puede clonarlo usted mismo y ejecutar scripts desde la carpeta sandbox, aunque, de hecho, ni siquiera podría hacer esto, porque Para el análisis de la operabilidad de la arquitectura del proyecto no se requiere.

En el futuro, lanzaré enlaces a confirmaciones específicas para corregir de inmediato los puntos técnicos descritos en el artículo.

Estado inicial

Supongo que ya te has familiarizado con la estructura. Entonces podemos seguir adelante.

Incluimos PHP Clean Architecture :
composer require v.chetkov/php-clean-architecture:0.0.3


Creamos y configuramos el archivo de configuración

Visualización para el análisis


Ejecutamos en la consola (en la raíz del proyecto):

vendor/bin/phpca-build-reports
o
vendor/bin/phpca-build-reports /path/to/phpca-config.php

Y en respuesta obtenemos:

Report: /path/to/reports-dir/index.html

El informe consta de 3 pantallas:

1. Información general del sistema

imagen

Esta pantalla muestra:

El mismo gráfico A / I que muestra la dispersión de los componentes:

imagen

Gráfico que muestra la lejanía de los componentes de la secuencia principal:

imagen

Y un gráfico que muestra las relaciones entre los componentes: las

imagen

flechas indican la dirección de las dependencias, y los números en ellas indican la fuerza de la conexión.

Porque Los IDE modernos proporcionan una manera fácil de refactorizar (ellos mismos encuentran y arreglan todas las áreas donde se llama explícitamente al método o clase, por ejemplo, al renombrar o transferir a otro espacio de nombres), tomé el número de elementos del módulo de dependencia utilizado por el módulo dependiente para la fuerza de la comunicación.

Por ejemplo: los elementos del módulo de servicios conocen aproximadamente 12 elementos del módulo modelo , y los elementos de infraestructura conocen aproximadamente 1 elemento de servicios . Etc.

Por cierto, lo que es * indefinido *? Hermano, la pregunta esperada. Este es un módulo creado automáticamente para todos los elementos que, durante el análisis del sistema, no pudieron atribuirse a ninguno de los conocidos (es decir, los que figuran en el archivo de configuración).

Sin embargo, si corrige la configuración de esta manera:

imagen

Luego, en el proceso de análisis del sistema, los paquetes conectados a través del compositor también se tendrán en cuenta (ellos mismos no se escanearán, pero la imagen se volverá mucho más completa).

Por cierto, en vendor_path debe especificar la ruta al directorio de proveedores y en las rutas excluidas a los directorios de paquetes que queremos excluir (por ejemplo, si describimos un paquete en la configuración principal de módulos para escaneo).

Después de habilitar vendor_based_modules el gráfico ha cambiado, aunque no cambiamos la configuración de los módulos en sí

imagen

2. Información detallada sobre el componente

imagen

Aquí también vemos:

  • Gráfico de interconexiones , pero no del sistema completo, sino solo de los componentes involucrados
  • Gráfico A / I que muestra solo el componente actual
  • Características clave del módulo

    imagen

y
  • Gráfico de dependencia saliente que muestra el número y la lista de archivos en el módulo actual, dependiendo de los archivos de otros módulos.
  • imagen

  • Y un gráfico de dependencias entrantes , que muestra el número y la lista de archivos en otros módulos, dependiendo del módulo actual.

    imagen

Los últimos 2 gráficos, en mi opinión, son especialmente interesantes, porque es fácil encontrar dependencias no deseadas en ellos, pero más sobre eso más adelante.

3. Información detallada sobre el elemento componente

imagen

Aquí puede ver:

  • Características principales del elemento, como abstracción de tipo, inestabilidad, primitivo y a qué componente pertenece y el modificador de acceso .

"Che, ¿un modificador de acceso de clase en PHP?" - dices, perforando un agujero en el área de la sien con tu dedo, ¿verdad? Tómese su tiempo, sé que no hay clases privadas en el calor, pero sería genial si lo fueran? En general, sobre esto también un poco más tarde.

  • Gráfico de dependencia , que refleja la interacción del elemento considerado con otros elementos del sistema.

  • Y tabletas con dependencias salientes y entrantes

    imagen

Con la descripción de las pantallas terminada, vaya a las configuraciones para elegir y configurar cómo se puede configurar.

Opciones de configuración


Limitación de la distancia máxima permitida a la secuencia principal (para todos los componentes)

Primero, intentemos configurar todos los componentes a la distancia máxima permitida a la secuencia principal. Sería una tontería pensar que todos estarán en la diagonal principal, porque el mundo no es perfecto, así que seamos realistas. Hago 0.3

imagen

Reinicio del comando de generación de informes e inmediatamente veo la violación en la página principal. El componente del modelo excede la distancia permitida en 0.192

imagen

Limitar la distancia máxima permitida a la secuencia principal (a un componente específico)

Es genial, pero supongamos que es el componente del modelo el que puede violar esta restricción. Suceden cosas diferentes ... Después de todo, a menudo ya no tenemos sistemas ideales con los que tenemos que trabajar, apoyarlos y mejorar. Cualquiera entiende que nadie podrá reducir rápidamente esta distancia, incluso probablemente con un dios (espero que me perdone).

En mi opinión, lo principal es arreglar el estado actual, trabajar para mejorar y controlar la situación para no agravar.

Nuevamente, vaya a la configuración y configure max_allowable_distance , solo para un módulo específico. Me fijo en su valor actual 0.492

imagen

ZBS, ahora todo vuelve a la normalidad.

imagen

Pero si, con un poco de ** ka Vasya, fuma algo de nuevo y empeora, ¡ córtale las manos! Un CI / CD que incluye ejecutar el comando phpca-check (hablaremos de eso más adelante) lo regaña, tal vez incluso un lenguaje grosero , y por supuesto resaltará los errores.

Control de dependencia de componentes

¿Qué más sería bueno tener en nuestro arsenal para lidiar con una arquitectura pobre? Por supuesto, control de dependencia. Quién puede saber sobre quién, o viceversa, no debería saberlo.

¿Qué crees que puede la parte central del sistema, digamos dominio , para que DDDowski pueda saber algo sobre una infraestructura maloliente ?
Por supuesto que SÍ, para algunos es, directamente, un atributo de éxito (bueno, estoy hablando de aquellos que procesan HTML mezclado con lógica empresarial). Pero finalmente, como debería ser, no debería ... Ciertamente, soy x, pero todo tipo de tipos inteligentes diferentes en los libros dicen que esto no es patsansky.

Entonces agitemos así ... Todo está en el mismo lugar, en la configuración de restricciones para el modelo .

imagen

Hmm ... Hasta ahora, todas las reglas, porqueel modelo sobre infraestructura realmente no sabe nada ...

Bueno, vamos a divertirnos ... La estupidez es ciertamente rara, pero no se me ocurrió nada mejor. Krch, al momento de crear el usuario, "enviaremos" SMS, y al momento de crear el pedido "enviaremos" correos electrónicos. Y para hacer esto a través de implementaciones específicas de notificadores que se encuentran en la infraestructura .

github.com/Chetkov/php-clean-architecture-example-project/commit/6bad365176b30999035967319a9c07fae69fabf9

Ahora miramos el informe ... Como podemos ver, los gráficos en diferentes páginas del informe resaltan esta conexión como ilegítima.

Casa.

imagen

Informe de componentes.

imagen

En los gráficos del modelo de "dependencias salientes" y "dependencias entrantes"infraestructura , inmediatamente vemos elementos que violan la regla introducida

imagen

en las tablas de "dependencias salientes" de elementos del modelo y "dependencias entrantes" de elementos de infraestructura , de manera similar.

PHPCAEP \ Modelo \ Usuario \ Usuario

imagen

PHPCAEP \ Infraestructura \ Notificación \ Sms \ SmsNotifier

imagen

Así como en el gráfico de relaciones de elementos. Pienso en el futuro deshacerme de él por completo, porque no es muy informativo (especialmente para clases usadas activamente, debido a la longitud del nombre de los nodos + su gran número)

imagen

Se pueden hacer acciones similares con la configuración allow_dependencies .

imagen

El resultado será completamente opuesto.

Es posible componer una configuración indicando para el módulo y prohibidoy permitido (si hay un deseo, lo discutiremos con más detalle en los comentarios). Todavía no es posible especificar un componente tanto en prohibido como en permitido ... Se pensó en introducir una configuración para indicar prioridad, pero hasta ahora no he hecho esto y no estoy seguro de lo que haré. Todo depende de tus comentarios. Tal vez todo esto se desperdicia?

Clase pública / privada en PHP

Bien, aprendimos cómo limitar y controlar el rango de conocimiento de los componentes. Ya no está mal. ¿Que sigue?

Y luego otro problema. El enemigo no duerme, aunque en la mayoría de los casos este enemigo, nosotros mismos somos, o nuestros compañeros en la oficina.

Después de todo, sucede que conociste a una chica, hablaste, descubriste algo sobre ella, tal vez incluso cortejada, pero maldita sea, no funciona para ti. Somos amigos y todo eso ... Ella puede besarte cuando te conoce, puede escucharte y apoyarte con una palabra amable, pero no te da nada para matar . Entonces, de qué estoy hablando ... Ah, aquí ... Se trata de accesibilidad.

Pero en el código, constantemente ... Conecte un nuevo paquete, no ha pasado un día, pero ya se está utilizando, pero directamente a todos los lugaresdesde todos lados. La mitad de su base de código ya está vinculada a sus diversas clases. En resumen, tiene una conexión muy íntima con el resto. Quizás en algunas situaciones esta sea la norma, pero no en todas, ¿verdad?

Tú: “Todo está bien, es tímido. ¿Como resolver el problema? "
Yo: "Dejar solo las clases permitidas para la interacción y restringir el acceso al resto".
Usted: "Pero en PHP no hay modificadores de acceso para las clases".
Yo: "Estoy de acuerdo, pero hay una arquitectura limpia de PHP ".

Un ejemplo ahora será nuevamente de los drogadictos, pero qué hacer.

En proyectos reales, por supuesto, los casos están llenos de casos, pero pueden traer una botella para drenar la información y pedirles que se sienten. Por eso tienes que componer.

Supongamos que en el modelo , por alguna razón, solo hay 2 clases que otros pueden conocer ... Usuario y Orden, todo lo demás debe estar oculto.

imagen

¿Qué tenemos ahora?

Cuenta con lo principal.

imagen

Puede ver de inmediato qué componentes deben revisarse.

Subimos para ver qué hay de malo en la infraestructura .

imagen

En el gráfico de "dependencias salientes" vemos elementos que violan la regla:

imagen

en la página de información del elemento, de manera similar.

imagen

Obtendremos exactamente el resultado opuesto si especificamos private_elements en la configuración .

imagen

Por ejemplo, prohibimos que todos sepan sobre Fio.

Ahora en la

imagen

página principal: en la página de información del componente de servicios :

imagen

Y en la página de información del elemento PHPCAEP \ Model \ User \ Fio :

imagen

Supervisión de violaciones de los principios de ADP y SDP

Aún así, tal vez, debemos destacar la posibilidad de incluir controles:

  • por violaciones del principio ADP, es decir para la existencia de dependencias cíclicas en el gráfico ( check_acyclic_dependencies_principle )
  • y por violaciones del principio SDP, es decir para dependencias dirigidas desde módulos más estables a menos estables ( check_stable_dependencies_principle )

imagen

Pero esto solo funciona en phpca-check hasta ahora y no se muestra en el informe. En el futuro, creo que lo corregiré.

Control automático en CI / CD


Todo este tiempo hablé sobre la primera parte: visualización. Y el análisis que puede llevarse a cabo sobre su base.

Ha llegado el momento de hacer sufrir a nuestros amigos govnokodera honorables colegas.

Lanzamos en la consola (en la raíz del proyecto):

vendor/bin/phpca-check

o

vendor/bin/phpca-check /path/to/phpca-config.php

Se supone que ejecutar este comando se agregará al proceso de CI / CD de su proyecto. En este caso, el error bloqueará el montaje posterior.

El script termina con un error y arroja algo como esto:

imagen

le doy el diente, la lista será mucho más larga en un proyecto real.

Interrogación

  1. Violación del principio de aciclicidad de dependencias (ADP)
  2. Del mismo modo, pero el ciclo es un poco más corto
  3. 2 elementos del modelo (enumerados) dependen de la infraestructura , que no está permitida por la configuración
  4. Infracción de ADP nuevamente
  5. Otro bucle y violación de ADP
  6. Infracción de SDP porque Un modelo más sostenible depende de una infraestructura menos sostenible.
  7. De nuevo dependencia cíclica, sea incorrecto
  8. 1 elemento de servicios (enumerado) depende de Fio no público

Aproximadamente este resultado lo tenemos gracias a nuestros esfuerzos y diligente gobierno .

Ahora volvamos todo por el culo. Bueno, es decir no todo, dejo las configuraciones de forma natural. Solo gobierno el código.

Para empezar, tiene sentido arreglar archivos que violan las reglas para las siguientes dependencias. En este proyecto, la mayoría de los ciclos probablemente desaparecerán por sí solos, pero en los reales, definitivamente tendrán que jugar más tiempo (aunque esto depende del grado de negligencia del sistema y la configuración de la configuración).

Solución de problemas

Eliminé una adicción inventada anteriormente.

github.com/Chetkov/php-clean-architecture-example-project/commit/f6bbbff1313bb4a22dfb6061f347ef007ba3b422f

Reiniciar proveedor / bin / phpca-check

imagen

Bueno, solo hay una configuración para editar, porque Un ejemplo fue realmente inventado por un drogadicto.

imagen

De nuevo vendor / bin / phpca-check ¡

imagen

Y el CI / CD continuó!

Eso es todo.

Epílogo


Atrapa un quinto si lo lees hasta el final, si no, huele tu pie en el camino (de todos modos, no viste esto).

Pero en serio, gracias por su tiempo, no importa si se fusionó en el medio o lo leyó, profundizó en cada línea y analizó cada pantalla o pasó ambas partes en diagonal. Gracias de cualquier manera.

Me disculpo nuevamente si algo andaba mal.

Tal vez, mi forma de presentación pueda parecerle a alguien demasiado imponente o irrespetuoso, solo quería diluir un poco el artículo y de ninguna manera quería ofender a nadie. Creo que sin esto, habría resultado demasiado seco y difícil de leer.

Estoy realmente interesado en conocer su opinión y si tiene alguna idea, idea, sugerencia u objeción, hablemos en los comentarios.

¡Código limpio y arquitectura flexible para ti!

All Articles