Architecture PHP pure. Comment le mesurer et le contrôler?

Préface


Comme vous l'avez déjà compris par le nom, je vais ici parler de l'architecture la plus «haute» - Pure. Et l'impulsion pour le développement de toute cette histoire a été le livre de Robert Martin «Architecture pure». Si je ne l'ai pas encore lu, j'ose le recommander! L'auteur révèle de nombreux sujets importants, partage activement sa riche expérience de vie (dans un domaine professionnel, bien sûr) et les conclusions tirées sur cette base, tisse de manière épisodique dans des chapitres de l'histoire comment magistralement parlé (et pas seulement, bien sûr) nos pères et grands-pères dans les années 60, 70, 80 et même les années 90, comme les grains de céréales, les principes préférés de tout le monde de SOLID et leurs analogues dans le monde des composants ont été collectés et ce qu'ils ont appris au cours du dernier demi-siècle. Au cours de la lecture du livre, la ligne de développement de l'industrie du développement logiciel est bien tracée, des problèmes typiques auxquels les garçons ont dû faire face,et les méthodes pour les résoudre.

Ne pensez pas, relire le résumé du livre n'est pas le but de ce post.
Ensuite, nous parlerons des idées qui m'ont poussé à développer un outil (je déterminerai le degré de son utilité pour vous, et j'attendrai avec beaucoup d'intérêt les retours, suggestions et critiques constructives).

Il me semble que l'article sera utile à tous. Ceux qui connaissent déjà le livre pourront rafraîchir certains de ses moments dans leur mémoire, ou simplement sauter la première partie et commencer immédiatement à se familiariser avec l'outil. Ceux qui n'ont pas lu le livre auparavant trouveront peut-être quelque chose de nouveau dans la première partie.

Pour plus de commodité, l'article est divisé en 2 parties.

Dans le premier, je parlerai des idées clés qui ont généré dans ma tête le désir d'automatiser tout cela, sommes-nous des programmeurs ou qui finalement? Ici, je citerai beaucoup de l'auteur, ainsi que d'insérer activement des extraits et des illustrations de différents chapitres du livre.

La deuxième partie, presque entièrement, sera consacrée à la description de l'outil qui a fait son apparition, révélant ses capacités et ses conseils étape par étape.

Si vous vous considérez comme une catégorie de personnes prenant tout trop près de votre cœur, je vous conseille de commencer la lecture de l' Afterword .



Partie 1


Qu'est-ce que l'architecture logicielle?


Hélas, l'auteur du livre ne donne pas une seule définition. Il existe un grand nombre de formulations différentes, et toutes sont correctes à leur manière.
Cependant, nous pouvons aller de l'autre côté ..

Quel est le but de l'architecture?


Il n'y a qu'une seule réponse:

le but de l'architecture logicielle est de réduire le travail humain requis pour créer et maintenir un système.

Une petite introduction ..

Où commencent de nombreux projets?


"Nous pourrons rétablir l'ordre plus tard, nous n'entrerons que sur le marché!"
En conséquence, l'ordre n'a pas été rétabli, car la pression de la concurrence sur le marché ne faiblit jamais.

«Le plus grand mensonge que de nombreux développeurs pensent est que le code sale les aidera à entrer rapidement sur le marché, mais en réalité, cela ralentira leur mouvement à long terme. Les développeurs qui croient en ce mensonge montrent l’arrogance de Hare, pensant qu’à l’avenir ils pourront passer du désordre à la restauration de l’ordre, mais ils commettent une simple erreur. Le fait est que la création du désordre est toujours plus lente que l'observation régulière de la propreté, quelle que soit l'échelle de temps choisie. "

