Architecture front
De manière générale :
- Diviser l'appli en couches, séparer domaine / infrastructure / UI
- Eviter le code métier dans un composant d'UI (le sortir dans un controller/service séparé) => meilleur découpage et permet de tester unitairement plus facilement (vu que pas besoin de gérer le framework d'UI)
- Eviter l'import de store, services,... dans le fichier du controller directement ! Venir l'injecter dans le constructeur => permet de pouvoir mocker lors du test unitaire (cf dependency-cruiser qui permet de mettre des règles de dépendances, et les visualiser)
- Penser au SRP => Single Responsibility Principle
- Eviter de coupler du code qui va diverger avec le temps : il vaut mieux parfois un code découplé qu'un code DRY
- Forte cohésion et faible couplage !
Gestion des dépendances
- Les dépendances du code source doivent pointer vers l'intérieur => plus facile d'isoler l'impact de nos changements
- Plusieurs façons d'organiser nos dépendances
- Ne pas les organiser (= un beau bordel)
- En couche (Couche A et E dépendant de couche B, B dépendant de couche C etc)
- Par module
- Inconvénients d'une mauvaise gestion : risque fort (ou inconnu) de régression
- Avantages d'une bonne gestion : limite le scope de régression. N'affecte pas les autres équipes.
Couplage
- = dépendances entre modules
- Dépendance = nécessaire au bon fonctionnement du module
- Plusieurs types de couplages : appel de méthodes, héritage, paramètre de méthode,...
- Impacts : modification en cascade, réutilisation + difficile, tests et externalisation + difficile
- Couplage efférent vs afférent
- Efférent = dépendance sortante, le nb de classes dans un paquet qui dépendent d'une classe d'un autre paquet
- Afférent = dépendance entrante, le nb de classes hors d'un paquet qui dépendent des classes dans le paquet
- Minimiser le couplage !
Quelques métriques utilisées : (de part les travaux du LCOM4 - Lack of Cohesion in Methods)
- CBO (Coupling Between Objects) = couplage entre objets, nb de classes couplées à la classe mesurée
- LCOM (Lack of Cohesion of Methods) = mesure le manque de cohésion de la classe
- LCC (Loose Class Cohesion) = le nombre relatif de méthodes connectées directement
- TCC (Tight Class Cohesion) = le nombre relatif de méthodes connectées directement et indirectement
- MCC (McCabe's Cydomalic Complexity) = le nombre de chemins possibles à l'intérieur d une méthode
Cohésion
- = niveau d’appartenance entre éléments d’un même module, lien entre les éléments d’un même module
- Différents types de cohésions
- coincidence (= accidentelle, aléatoire)
- logique (regroupement par type d’opération, exemple "controllers")
- temporel (regroupé par activitées liées dans le temps)
- procédural
- communicationnel/Informationnel (regroupement par opération sur les mêmes données (ex: utils) )
- séquentiel
- fonctionnel (regroupement par cas d’utilisations)
Architecture hexagonale
Aussi appelé "ports et adapters", "port" étant l'interface que le code doit implémenté pour s'abstraire d'une technologie, et "adapter" étant l'implémentation de cette interface.
- Couche Domain
- Interface (typage métier) => de la donnée métier ("Entities" ou "Models") et du controller
- Usecase (= besoin fonctionnel de l'application)
- Exemple : "Un panier ne peut pas contenir plus de 10 produits" ou "Ajouter un article au panier"
- C'est l'orchestrateur
- Couche Infrastructure
- gestion des appels vers le back
- services,...
- DTO (Data Transfer Object) : interface/typage de la donnée qui nous est retournée par le back
- Couche UI : composants d'UI => ne doit pas contenir de code métier, interagit avec la couche infrastructure
Clean architecture
- Principes
- Indépendant des frameworks (frameworks de vue, de gestion du réseau, de la BDD, etc)
- Découpage métier : pas de regroupement technique (par dossier “services”, “controller”, etc) mais un regroupement métier par module
- Création de usecase / interactor (un usecase = une fonctionnalité métier)
- Avantages
- Simplifie le changement d’implémentation
- Implémentation des fonctionnalités plus rapide
- Réutilisation des usecases
- Risques : trouver le juste milieu en trop / pas assez découper
Onion architecture
SOLID
= 5 principes de conception pour une bonne architecture
Principes inventés par Robert C Martin (livre "Design Principles and Design Patterns") et acronyme créé par Michael Feathers.
- Single responsibility = une classe ne doit comporter qu'une seule responsabilité, "une classe ne doit avoir qu'une seule et unique raison de changer"
- Open/closed
- Liskov substitution
- Interface segregation = un client ne doit pas être forcé à dépendre d'interfaces qu'il n'utilise pas, il faudrait ne voir que les services qu'il utilise réellement !
- Dependency inversion
Sources
- How to implement Hexagonal architecture in frontend (Javascript/Typescript)
- Building resilient frontend architecture de Monica Lent (FrontCon 2019)
- Pourquoi vous avez besoin d'une Clean Architecture (Devoxx 2018)