Donc, probablement comme beaucoup, je me trouve souvent dans des maux de tête avec des problèmes de conception dans lesquels, par exemple, il existe un modèle/approche de conception qui semble convaincu de manière intuitive le problème et a souhaité des avantages. Très souvent, il y a une certaine mise en garde qui rend difficile la mise en œuvre du modèle/de l'approche sans une sorte de travail autour qui annule ensuite l'avantage du modèle/de l'approche. Je peux très facilement me mettre facilement en itération à travers de nombreux schémas/approches, car de manière prévisible, presque tous ont des mises en garde très importantes dans des situations du monde réel dans lesquelles il n'ya tout simplement pas une solution facile.
Je vais vous donner un exemple hypothétique basé sur un vrai sur une vraie que j'ai récemment rencontrée. Disons que je souhaite utiliser la composition sur l'héritage, car les héritiers d'héritage ont entravé la fluidification du code dans le passé. Je pourrais refroidir le code, mais constatez ensuite qu'il existe des contextes où la superclasse/base de base doit simplement appeler la fonctionnalité sur la sous-classe, malgré les tentatives de l'éviter.
La meilleure approche semble mettre en œuvre un modèle de délégué-moitié-délégué/observateur et demi-composition de manière à ce que la superclasse puisse déléguer un comportement ou de manière à ce que la sous-classe puisse observer des événements de super-classes. Ensuite, la classe est moins évolutive et maintenue, car il est difficile de savoir comment il devrait être prolongé, il est également difficile d'étendre les auditeurs/délégués existants. Les informations ne sont pas bien cachées parce qu'on commence à avoir besoin de connaître la mise en œuvre pour savoir comment prolonger la superclasse (à moins que vous n'utilisiez des commentaires très approfondis).
Ainsi, après cela, je pourrais choisir simplement d'utiliser simplement des observateurs ou des délégués complètement pour vous éloigner des inconvénients liés à la combinaison des approches à fortement. Cependant, cela vient avec ses propres problèmes. Par exemple, je pourrais constater que je finirai par avoir besoin d'observateurs ou de délégués pour un comportement croissant jusqu'à ce que je puisse avoir besoin d'observateurs/délégués pour pratiquement tous les comportements. Une option pourrait être de simplement avoir un grand auditeur/délégué pour tout le comportement, mais la classe d'exécution finit alors avec beaucoup de méthodes vides, etc.
Ensuite, je pourrais essayer une autre approche, mais il y a juste autant de problèmes avec cela. Puis le prochain, et celui après etc.
Ce processus itératif devient très difficile lorsque chaque approche semble avoir autant de problèmes que l'un des autres et conduit à une sorte de paralysie de décision de conception. Il est également difficile d'accepter que le code se retrouve également problématique, quel que soit le modèle de conception ou une approche. Si je me retrouve dans cette situation, cela signifie-t-il que le problème lui-même doit être repensé? Que font les autres quand ils rencontrent cette situation?
Edit : Il semble y avoir un certain nombre d'interprétations de la question que je veux effacer:
La situation que vous décrivez ressemble à une approche ascendante. Vous prenez une feuille, essayez de le réparer et de savoir qu'il est connecté à une branche qui elle est également connectée à une autre branche, etc.
C'est comme essayer de construire une voiture commençant par un pneu.
Ce dont vous avez besoin, c'est de prendre un pas en arrière et de regarder la plus grande image. Comment cette feuille est-elle assis dans la conception générale? Est-ce toujours actuel et correct?
Comment le module ressemblerait-t-il si vous le concevez et le mettre en œuvre à partir de zéro? À quelle distance de cet "idéal" est votre mise en œuvre actuelle.
De cette façon, vous avez une image plus grande de quoi travailler. (Ou si vous décidez que c'est trop de travail, quelles sont les problèmes).
Votre exemple décrit une situation qui se présente généralement avec des morceaux de code legacy plus grandes et lorsque vous essayez de faire un refactoring "trop gros".
Le meilleur conseil que je puisse vous donner pour cette situation est:
N'essayez pas d'atteindre votre objectif principal dans un "Big Bang" ,
Découvrez comment améliorer votre code en petites étapes!
Bien sûr, cela est plus facile écrit que fait, alors comment accomplir cela en réalité? Eh bien, vous avez besoin d'une pratique et d'une expérience, cela dépend beaucoup de l'affaire et il n'y a pas de règle durement et rapide qui dit "faire cela-ou-qui" qui convient à tous les cas. Mais laissez-moi utiliser votre exemple hypothétique. "Composition-Over-héritage" n'est pas un objectif de conception tout ou-rien, c'est un candidat parfait à atteindre dans plusieurs petites étapes.
Disons que vous avez remarqué "la composition-over-héritage" est le bon outil pour le cas. Il doit y avoir des indications pour cela être un objectif sensible, sinon vous n'auriez pas choisi ceci. Supposons donc qu'il y a beaucoup de fonctionnalités dans la superclasse qui est simplement "appelée" des sous-classes. Cette fonctionnalité est donc candidate à ne pas rester dans cette superclasse.
Si vous remarquez que vous ne pouvez pas supprimer immédiatement la superclasse des sous-classes, vous pouvez commencer par commencer à refactoriser la superclasse en composants plus petits encapsulant les fonctionnalités mentionnées ci-dessus. Commencez par les fruits suspendus les plus bas, extrayez d'abord certains composants simples, ce qui rendra votre superclasse moins complexe. Plus la superclasse est petite, plus les refactorings supplémentaires deviendront plus faciles. Utilisez ces composants des sous-classes ainsi que de la superclasse.
Si vous avez de la chance, le code restant dans la superclasse deviendra si simple tout au long de ce processus que vous pouvez supprimer la superclasse des sous-classes sans autre problème. Ou, vous remarquerez que garder la superclasse n'est plus un problème, car vous avez déjà extrait suffisamment le code dans des composants que vous souhaitez réutiliser sans héritage.
Si vous ne savez pas où commencer, car vous ne savez pas si un refactoring se révélera simple, la meilleure approche est parfois de faire un peu refactoring de rayures .
Bien sûr, votre situation réelle pourrait être plus compliquée. Alors apprenez, rassemblez-vous et soyez patient, ce droit prend des années. Il y a deux livres que je peux recommander ici, peut-être que vous les trouvez utiles:
refactoring par Fowler: décrit un catalogue complet de de très petits refactorings.
Travailler efficacement avec le code hérité Par plumes: donne un excellent conseil comment gérer de gros morceaux de code mal conçu et le rendre plus testable dans des étapes plus petites
Quand je suis dans cette situation, la première chose que je fais est d'arrêter. Je passe à un autre problème et je travaille sur cela pendant un moment. Peut-être une heure, peut-être une journée, peut-être plus. Ce n'est pas toujours une option, mais mon subconscient travaillera sur des choses pendant que mon cerveau conscient fait quelque chose de plus productif. Finalement, je reviens avec des yeux frais et j'essaie à nouveau.
Une autre chose que je fais est de demander à quelqu'un plus intelligent que moi. Cela peut prendre la forme de demander l'échange de piles, de lire un article sur le Web sur le sujet ou de demander à un collègue qui a plus d'expérience dans ce domaine. Souvent, la méthode que je pense est la bonne approche s'avère complètement fausse pour ce que je tente de faire. J'ai mal maîtrisé un aspect du problème et cela ne convient pas au motif que je pense. Quand cela se produit, avoir quelqu'un d'autre dire: "Vous savez, cela ressemble plus à ..." peut être une grande aide.
Liée à ce qui précède est la conception ou le débogage par des aveux. Vous allez chez un collègue et dites: "Je vais vous dire le problème que je vais avoir, puis je vais vous expliquer les solutions que j'ai. Vous soulignez les problèmes dans chaque approche et suggérez d'autres approches . " Souvent avant même que l'autre personne ne parle même, comme je l'explique, je commence à réaliser qu'un chemin qui semblait égal à d'autres est beaucoup mieux meilleur ou pire que je ne le pensais à l'origine. La conversation résultante peut soit renforcer cette perception, soit indiquer de nouvelles choses que je n'avais pas pensées.
Donc, TL; DR: Faites une pause, ne forcez pas cela, demandez de l'aide.