Deux valeurs des produits logiciels


  1. Comportement (quelque chose d'urgence mais pas toujours important)
  2. Architecture (quelque chose d'important, mais pas toujours urgent)

Beaucoup se noient souvent dans le premier et négligent complètement le second.

Type: "Pourquoi perdre du temps à réfléchir à l'architecture, l'essentiel est qu'elle fonctionne correctement!" .

Mais ils manquent un point important: «Si un programme fonctionnant correctement ne permet pas de le changer, il cessera de fonctionner correctement lorsque les exigences changeront, et ils ne pourront pas le faire fonctionner correctement. Autrement dit, le programme deviendra inutile.

Si le programme ne fonctionne pas correctement, mais peut facilement être modifié, ils pourront le faire fonctionner correctement et maintenir ses performances à mesure que les exigences évolueront. Autrement dit, le programme restera toujours utile. "

J'ai aimé cette déclaration:«Si vous pensez qu'une bonne architecture coûte cher, essayez une architecture médiocre.» (Brian Foote et Joseph Yoder)

Il s'avère qu'il est important de prêter l'attention voulue à la propreté du code et à l'architecture en général dès les toutes premières lignes. Mais, si tout est relativement clair avec la pureté du code (reniflez toutes sortes de mauvaises odeurs dans le code et corrigez-le, en plus les outils sont pleins d'IDE intelligents, d'analyseurs statiques et d'autres déchets sans aucun doute importants), alors avec l'architecture ce n'est pas tout à fait le cas (du moins moins moi).

Comment pouvez-vous contrôler quelque chose qui est si vague qu'il est difficile même d'être défini par un seul libellé qu'il a une idée très polyvalente et chaque seconde, bon sang, merde le voit et essaie de l'interpréter à sa manière, si vous n'êtes pas le petit-fils de Vanga, n'a pas gagné le spectacle "Intuition ”Et ne sont pas particulièrement sensibles cinquième point? Ensuite, l'auteur du livre lance quelques réflexions précieuses pour la réflexion ... Disons le trier.

Pourquoi avez-vous trouvé SOLID et pourquoi ne suffit-il pas seul?


Nous connaissons probablement tous les principes de SOLID.

Leur objectif est de créer des structures logicielles de niveau intermédiaire qui:

  • tolérant au changement;
  • simple et compréhensible;
  • constituent la base de composants pouvant être utilisés dans de nombreux systèmes logiciels.

Mais: «Tout comme de bonnes briques peuvent rendre un mur inutilisable, des composants de milieu de gamme bien conçus peuvent créer un système inutilisable.»
Par conséquent, dans le monde des composants, il existe des analogues des principes SOLID, ainsi que des principes de haut niveau pour la création d'architectures.

Je vais aborder ces sujets très superficiellement, plus de détails peuvent être trouvés dans le livre. Allons-y!

Connectivité des composants et ses principes déterminants


«À quel composant appartient telle ou telle classe? Cette décision importante doit être prise conformément aux principes de développement de logiciels établis. Malheureusement, ces décisions sont de nature particulière et sont prises presque exclusivement sur la base du contexte. »

REP: Principe d'équivalence de réutilisation / libération - Le principe d'équivalence de réutilisation et de libération.

En termes d'architecture et de design, ce principe signifie que les classes et modules qui composent un composant doivent appartenir à un groupe connecté. Un composant ne peut pas simplement inclure un mélange aléatoire de classes et de modules; Il devrait y avoir un thème ou un objectif commun à tous les modules.

Les classes et modules combinés en un composant doivent être libérés ensemble.

CCP: Common Closure Principle - le principe d'un changement cohérent.
C'est le principe de la SRP (responsabilité unique) reformulé pour les composants.

Les classes qui changent pour les mêmes raisons et en même temps doivent être incluses dans un composant. Différents composants doivent inclure des classes qui changent à différents moments et pour diverses raisons.

CRP: Common Reuse Principle - Le principe de la réutilisation partagée.
Ce principe est similaire à l'ISP (interface segregation).

Ne forcez pas les utilisateurs de composants à dépendre de ce dont ils n'ont pas besoin.

Le principe indique que les classes qui ne sont pas étroitement liées ne doivent pas être incluses dans un composant.

«Vous avez peut-être déjà remarqué que les trois principes des composants connectés entrent en conflit les uns avec les autres. Les principes d'équivalence de réutilisation (REP) et de changement cohérent (CCP) sont inclusifs: tous deux s'efforcent de rendre les composants aussi grands que possible. Le principe de réutilisation (CRP) est exceptionnel, s'efforçant de rendre les composants aussi petits que possible. La tâche d'un bon architecte est de résoudre cette contradiction. »

image

«Dans le passé, nous avons examiné la connectivité plus facilement que les principes d'équivalence de réutilisation (REP), de changement cohérent (CCP) et de réutilisation partagée (CRP). Une fois que nous pensions que la connectivité n'est qu'un attribut, qu'un module remplit une et une seule fonction. Cependant, les trois principes de connectivité des composants décrivent une variété beaucoup plus complexe. Lors du choix des classes à inclure dans les composants, vous devez tenir compte des forces opposées associées à la facilité de réutilisation et de développement. Trouver un équilibre de ces forces en fonction des besoins de l'application n'est pas une tâche facile. De plus, l'équilibre est presque toujours constamment déplacé. Autrement dit, la partition considérée comme réussie aujourd'hui peut échouer après un an. Par conséquent,la composition des composants changera presque certainement avec le temps et l'objectif du projet passera de la facilité de développement à la facilité de réutilisation.

Compatibilité des composants


«Les trois principes suivants définissent les règles de la relation entre les composants. Et là encore, nous sommes confrontés à des contradictions entre facilité de développement et organisation logique. Les forces qui affectent l'architecture de la structure des composants sont techniques, politiques et volatiles. »

ADP: Principe des dépendances acycliques - le principe de l'acyclicité des dépendances.
Les boucles dans le graphique de dépendance des composants ne sont pas autorisées!

image

Quel que soit le composant affiché sur le graphique, vous commencez à vous déplacer le long des flèches indiquant la direction de la dépendance, vous ne pourrez pas revenir au point d'origine. Il s'agit d'un graphe orienté acyclique (DAG - Directed Acyclic Graph).

image

Dans cette image, nous avons une dépendance conduisant à l'apparition d'un cycle. La dépendance cyclique qui en résulte peut toujours être rompue.

Méthodes pour briser les dépendances cycliques


1. En appliquant le DIP (principe d'inversion de dépendance)

image

2. Introduction du nouveau composant

image

«La deuxième solution implique la dépendance de la structure des composants à l'évolution des besoins. En effet, au fur et à mesure que l'application grandit, la structure des dépendances des composants grandit et change. Par conséquent, il doit être constamment vérifié pour les cycles. Lorsque les cycles se forment, ils doivent être rompus d'une manière ou d'une autre. Parfois, pour cela, il est nécessaire de créer de nouveaux composants, ce qui fait croître la structure des dépendances. »

Conception descendante, ou plutôt son impraticabilité


«La structure des composants ne peut pas être conçue de haut en bas. Cette conclusion n'est pas immédiatement atteinte dès qu'ils commencent à concevoir le système, mais cela se produit inévitablement avec la croissance et le changement du système.

En considérant un grand diagramme, comme la structure des dépendances des composants, nous pensons que les composants doivent en quelque sorte représenter les fonctions du système. Mais en réalité, ce n'est pas un attribut indispensable des diagrammes de dépendance des composants.

En fait, les diagrammes de dépendances des composants reflètent faiblement les fonctions de l'application. Dans une plus large mesure, ils reflètent la commodité du montage et de la maintenance de l'application. C'est la principale raison pour laquelle ils ne sont pas conçus au début du développement du projet. Pendant cette période, aucun logiciel ne doit être collecté et entretenu, il n'est donc pas nécessaire d'établir une carte de construction et de maintenance. Mais avec l'avènement d'un nombre croissant de modules aux premiers stades de la mise en œuvre et de la conception, le besoin de gérer les dépendances augmente ... De plus, il y a un désir de limiter autant que possible l'impact des changements, nous commençons donc à prêter attention aux principes de responsabilité unique (SRP) et de changement coordonné (CCP) et à combiner les classes, qui va probablement changer ensemble.

L'une des tâches principales d'une telle structure de dépendance est l'isolement de la variabilité. Nous n'avons pas besoin de composants qui changent souvent pour les moindres raisons et qui affectent d'autres composants qui autrement seraient complètement stables. Par exemple, les modifications cosmétiques de l'interface graphique ne doivent pas affecter les règles métier. L'ajout et la modification de rapports ne doivent pas affecter les stratégies de haut niveau. Par conséquent, un graphique de dépendance des composants est créé et créé par les architectes pour protéger les composants stables et précieux contre l'influence des composants volatils.

À mesure que l'application se développe, nous commençons à nous soucier de créer des articles réutilisables. À ce stade, le principe de réutilisation partagée (CRP) commence à influencer la composition des composants. Enfin, avec l'avènement des boucles, nous commençons à appliquer le principe de l'acyclicité des dépendances (ADP), en conséquence, le graphe de dépendance des composants commence à changer et à croître.

Une tentative de conception de la structure de dépendance des composants plus tôt que n'importe quelle classe est susceptible d'échouer. À ce stade, nous ne savons presque rien de la réconciliation des changements, nous n'imaginons pas quels éléments peuvent être utilisés à plusieurs reprises, et nous allons presque certainement créer des composants qui forment des dépendances cycliques. Par conséquent, la structure des dépendances des composants devrait croître et se développer avec la conception logique du système. »

Hé, tu es toujours là? Man, c'est important, vous devez dire bonjour au moins pour entrer le sens de la partie suivante, il y aura un tutoriel brut sur l'utilisation de tulza.

SDP: Stable Dependencies Principle - le principe des dépendances stables.
Les dépendances doivent être orientées vers la stabilité!

«Qu'entend-on par« durabilité »? Imaginez une pièce se tenant sur un bord. Sa position est-elle stable? Vous répondrez très probablement «non». Cependant, si vous le protégez des vibrations et des coups de vent, il peut rester dans cette position pendant une durée arbitraire. Autrement dit, la durabilité n'est pas directement liée à la fréquence des changements. La pièce ne change pas, mais presque personne ne dira que, debout sur le bord, elle est dans une position stable.

Le dictionnaire explicatif dit que la durabilité est «la capacité de maintenir sa condition sous des influences extérieures». La durabilité est liée à la quantité de travail qui doit être fait pour changer d'état. D'une part, une pièce se tenant sur un bord est dans un état instable car il faut un petit effort pour la renverser. En revanche, la table est dans un état très stable, car elle nécessite un effort beaucoup plus important pour la faire basculer.

Qu'est-ce que tout cela a à voir avec les logiciels? De nombreux facteurs compliquent le changement d'un composant, tels que sa taille, sa complexité et sa clarté. Mais nous allons laisser de côté tous ces facteurs et nous concentrer sur autre chose. Il existe un moyen infaillible de rendre un composant logiciel difficile à modifier en créant de nombreux autres composants qui en dépendent. Un composant avec de nombreuses dépendances entrantes est très stable, car la réconciliation des modifications avec tous les composants dépendants nécessite un effort considérable. "

image

image

Comment évaluer la stabilité du composant? L'auteur suggère de calculer le nombre de ses dépendances entrantes et sortantes et de calculer sur leur base la mesure de sa stabilité.

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

Donc, ce principe dit que la métrique du composant I doit être supérieure aux métriques des composants I qui en dépendent. Autrement dit, les mesures que je devrais diminuer dans le sens de la dépendance.

Il est important de noter que si tous les composants du système sont aussi stables que possible, un tel système ne pourra pas être modifié. Par conséquent, tous les composants ne doivent pas être stables.

Mec, ne t'endors pas, je suis près. Il ne reste qu'un peu!

SAP: Stable Abstractions Principle - le principe de stabilité des abstractions. La stabilité d'un composant est proportionnelle à son caractère abstrait.

«Certaines parties des systèmes logiciels devraient changer très rarement. Ces pièces représentent des décisions architecturales de haut niveau et d'autres décisions importantes. Personne ne veut que ces décisions soient volatiles. Par conséquent, les logiciels encapsulant des règles de haut niveau doivent résider dans des composants stables (I = 0). Volatile (I = 1) ne devrait contenir que du code mutable - un code qui pourrait être facilement et rapidement modifié.

Mais si vous placez des règles de haut niveau dans des composants stables, cela compliquera la modification du code source qui les implémente. Cela peut rendre toute l'architecture rigide. Comment rendre un composant avec une stabilité maximale (I = 0) si flexible qu'il reste stable lors des changements? La réponse réside dans le principe d'ouverture / fermeture (OCP). Ce principe dit qu'il est possible et nécessaire de créer des classes suffisamment flexibles pour qu'elles puissent être héritées (étendues) sans changement. Quelles classes respectent ce principe? Abstrait.

SAP (le principe de la stabilité des abstractions) établit un lien entre la stabilité et l'abstraction. D'une part, il dit qu'un composant stable doit également être abstrait pour que sa stabilité n'entrave pas l'expansion, et d'autre part, il dit qu'un composant instable doit être concret, car l'instabilité facilite le changement de code.

Autrement dit, un composant stable doit être composé d'interfaces et de classes abstraites afin de pouvoir être facilement étendu. Les composants résilients disponibles pour l'expansion sont suffisamment flexibles pour ne pas trop restreindre l'architecture.

Les principes de stabilité des abstractions (SAP) et des dépendances stables (SDP) correspondent ensemble au principe de l'inversion de dépendance (DIP) pour les composants. Cela est vrai parce que le principe SDP exige que les dépendances soient dirigées vers la durabilité, et le principe SAP stipule que la durabilité implique l'abstraction. Autrement dit, les dépendances doivent être orientées vers l'abstrait.

Cependant, le principe DIP est formulé pour les classes, et dans le cas des classes, il n'y a pas de tons moyens. La classe est abstraite ou non. Les principes de SDP et SAP s'appliquent aux composants et permettent une situation où un composant est partiellement abstrait ou partiellement stable. »

Comment mesurer l'abstraction d'un composant? Ici aussi, tout est très simple.
La valeur de la mesure de la composante abstraite est déterminée par le rapport du nombre de ses interfaces et classes abstraites au nombre total de classes.

  • Nc: le nombre de classes dans le composant.
  • Na: le nombre de classes abstraites et d'interfaces dans le composant.
  • A: abstrait. A = Na ÷ Nc .

La valeur de la métrique A varie dans la plage de 0 à 1. 0 signifie l'absence totale d'éléments abstraits dans le composant et 1 signifie que le composant ne contient que des classes et des interfaces abstraites.

Dépendance entre I et A

Si vous tracez sur le graphique (Y - abstraction, X - instabilité) de «bons» composants des deux types: abstrait stable et concret instable, nous obtenons ceci:

image

Mais, parce que les composants ont différents degrés d'abstraction et de stabilité, loin de tous tomber dans ces 2 points (0, 1) ou (1, 0), et comme il est impossible d'exiger que tous les composants soient en eux, nous devons supposer que sur le graphique A / Il y a quelques points qui déterminent les positions optimales pour les composants.

Cet ensemble peut être dérivé en définissant des zones où les composants ne doivent pas être situés - en d'autres termes, en définissant des zones d'exclusion.

image

Zone de douleur

Considérez les composants situés près du point (0, 0).

Ils sont très stables et spécifiques. De tels composants sont indésirables car sont trop durs. Ils ne peuvent pas être développés, car ils ne sont pas abstraits et il est très difficile de les changer en raison de leur grande stabilité. Plus nous modifions le composant qui pénètre dans la zone douloureuse, plus il apporte de douleur. Cela est dû à la complexité de son changement.

Les composants correctement conçus ne doivent généralement pas être proches du point (0, 0).
Cependant, en réalité, il existe des entités logicielles qui tombent dans cette zone. Par exemple, le schéma de base de données, il est aussi spécifique que possible et de nombreuses dépendances s'étendent vers lui. C'est l'une des raisons pour lesquelles les modifications de schéma de base de données sont généralement associées à une grande douleur.

Zone inutile

Considérez les composants situés près du point (1, 1).

De tels composants sont également indésirables, car ils sont aussi abstraits que possible et n'ont pas de dépendances. Ils sont tout simplement inutiles. Ce sont souvent des classes abstraites qui n'ont jamais été implémentées.

Comment éviter d'entrer dans les zones d'exclusion?

Placez les composants à proximité ou sur la séquence principale. De tels composants ne sont pas «trop abstraits» pour leur stabilité et pas «trop instables» pour leur caractère abstrait. Ils ne sont pas inutiles et ne causent pas beaucoup de douleur. D'autres composants en dépendent dans la mesure de leur caractère abstrait, et ils dépendent eux-mêmes d'autres dans la mesure de leur spécificité.
Les positions les plus souhaitables pour les composants sont les extrémités de la séquence principale. Cependant, dans les grands systèmes, il y aura toujours plusieurs composants qui ne sont pas suffisamment abstraits et pas assez stables. Ces composants ont d'excellentes caractéristiques lorsqu'ils sont situés sur ou à proximité de la séquence principale.

La distance à la séquence principale

Puisqu'il est souhaitable que le composant soit situé sur ou près de la séquence principale, il est possible de déterminer une métrique exprimant la distance du composant par rapport à l'idéal.

  • D: distance. D = | A + I - 1 | . Cette métrique prend des valeurs de la plage [0, 1]. Une valeur de 0 indique que le composant est directement sur la séquence principale. Une valeur de 1 indique que le composant est situé à la distance maximale de la séquence principale.

En adoptant cette métrique, vous pouvez explorer la conception entière à proximité de la séquence principale. La métrique D peut être calculée pour n'importe quel composant. Tout composant avec une valeur métrique D loin de zéro nécessite une révision et une restructuration.

image

Conclusion de l'auteur (Robert Martin)


«Les métriques de gestion des dépendances décrites dans ce chapitre vous aident à quantifier la cohérence de la structure de dépendance et de l'abstraction de conception avec ce que j'appelle une« bonne »conception. L'expérience montre qu'il existe de bonnes dépendances, il y en a de mauvaises. Cette note reflète cette expérience. Cependant, les métriques ne sont pas la vérité ultime; ce ne sont que des mesures basées sur une norme arbitraire. Ces mesures sont imparfaites - au mieux, mais j'espère que vous les trouverez utiles. »

Mec, je suis content si tu es toujours avec moi. C'est tout avec la première partie. Bien qu'il y ait encore beaucoup de sujets, et les pensées détaillées de l'auteur sont restées inchangées. Pourtant, le but principal de mon article n'est pas de relire le livre, sinon vous seriez certainement plus heureux de lire l'original. Moi, je fais de la randonnée, et donc déjà spécifiquement allé trop loin avec la quantité de contenu, mais je serai bâtard, j'ai essayé de ne pas gonfler comme je le pouvais. Rond!

Deuxième jour. Umm, c'est-à-dire Partie 2


introduction


Qu'est-ce que je frotte depuis si longtemps? "Ah, oui ... Nous sommes comme des architectes, ou nous voulons vraiment être eux, non?"

Qu'avons-nous? - Une sorte de projection misérable, ou peut-être un système monstrueux, PROJECT, sa mère, eh bien, ou finalement il n'y a pas encore de nifig, mais nous nous frottons les mains, regardons le calendrier et trouvons à quel point nous devrons parler.

Il n'y a pas de nous, je travaille seul! Ou peut-être que nous, avec un acolyte, dans le garage, allions remplir une nouvelle pomme, pourquoi pas? Eh bien, soit nous sommes une armée et nous faisons tous partie d'une entreprise lourde, nous travaillons dur, comme les Noirs des pauvres à la maison (c'est-à-dire, les Afro-Américains, bien sûr, vous comprenez), ou peut-être que nous donnons des coups de pied tranquillement pour ne pas être licenciés. Pour un gros salaire avec un bonus, des cookies et une vue de la ville de Moscou ou pour un enthousiasme dénudé, pour une idée et une mise dans une startup qui naturellement enfer quand elle décolle.

En fait, cela n'a pas d'importance. Ce qui est important, c'est ceci: au final, nous voulons tous simplement que notre idée originale ne se plie pas prématurément, enfin, au moins avant notre départ, et il y a toutes les chances pour cela. Oui, oui ...

Et que faire maintenant, demandez-vous? Donc, si vous n'avez pas de grand frère au bureau, alors frère ne peut pas se passer d'un troisième œil.

Résumé de la première partie


Dans la dernière partie de l'article, nous avons parlé un peu des métriques qui permettent aux architectes de mesurer leur nombre en chiffres pour refléter le degré de qualité de l'architecture de leur système.

A - abstraction du composant
I - instabilité du composant
D - distance à la séquence principale sur le graphique A / I Des zones érogènes des zones de douleur et de futilité ont été

révélées . Nous sommes arrivés à la conclusion que, idéalement, A devrait augmenter et diminuer proportionnellement à une diminution et, par conséquent, une augmentation de I

. Les composants bien conçus doivent être sur ou au moins proches de la séquence principale, c'est-à-dire D doit être aussi proche de zéro que possible et les dépendances entre les composants doivent être acycliques et orientées vers la stabilité.

J'espère également que tout le monde comprend que certains composants peuvent en connaître beaucoup d'autres, tandis que d'autres ne devraient rien savoir. Tout comme dans les États esclavagistes avant l'arrivée du bon oncle Abraham, au contraire, les nègres (au sens des Afro-Américains) n'étaient pas autorisés au nichrome (en termes de connaissances, et pas seulement), dans notre cas, les composants les plus importants du système devraient avoir un minimum de connaissances, ils devrait être autosuffisant et abstrait de différents détails.

Et le troisième œil? Architecture propre PHP- un outil qui est apparu à la suite de la lecture d'un livre, grâce à l'oncle Bob (Robert Martin) pour ses pensées précieuses, et son désir fou de visualiser le tout, pour la commodité de l'analyse, et d'automatiser, pour la possibilité d'inclure diverses vérifications dans CI / CD (similaire à PHPStan, Phan et d'autres, uniquement pour identifier précisément les problèmes architecturaux).

Outil et projet de test. Introduction au sujet


Pouf, tout semble être comme une théorie ... Maintenant, vous pouvez même vous salir les mains pour plus de détails.
Et donc pour moi maintenant je n'ai pas de chevaux abstraits dans le vide à frotter, et tu as la fin de la lecture c'était moins de raison de m'appeler mudiloy, à cause de laquelle tu as baisé passé tellement de temps, je devais prosrat passer un peu de son, et préparer une démo projet, qui, sobstna, nous allons maintenant faire hara-kiri. Pour les mecs «super doués» qui seront sans aucun doute et voudront se détendre dans les commentaires, concernant ses détails, j'insiste - c'est un projet DEMO .
Je l'ai coupé en une demi-journée environ, à peu près, sur les genoux de ma copine. Après tout, je ne peux pas donner au grand public les détails des projets de combat avec lesquels je dois travailler ... Les gars de l'épave ne comprendront pas, ils me montreront, mais en ai-je besoin? Eh bien, si vous êtes un simple garçon, pas l'un des "particulièrement remarquables", alors je suis moche pour une si longue introduction, je devais juste prendre les risques et réduire la menace potentielle de reproduction dans les commentaires des bazars à propos de rien.

Ainsi, le projet lui-même se trouve ici github.com/Chetkov/php-clean-architecture-example-project .

À l'avenir, il pourrait devenir une boutique en ligne à part entière. Je suis certainement un perfectionniste féroce, mais vous devez être un non-sens completmangeur de soleil et long foie, en plus de souffrir d'insomnie, afin de passer autant de temps sur le «lapin expérimental» et en confectionner des bonbons. Comme vous le comprenez, ce projet ne sera jamais mené à son terme logique , cependant, comme tous les autres, même des projets de combat.

Bien que ce ne soit pas si mal. À l'heure actuelle, il a: utilisateur, produit et commande , ainsi que des scénarios: enregistrement d'utilisateur, changement de mot de passe, ajout d'un produit et réservation d'une commande .

Le projet fonctionne plus ou moins, vous pouvez le cloner vous-même et exécuter des scripts à partir du dossier sandbox, bien qu'en fait, je n'ai même pas pu le faire, car pour l'analyse de l'architecture, le projet ne nécessite pas d'opérabilité.

À l'avenir, je mettrai des liens vers des commits spécifiques afin de corriger immédiatement les points techniques décrits dans l'article.

Etat initial,

je suppose que vous avez déjà réussi à vous familiariser avec la structure. Nous pouvons donc continuer.

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


Nous créons et configurons le fichier de configuration

Visualisation pour analyse


Nous exécutons dans la console (à la racine du projet):

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

Et en réponse, nous obtenons:

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

Le rapport se compose de 3 écrans:

1. Informations générales sur le système

image

Cet écran affiche:

Le même graphique A / I montrant la dispersion des composants:

image

Graphique montrant l'éloignement des composants de la séquence principale:

image

Et un graphique montrant les relations entre les composants: les

image

flèches indiquent la direction des dépendances et les nombres sur elles indiquent la force de la connexion.

Parce que Les IDE modernes fournissent un moyen facile de refactoriser (ils trouvent eux-mêmes et corrigent tous les domaines où la méthode ou la classe est explicitement appelée, par exemple, lors du changement de nom ou du transfert vers un autre espace de noms), j'ai pris le nombre d'éléments du module de dépendance utilisé par le module dépendant pour la force de communication.

Par exemple: les éléments du module services connaissent environ 12 éléments du module modèle et les éléments infrastructure connaissent 1 élément de services . Etc.

Soit dit en passant, ce qui est * non défini *? Bro, la question attendue. Il s'agit d'un module créé automatiquement pour tous les éléments qui, lors de l'analyse du système, n'ont pu être attribués à aucun des éléments connus (c'est-à-dire ceux répertoriés dans le fichier de configuration).

Si, cependant, vous corrigez la configuration de cette manière:

image

Ensuite, dans le processus d'analyse du système, les paquets connectés via composer seront également pris en compte (ils ne seront pas eux-mêmes scannés, mais l'image deviendra beaucoup plus complète).

Soit dit en passant, dans vendor_path, vous devez spécifier le chemin vers le répertoire du fournisseur et dans les chemins exclus vers les répertoires des packages que nous voulons exclure (par exemple, si nous décrivons un package dans la configuration principale des modules à analyser).

Après avoir activé vendor_based_modules le graphique a changé, bien que nous n'ayons pas changé la configuration des modules eux-mêmes

image

2. Informations détaillées sur le composant

image

Ici, nous voyons également:

  • Graphique des interconnexions , mais pas de l'ensemble du système, mais uniquement des composants impliqués
  • Graphique A / I affichant uniquement le composant actuel
  • Caractéristiques du module clé

    image

et
  • Graphique de dépendance sortante montrant le nombre et la liste des fichiers dans le module actuel, en fonction des fichiers des autres modules.
  • image

  • Et un graphique des dépendances entrantes , montrant le nombre et la liste des fichiers dans d'autres modules, selon le module actuel.

    image

Les 2 derniers graphiques, à mon avis, sont particulièrement intéressants, car il est facile de trouver des dépendances indésirables sur eux, mais plus à ce sujet plus tard.

3. Informations détaillées sur l'élément composant

image

Ici, vous pouvez voir:

  • Caractéristiques principales de l'élément, tels que l' abstraction de type, l' instabilité, primitif, et à laquelle le composant appartient , et le modificateur d'accès .

"Che, un modificateur d'accès aux classes en PHP?" - vous dites, percer un trou dans la zone du temple avec votre doigt, non? Prenez votre temps, je sais qu'il n'y a pas de cours privés sous la chaleur, mais ce serait cool s'ils l'étaient? En général, plus à ce sujet plus tard.

  • Graphique de dépendance , qui reflète l'interaction de l'élément considéré avec d'autres éléments du système

  • Et tablettes avec dépendances sortantes et entrantes

    image

Une fois la description des écrans terminée, allez dans les configurations pour choisir et piquer comment il peut être configuré.

Options de configuration


Limitation de la distance maximale autorisée par rapport à la séquence principale (pour tous les composants)

Tout d'abord, essayons de définir tous les composants sur la distance maximale autorisée par rapport à la séquence principale. Il serait stupide de penser qu'ils se trouveront tous sur la diagonale principale, car le monde n'est pas parfait, alors soyons réalistes. Je fais 0.3

image

Redémarrez la commande de génération de rapport et voyez immédiatement la violation sur la page principale. Le composant du modèle dépasse la distance autorisée de 0,192

image

Limiter la distance maximale autorisée à la séquence principale (à un composant spécifique)

C'est bien, mais supposons que c'est le composant de modèle qui peut violer cette restriction. Différentes choses se produisent ... Après tout, nous n'avons souvent pas déjà de systèmes idéaux avec lesquels nous devons travailler, les soutenir et les améliorer. Tout le monde comprend que personne ne pourra réduire rapidement cette distance, même probablement avec un dieu (j'espère qu'il me pardonnera).

À mon avis, l'essentiel est de réparer l'état actuel, de travailler à des améliorations et de contrôler la situation afin de ne pas aggraver.

Encore une fois, accédez à la configuration et définissez max_allowable_distance , uniquement pour un module spécifique. Je fixe sa valeur actuelle 0.492

image

ZBS, maintenant tout redevient normal.

image

Mais si, avec du ** ka Vasya, il fume à nouveau quelque chose et empire - coupez-lui les mains! Un CI / CD qui inclut l'exécution de la commande phpca-check (nous en parlerons plus tard) le gronde, peut-être même un langage grossier, et bien sûr, il mettra en évidence les erreurs.

Contrôle de la dépendance des composants

Quoi d'autre serait bien d'avoir dans notre arsenal pour faire face à une mauvaise architecture? Bien sûr, le contrôle des dépendances. Qui peut savoir qui, ou vice versa, ne devrait pas savoir.

Que pensez-vous, la partie très centrale du système, disons domaine , peut-elle permettre à DDDowski de savoir quelque chose sur une infrastructure malodorante ?
Bien sûr OUI, pour certains, c'est directement un attribut de réussite (enfin, je parle de ceux qui rendent le HTML mélangé à la logique métier). Mais finalement, comme ça, je ne devrais pas ... Je certes xs, mais toutes sortes de gars intelligents différents dans les livres disent que ce n'est pas patsansky.

Alors remuons comme ça ... Tout est au même endroit, dans la configuration des restrictions pour le modèle .

image

Hmm ... Jusqu'à présent, toutes les règles, parce quemodèle sur l' infrastructure ne sait vraiment rien ...

Eh bien alors amusons-nous ... La stupidité est certainement rare, mais je n'ai rien trouvé de mieux. Krch, au moment de la création de l'utilisateur, nous «enverrons» des SMS et au moment de la création de la commande, «enverrons» les courriels. Et pour ce faire, grâce à des implémentations spécifiques de notifiants qui se trouvent dans l' infrastructure .

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

Maintenant, nous examinons le rapport ... Comme nous pouvons le voir, les graphiques sur différentes pages du rapport mettent en évidence cette connexion comme illégitime.

Accueil.

image

Rapport de composant.

image

Sur les graphiques du modèle des «dépendances sortantes» et des «dépendances entrantes»l'infrastructure , nous voyons immédiatement des éléments qui violent la règle introduite

image

Dans les tableaux des «dépendances sortantes» des éléments du modèle et des «dépendances entrantes» des éléments de l' infrastructure , de la même manière.

PHPCAEP \ Model \ User \ User

image

PHPCAEP \ Infrastructure \ Notification \ Sms \ SmsNotifier

image

Ainsi que sur le graphique des relations entre les éléments. Je pense que dans le futur, pour m'en débarrasser complètement, parce que il n'est pas très informatif (en particulier pour les classes activement utilisées, en raison de la longueur du nom des nœuds + leur nombre énorme)

image

Des actions similaires peuvent être effectuées avec la configuration allowed_dependencies .

image

Le résultat sera complètement opposé.

Il est possible de composer une config indiquant pour le module et interdite, et autorisé (s'il y a un désir, nous discuterons plus en détail dans les commentaires). Il n'est pas encore possible de spécifier un composant à la fois en interdit et en autorisé ... On a pensé à introduire une configuration pour indiquer la priorité, mais jusqu'à présent je n'ai pas fait cela et je ne suis pas sûr de ce que je vais faire. Tout dépend de vos commentaires. Peut-être que tout cela est gaspillé?

Classe publique / privée en PHP

D'accord, nous avons appris comment restreindre et contrôler la gamme de connaissances des composants. Déjà pas mal. Et après?

Et puis un autre problème. L'ennemi ne dort pas, bien que dans la plupart des cas cet ennemi, nous le sommes nous-mêmes ou nos acolytes au bureau.

Cela arrive après tout, vous avez rencontré une fille, parlé, découvert quelque chose à son sujet, peut-être même courtisé, mais bon sang, ça ne marche pas pour vous. Nous sommes amis et tout ça ... Elle peut vous embrasser quand elle vous rencontre, elle peut vous écouter et vous soutenir avec un mot aimable, mais elle ne vous donne rien à tuer . Alors de quoi je parle ... Ah, ici ... Tout est question d'accessibilité.

Mais dans le code, en permanence ... Connectez un nouveau package, pas un jour ne s'est écoulé, mais il est déjà utilisé, mais directement à tous les endroitsde tous les côtés. La moitié de votre base de code est déjà liée à ses différentes classes. Bref, il a un lien très intime avec les autres. Peut-être que dans certaines situations, c'est la norme, mais pas du tout, non?

Vous: «Tout va bien, c'est timide. Comment résoudre le problème? "
Moi: "Ne laissez que les classes autorisées pour l'interaction et restreignez l'accès au reste."
Vous: "Mais en PHP, il n'y a pas de modificateurs d'accès pour les classes."
Moi: "Je suis d'accord, mais il y a une architecture PHP propre ."

Un exemple sera maintenant à nouveau des toxicomanes, mais que faire.

Dans les projets réels, bien sûr, les étuis sont pleins d'étuis, mais ils peuvent apporter une bouteille pour drainer les informations et leur demander de s'asseoir. C'est pourquoi vous devez composer.

Supposons que dans le modèle , pour une raison quelconque, il n'y a que 2 classes que les autres sont autorisés à connaître ... Utilisateur et ordre, tout le reste doit être caché.

image

Qu'avons-nous maintenant?

Comptez sur le principal.

image

Vous pouvez immédiatement voir quels composants doivent être examinés.

Nous montons pour voir ce qui ne va pas avec l' infrastructure .

image

Sur le graphique des «dépendances sortantes», nous voyons des éléments qui violent la règle:

image

De la même manière, sur la page d'informations sur les éléments.

image

Nous obtiendrons exactement le résultat opposé si nous spécifions private_elements dans la config .

image

Par exemple, nous interdisons à tout le monde de connaître Fio.

Maintenant sur la

image

page principale: Sur la page d'informations sur les composants des services :

image

Et sur la page d'informations sur l'élément PHPCAEP \ Model \ User \ Fio :

image

Surveillance des violations des principes de l'ADP et du SDP

Néanmoins, nous devons peut-être souligner la possibilité d'inclure des contrôles:

  • pour les violations du principe ADP, à savoir pour l'existence de dépendances cycliques dans le graphique ( check_acyclic_dependencies_principle )
  • et pour les violations du principe SDP, à savoir pour les dépendances dirigées de modules plus stables vers moins stables ( check_stable_dependencies_principle )

image

Mais cela ne fonctionne que dans phpca-check jusqu'à présent et n'est pas affiché dans le rapport. À l'avenir, je pense que je vais le corriger.

Contrôle automatique en CI / CD


Pendant tout ce temps, j'ai parlé de la première partie - la visualisation. Et l'analyse qui peut être effectuée sur sa base.

Le moment est venu de faire souffrir nos amis govnokodera collègues.

Nous lançons dans la console (à la racine du projet):

vendor/bin/phpca-check

ou

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

Il est supposé que l'exécution de cette commande sera ajoutée au processus CI / CD de votre projet. Dans ce cas, l'erreur bloquera tout autre assemblage.

Le script se termine avec une erreur et lance quelque chose comme ceci:

image

je donne la dent, la liste sera beaucoup plus longue dans un vrai projet.

Compte rendu

  1. Violation du principe de l'acyclicité des dépendances (ADP)
  2. De même, mais le cycle est un peu plus court
  3. 2 éléments de modèle (répertoriés) dépendent de l' infrastructure , ce qui n'est pas autorisé par la configuration
  4. Violation ADP à nouveau
  5. Un autre cycle et violation ADP
  6. Violation SDP car un modèle plus durable dépend d'une infrastructure moins durable
  7. Encore une fois, la dépendance cyclique
  8. 1 élément de services (répertorié) dépend de Fio non public

Environ ce résultat, nous avons grâce à nos efforts et govnokoding diligent .

Maintenant, mettons tout dans le cul. Eh bien, c'est-à-dire pas tout à fait, je laisse les configs naturellement. Je règle uniquement le code.

Pour commencer, il est logique de corriger les fichiers qui enfreignent les règles pour les dépendances suivantes. Dans ce projet, la plupart des cycles disparaîtront probablement d'eux-mêmes, mais dans les vrais, ils devront définitivement bricoler plus longtemps (bien que cela dépende du degré de négligence du système et des paramètres de la configuration).

Dépannage

J'ai supprimé une dépendance inventée précédemment.

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

Redémarrez le vendeur / bin / phpca-check

image

Eh bien, il n'y a qu'une configuration à modifier, car un exemple a vraiment été inventé par un toxicomane.

image

Encore une fois vendeur / bin / phpca-check

image

Et le CI / CD a continué!

C'est tout.

Épilogue


Attrapez un cinquième si vous le lisez à la fin, sinon, reniflez votre pied sur la route (de toute façon, vous ne l'avez pas vu).

Mais sérieusement, merci pour votre temps, peu importe si vous avez fusionné au milieu ou que vous l'avez lu, fouillé dans chaque ligne et analysé chaque écran ou parcouru les deux parties en diagonale. Merci quand même.

Je m'excuse encore si quelque chose n'allait pas.

Peut-être, ma manière de présenter pourrait sembler à quelqu'un trop imposant ou irrespectueux, je voulais juste diluer légèrement l'article et en aucun cas je ne voulais offenser personne. Je pense que sans cela, il se serait avéré trop sec et difficile à lire.

Je suis vraiment intéressé de connaître votre opinion et si vous avez des pensées, des idées, des suggestions ou des objections, discutons-en dans les commentaires.

Du code propre et une architecture flexible pour vous!

All Articles