Je suis assez nouveau sur les principes de conception SOLID . Je comprends leur cause et leurs avantages, mais je n'arrive pas à les appliquer à un projet plus petit que je souhaite refactoriser comme un exercice pratique pour utiliser les principes SOLIDES. Je sais qu'il n'est pas nécessaire de changer une application qui fonctionne parfaitement, mais je veux quand même la refactoriser afin d'acquérir une expérience de conception pour de futurs projets.
L'application a la tâche suivante (en fait beaucoup plus que cela mais restons simple): elle doit lire un fichier XML qui contient les définitions de table / colonne / vue etc. de la base de données et créer un fichier SQL qui peut être utilisé pour créer un schéma de base de données ORACLE.
(Remarque: veuillez vous abstenir de discuter des raisons pour lesquelles j'en ai besoin ou pourquoi je n'utilise pas XSLT et ainsi de suite, il y a des raisons, mais elles sont hors sujet.)
Pour commencer, j'ai choisi de ne regarder que les tableaux et les contraintes. Si vous ignorez les colonnes, vous pouvez le déclarer de la manière suivante:
Une contrainte fait partie d'une table (ou plus précisément, fait partie d'une instruction CREATE TABLE), et une contrainte peut également référencer une autre table.
Tout d'abord, je vais expliquer à quoi ressemble l'application en ce moment (sans appliquer SOLID):
À l'heure actuelle, l'application possède une classe "Table" qui contient une liste de pointeurs vers des contraintes appartenant à la table et une liste de pointeurs vers des contraintes faisant référence à cette table. Chaque fois qu'une connexion est établie, la connexion arrière sera également établie. La table a une méthode createStatement () qui à son tour appelle la fonction createStatement () de chaque contrainte. Cette méthode utilisera elle-même les connexions à la table propriétaire et à la table référencée afin de récupérer leurs noms.
Évidemment, cela ne s'applique pas du tout à SOLID. Par exemple, il existe des dépendances circulaires, qui gonflent le code en termes de méthodes "ajouter" / "supprimer" requises et de certains destructeurs d'objets volumineux.
Il y a donc quelques questions:
- Dois-je résoudre les dépendances circulaires à l'aide de l'injection de dépendances? Si c'est le cas, je suppose que la contrainte doit recevoir le propriétaire (et éventuellement la table référencée) dans son constructeur. Mais comment pourrais-je alors parcourir la liste des contraintes pour une seule table?
- Si la classe Table enregistre à la fois son état (par exemple, nom de table, commentaire de table, etc.) et les liens vers les contraintes, s'agit-il d'une ou deux "responsabilités", en pensant au principe de responsabilité unique?
- Dans le cas 2. a raison, dois-je simplement créer une nouvelle classe dans la couche métier logique qui gère les liens? Dans l'affirmative, 1. ne serait évidemment plus pertinent.
- Les méthodes "createStatement" doivent-elles faire partie des classes Table / Contrainte ou dois-je également les déplacer? Si oui, où? Une classe Manager pour chaque classe de stockage de données (ie Table, Contrainte, ...)? Ou plutôt créer une classe de gestionnaire par lien (similaire à 3.)?
Chaque fois que j'essaie de répondre à l'une de ces questions, je me retrouve à tourner en rond quelque part.
Le problème devient évidemment beaucoup plus complexe si vous incluez des colonnes, des index et ainsi de suite, mais si vous m'aidez avec la simple chose Table / Contrainte, je peux peut-être résoudre le reste par moi-même.