Outils de conception indispensables pour les développeurs juniors qui souhaitent aller au-delà du CRUD
Vous avez terminé vos fonctionnalités CRUD, mais le moment redouté de la maintenance arrive. Prendre l'habitude de commencer par la conception des tables finit par complexifier le système. Cet article présente une méthodologie concrète pour séparer le code par domaine et standardiser l'environnement afin de limiter le périmètre des modifications.
Augmenter la cohésion du code : Séparation entre accès aux données et logique
Si la logique métier est mélangée au contrôleur, chaque changement dans la structure de la base de données vous obligera à réécrire tout le code. Adoptez une architecture en couches (Layered Architecture) pour isoler les deux. Cela peut réduire le temps de maintenance de votre base de code d'environ 40 %.
Les étapes pour séparer l'accès aux données de la logique sont les suivantes :
- Déplacez le code de validation du contrôleur vers un DTO de requête et utilisez des annotations de validation.
- Rassemblez la logique éparpillée dans les scripts de transaction à l'intérieur des méthodes des entités de domaine.
- Au lieu d'utiliser des pilotes de base de données concrets, déclarez des interfaces définissant les comportements de persistance afin de les isoler de la couche domaine.
Même si le schéma d'une table spécifique change, les règles métier fondamentales restent inchangées.
Créer un environnement de test avec l'injection de dépendances
Si vous créez des objets directement avec l'opérateur new à l'intérieur d'une classe, les tests unitaires deviennent impossibles. Réalisez l'inversion de contrôle (IoC) pour effectuer des tests indépendants avec des objets simulés (Mock) sans serveur externe.
Voici la procédure pratique pour augmenter l'efficacité des tests :
- Déclarez les collaborateurs utilisés par l'objet via des interfaces plutôt que des classes concrètes.
- Configurez le conteneur externe pour injecter l'implémentation appropriée au moment de l'exécution.
- Utilisez des outils comme
@automock/jest pour automatiser la configuration des doublures de test.
Grâce à cette structure, vous pouvez améliorer la vitesse d'exécution des tests de plus de 20 %.
Isoler les entités des DTO
Si vous faites correspondre la structure de l'interface utilisateur aux tables de la base de données un par un, vous devrez modifier le schéma de la DB à chaque changement d'écran. Séparez strictement les DTO destinés aux messages réseau des entités de domaine.
Voici comment isoler les deux en utilisant des mappers :
- Créez des classes de mapper pures dédiées uniquement à la conversion des données.
- Transférez les données uniquement à l'intérieur du mapper pour éviter une dépendance directe entre le DTO et l'entité.
- Forcez la couche de service à n'utiliser que des entités.
Même si vous remplacez le stockage de données, aucune modification de logique ne sera nécessaire.
Aligner l'environnement de développement avec Docker Compose
Si l'environnement local diffère selon le développeur, la collaboration s'arrête. Synchronisez les environnements en écrivant l'infrastructure sous forme de code avec Docker Compose.
La procédure pour créer un environnement standard :
- Spécifiez la version de la base de données, du serveur de cache et les variables d'environnement dans le fichier
docker-compose.yml.
- Placez le SQL du schéma initial dans le répertoire
/docker-point-initdb.d via un montage de volume.
- Utilisez un gestionnaire de paquets comme
pnpm Workspaces pour éviter les enchevêtrements de dépendances.
Une fois cette configuration terminée, vous pouvez lancer une infrastructure standard en moins de 3 secondes sans vous soucier de la configuration de votre machine locale.
Modéliser le domaine avant de concevoir les tables
Si vous commencez par dessiner l'ERD, vous n'obtiendrez qu'une logique fragmentée centrée sur les données. Chez Shopify, plus de 800 ingénieurs ont abandonné l'héritage centré sur le schéma physique pour passer à une modélisation centrée sur les objets métier.
Les étapes pour commencer la modélisation de domaine :
- Listez les noms et verbes principaux du domaine en vous basant sur les cas d'utilisation (use cases) et le langage ubiquitaire.
- Définissez les entités qui nécessitent une transition d'état et les objets de valeur (Value Objects) ayant des attributs immuables.
- Déterminez les racines d'agrégat (Aggregate Roots) pour vérifier l'intégrité métier par unité de transaction.
Cette approche permet de contenir la portée des modifications au sein d'un module spécifique, même si les exigences changent. La conception de systèmes complexes est l'alternative la plus pratique pour dissiper le sentiment d'impuissance.