2.2 Principes de conception du BACK
Ce chapitre liste les principaux principes de conception du Back.
2.2.1 - Découpage en micro-service
Le code du BACK est construit sous forme de micro-services. Un micro-service est un applicatif
- autonome : Capable de démarrer seul et proposant des fonctionnalités sous forme de service (exemple : à défaut d’une base de données démarrée, un applicatif autonome peut renvoyer une réponse contenant un message d’erreur).
- cohérent : Les services qu’il fournit sont fonctionnellement liés entre eux et forment un tout qui a du sens (contre-exemple : il ne fait pas le lit en fournissant le café et nettoyant la mousse sur les tuiles du toit de la maison).
- faiblement couplé : L’applicatif n’a pas besoin d’interroger tout un ensemble d’autres applicatifs pour fournir ses services.
- de bonne granularité : Il fournit plus d’un service mais pas des centaines non plus. La granularité est un autre point de vue sur la dualité cohérence/couplage. Sur ce projet (comme souvent), la bonne granularité est définie via les données traitées/stockées. Ainsi chaque micro-service du socle traite de données différentes sans couplage fort entre elles (une référence par un identifiant est autorisée mais pas de contraintes structurelles ou métiers comme le ferait une ForeignKey SQL).
2.2.2 - Gestion commune des dépendances
Malgré la multiplication des applicatifs, il est important qu’une homogénéité soit conservée dans la gestion des dépendances tant pour faciliter le maintien en conditions opérationnelles du SI que dans son maintien en conditions de sécurité (simplification de la veille sécuritaire).
2.2.3 - Design pattern en couches
Les composants applicatifs Java des micro-services sont répartis selon le design pattern en couches (explications Oreilly). L’idée est que chaque composant applicatif, en fonction de ce qu’il fait, est placé dans une couche applicative. Une couche, dans le code, se matérialise par un package précis et des suffixes de nom de classe. La dernière contrainte apportée par ce pattern est la communication entre les composants : un composant ne peut appeler que un composant de la couche inférieur et ne peut être appelé que par un composant de la couche supérieur (et sans saut de couche). Les dites couches sont :
- contrôleur (package controlleur et suffixe Controleur) : cette couche contient des composants exposant des méthodes JAVA sous forme d’API REST avec Spring MVC
- service (package service et suffixe Service) : ces composants contiennent toute l’intelligence et l’algorithmie des applicatifs. Les transactions débutent à l’entrée d’un service et se terminent à la sortie du dit service. A défaut de transaction, le service doit prévoir des mécaniques de compensation (transaction & Spring).
- dao (package dao et suffixe Dao) : ces composant traite du stockage ([S]CRUD) de données quelque soit le conteneur (base de données SQL ou noSQL.
- dto (package dto et suffixe Dto) et/ou objets métiers (package entity) sont les deux couches qui n’en sont pas. Ces deux ensembles contiennent les classes décrivant les données gérées par l’application. Ces éléments traversent les couches. Ces deux couches sont donc transverses. Attention, 3 concepts différents sont en jeu ici :
- un DTO est un objet de transport (Data Transport Object). Son objectif est de décrire des données dont la structure est utilisée dans un contexte précis (exemple : pour afficher le nombre et la moyenne d’âge des clients regroupés par la première lettre de leur prénom, il nous faut une liste d’objet contenant les 3 attributs premiereLettrePrenomClient, ageMoyen et nombreDeClients).
- un objet métier est une classe décrivant une structure de données ayant un sens réel pour l’utilisateur (exemple : un système de facturation contiendra des objets métiers comment Facture, LigneDeFacture, LigneComptable, …) et contenant du code intelligent. Ainsi, un service métier peut appeler du code intelligent présent dans un objet métier (exemple : Facture.calculerSommeDesLignesDeFacture voir même Facture.genererFactureEnPdf)
- une entité persisté (alias entity) est une classe décrivant une structure de données de stockage.
Existent des débats sur le fait d’exposer des entités persistées en sortie des contrôleurs (exposition de la structure de la base de données) ou sur le fait de ne pas distinguer entités persistées et objets métiers (je n’ai pas de bon argument pour cette distinction). Les choix de ce projet sont :
- Il ne faut pas faire de distinction entre une entité persistée et un objet métier. Il est légitime de développer une méthode intelligente dans une classe mappée avec Hibernate si cela a du sens.
- un objet métier peut être renvoyé en sortie d’une API.
D’autres noms réservés de package et d’autres règles de nommage existent. Elles sont décrites dans le chapitre 3.21.2 Règles de nommage
2.2.4 - Gestion de la configuration
La configuration des applications (bien que fortement basée sur les paramètres par défaut offerts par Spring) fait l’objet de choix assez particuliers :
- Le projet socle-commun contient tous les fichiers de configuration nécessaires pour faire fonctionner un applicatif métier du socle dans le répertoire src/main/resources (pour être embarqués et disponibles pour les artefacts dépendants de ce projet).
- Chaque fonctionnalité/librairie fait l’objet d’un fichier de configuration différent afin d’en facilité la documentation et la maintenance (log, swagger, jwt, serviceregistry et administration par exemple).
2.2.5 - Séparation de l’application et de ses tests
La séparation des sources applicatives et sources de test est induite par l’utilisation de Maven (documentation officielle). Le principe est double :
- séparer
- l’applicatif dans src/main/
- des tests dans src/test/
- séparer
- le code dans src/xxx/java/
- des ressources dans src/xxx/resources
2.2.6 - le “10mn buld”
La pratique 10mn build (documentation) a pour objectif que la compilation de la solution doit être la plus rapide possible pour que soit le plus court possible le temps entre le push du développeur et la fin de la vérification de la qualité de son code (merci à la PIC
2.2.7 - les logs
Les micro-services pouvant s’appeler entre eux, il n’est pas pertinent de tracer les appels HTTP au niveau de la Gateway (surtout que le faire avec Netty est pénible). Les accessLog sont donc générés au niveau de chacun des micro-services via le fichier de configuration application-accesslog.properties présent dans le projet socle-commun.