L'objectif est de refactorisé ce projet OpenSource. Il est un réseau social de musique.
On commence par faire du refactoring de surface, renaming.
On change quelques noms, BOOM ça casse...
On peut aussi commencer par installer les linters :)
- Problème de lisibilité du code
- Couplage fort entre les couches (On touche un truc ça casse ailleurs)
- Problème de SoC
- Problème au niveau des tests (manque de pertinence et de ciblage, filet de sécu défaillant)
Opacité : Difficile de rentrer dans le code, peu de lisibilité.
Rigidité : On change quelque chose on casse quelque chose d'autres.
Immobilité : Difficile de bouger quelque chose pour faire plus propre.
=> Pourriture logicielle
On a des tests mais attention, ça peut être un piège les tests si ils ne sont pas pertinents.
Il nous faut un filet de sécurité pour pouvoir refactor.
On peut grâce aux tests graver dans le marbre ce que l'on attend de notre app. (APIs requests ?)
=> Approval tests, on va venir définir ce que l'on attend.
On peut d'ailleurs avec une librarie vous les différences entre ce qui était ce que l'on avait avant et maintenant.
Bénéfices :
- Cette technique nous permet de refacto quand on a perdu l'intelligence métier. (Baisse de l'opacité)
- Filet de sécurité (Baisse de la viscosité)
- Ciblage des erreurs (Baisse de l'opacité)
On part des APIs pour voir ce qui en sort, c'est un peu des tests d'inté mais attention ici on devine un peu ce qu'on attend en sortie on le sait pas vraiment. Dans le test d'inté on sait exactement ce que l'on veut en sortie.
On commence donc notre refacto :
- Renommage de variables / de fonction (Baisse de l'opacité)
- Reduction de charge cognitive, un seul niveau d'abstraction (Baisse de l'opacité)
- Extraction dans des méthodes
- Suppression des try/catch pour deal avec des promesses
await new Promise((reseolve) => monModel.createToto())
La solution pour pouvoir travailler les couches de manière indépendante s'appelle : L'architecture Hexagonale. On inverse les dépendances, le domaine ne dépend plus de rien.
Complexité Essentielle / Complexité obligatoire
On travaille sur du petit et on grossit au fur et à mesure.
- On va d'abord faire un passe-plat tout bête, en y intégrant les interfaces et les types métiers, sinon copier/coller de l'existant
- Bon on va essayer déjà de mettre des types d'entrée sorties pour nos interface donc TYPESCRIPT TUTO
Maintenant, il faut faire en sorte que notre domaine ne dépende de rien, on va le découpler de notre BDD.
- On va créer des tests fonctionnels qui vont mettre en avant nos cas métiers (Le cas où on ajoute une musique à une playlist existante, et le cas non existant)
- On va ensuite créer un contrat qui va nous permettre de dialoguer avec la BDD, aller cherche un truc, sauvegarder...
- On ajoute les typages pour le Repository
- On vient mettre à jour les tests fonctionnels en utilisant les nouvelles fonctions écrites, et utilisation de stub pour stuber les repositories
On arrive donc à ça :
On voit bien qu'on ne sort pas du domaine, c'est assez cyclique. D'ailleurs pour le moment il n'est pas connecté au reste du monde.
On voit aussi la dépendance avec le Stub.
On a donc :
- Créer des tests fonctionnels (Baisse de l'opacité et viscosité)
- Défini et détourer les responsabilités (Baisse de l'opacité, immobilité et viscosité)
- Isolé le domaine (Baisse de la rigidité et de la fragilité)
- Typé, grâce à JsDOC (Baisse de l'opacité, fragilité et viscosité)
- Création d'un repository infrastructure, création de la
collection
(car ici mongo) - On type de repository avec l'interface Repository définie dans le domaine et on défini les méthodes
- On lance les tests approvals pour voir si on a bien cablé
- Création du type qui va représenter ce que l'on aura en BDD, en Mongo des objets
Document
- On rempli les fonctions qui sont défini avec le contrat du domaine, et on créer les Mappers qui vont transformer les Documents en objets métier
- On migre la donnée legacy que nous voulons fixer pour mieux la manipuler
On a donc :
- Rendu la structure de données de la persistence explicite (Baisse de l'opacité et viscosité)
- Mis en place l'anti corruption layer (Baisse de la fragilité, rigidité et viscosité)
- Externalisé la migration de données (Baisse de la fragilité, rigidité et viscosité)
- Injection des dépendances pour le framework (Nest ou Spring, dans l'application souvent)
On a donc :
- Découplé les différentes couches, controller, domaine, persistance | Composition Root (Application) (Baisse de l'immobilité et la rigidité)
Suppression des Approvals tests et créer des tests sur les controllers et la couche persistance.