Combien d'efforts dois-je investir pour créer des conceptions à couplage lâche?

10

J'apprends actuellement sur les modèles de conception.

Je pense que la plupart des gens conviendraient que ces modèles sont d'excellents outils, mais devraient être utilisés avec modération et non comme réponse à tout. Les utiliser trop compliquerait trop l'application avec peu d'avantages. Les modèles ne doivent être utilisés que lorsqu'ils peuvent être la meilleure solution ou aider à la création d'une bonne solution (êtes-vous d'accord?).

Avec ça en tête:

Le livre que je lis (Head First Design Patterns) souligne fréquemment l'importance du couplage lâche . Ce couplage lâche est obtenu en suivant des principes tels que «programmer vers une interface, pas une implémentation» et «encapsuler ce qui varie».

Fondamentalement, la plupart des modèles que j'ai appris jusqu'à présent existent principalement pour permettre aux conceptions d'être couplées de manière lâche et donc plus flexibles.

Je comprends l'importance et les avantages d'un couplage lâche.

Mais ma question est, combien d'efforts doit-on réellement investir pour créer des conceptions flexibles à couplage lâche?

Ceux qui s'opposent aux modèles de conception affirment que les coûts d'utilisation de ces modèles l'emportent souvent sur les avantages. Vous investissez beaucoup de temps dans la création d'une conception à couplage lâche à l'aide d'un modèle, alors qu'en réalité - le couplage lâche, la `` programmation sur une interface, pas une implémentation '', et tous ces principes - pourraient ne pas être réellement si importants.

Ce que j'aimerais savoir, c'est combien d'efforts devrais-je réellement consacrer à la création de niveaux supplémentaires d'abstraction et de conceptions, uniquement pour permettre à mon application de suivre les principes OO tels que le couplage lâche, la programmation à une interface, etc. il? Combien d'efforts dois-je y consacrer?

Aviv Cohn
la source
Certaines personnes y mettent toute leur vie, Kent Beck par exemple, des gens qui l'apprécient verraient vos efforts.
Niing

Réponses:

14

Réponse fatale: plus vous le faites, moins d'efforts.

Fondamentalement, la construction de code faiblement couplé n'est pas vraiment très difficile. Former votre esprit à penser en termes de couplage lâche, d'autre part, l'est. Et bien, je pense que cela en vaut la peine.

Supposons que vous preniez un travail qui utilise une approche itérative du développement logiciel, comme cela a été recommandé par la plupart des gens au cours des 20 dernières années. Vous construisez quelque chose qui fonctionne à merveille dans l'itération 1. Dans l'itération 2, vous construisez par-dessus, en ajoutant de nouvelles fonctionnalités et en pliant un peu une ou deux choses quand elles ne correspondent pas à votre concept d'itération 1 sur la façon dont les choses devraient fonctionner . Vient maintenant l'itération 3, et vous découvrez les exigences qui vous demandent de repenser votre architecture de base. Comment déchirer votre code et le reconstruire sans revenir à la case départ?

Ça arrive. Beaucoup. Soit cela rend les projets en retard, soit tout le monde a trop peur de faire ce qui doit être fait dans les itérations ultérieures. Dans le meilleur des cas, vous obtenez une grosse boule de boue. Des choses comme le couplage lâche et le principe de responsabilité unique atténuent considérablement ces problèmes. C'est pourquoi les principes SOLIDES sont vantés - ils aident vraiment.

Et vous constaterez qu'après avoir quelques conceptions faiblement couplées sous votre ceinture, cela commence à venir naturellement. Les modèles sont des choses que les gens ont trouvées qui ont fonctionné pour eux, ils les ont donc documentés. Ce sont des outils utiles qui viennent aussi naturellement avec le temps.

Matthew Flynn
la source
5

L'effort requis ne vous en dira pas toujours assez; Je pense qu'une meilleure mesure serait le rapport effort / rendement. Mais déterminer quel pourrait être le gain n'est pas toujours simple et sans erreur.

La chose à garder à l'esprit avec les modèles qui augmentent la flexibilité est que cela coûte un certain effort pour les mettre en place, et à moins que vous ne puissiez voir exactement pourquoi vous en avez besoin, vous pouvez finir par avoir la complication dans le code, mais ne jamais l'utiliser. Si la flexibilité n'est jamais fléchie, elle pourrait tout aussi bien ne pas être là.

Il y a une chose que vous devez toujours faire (ou aussi près que possible): transformer les composants individuels de votre logiciel (objets pour la POO, fonctions pour la programmation fonctionnelle ou procédurale) en boîtes noires. Une boîte noire est quelque chose dont nous ne connaissons pas ou ne nous soucions pas (mise en œuvre).

Si nous ne savons pas ou comment nous nous soucions de son fonctionnement, nous n'allons pas essayer d'utiliser autre chose que l'interface, donc si l'implémentation change sans changer l'interface, cela n'a d'importance que dans la boîte noire - rien en dehors peut être affecté. Cela facilite également la réflexion sur le programme, car vous n'avez pas à garder dans votre tête tous les détails de l'ensemble du programme. Plus vous pouvez légitimement oublier les détails, plus vous avez de place dans la tête pour les détails qui comptent.

Je pense que vous avez mal compris les objections aux modèles de conception; Je ne suis pas fan d'eux, mais j'aime beaucoup le principe du couplage lâche et de la programmation d'une interface. Ma plus grande objection à leur égard est qu'ils sont présentés comme une solution préemballée qui n'encourage pas à comprendre les principes qui les sous-tendent, mais encourage plutôt la mémorisation des détails. Je ne vais pas recommander que vous ne les étudiez pas, mais lorsque vous le faites, rappelez-vous que la compréhension des principes qui les sous-tendent est plus importante que les spécificités d'un modèle particulier.

L'une des objections aux modèles de conception est qu'ils sont «évidents» ou que «je les utilisais avant d'en entendre parler, mais pas sous ce nom». La raison pour laquelle les gens peuvent émettre ces objections, ou que les concepteurs de modèles de conception peuvent les proposer en premier lieu, c'est qu'ils ont compris les principes qui les sous-tendent.

L'utilisation de boîtes noires organise votre code d'une manière sensée et elles ne coûtent généralement pas beaucoup (le cas échéant); utilisez-les partout. L'utilisation d'un modèle de conception ou d'une autre technique qui ajoute une couche d'abstraction ou complique les choses a un coût; ne les utilisez jamais simplement parce qu'ils sont jolis, soignés ou intelligents; utilisez-les quand elles correspondent au problème et que le coût en vaut la peine pour en bénéficier.

Michael Shaw
la source
4

Votre question semble associer un couplage lâche avec des modèles de conception, mais ce sont vraiment des choses distinctes mais liées.

Le couplage lâche est une préoccupation fondamentale dans la programmation. Dès que nous nous sommes éloignés du code machine pour passer aux langages symboliques, les programmes se sont associés de manière lâche à leur exécution. Etc.

L'OO lui-même est fondamentalement un modèle pour créer des composants à couplage lâche. L'encapsulation rend les éléments internes des objets faiblement couplés avec d'autres objets. La programmation fonctionnelle l'est peut-être encore plus, car l'exécution des fonctions est vaguement couplée à l'exécution d'autres fonctions à l'extrême.

Presque par définition, toute conception que vous réalisez impliquera un couplage lâche. Il y a des façons que vous pouvez organiser pour que les choses soient étroitement couplées par inadvertance, mais je n'ai vu que quelques cas où quelqu'un a réellement conçu un système pour être plus étroitement couplé.

(De temps en temps, je travaille avec quelqu'un qui veut empêcher les futurs développeurs de faire des choix de conception en incorporant des références statiques à des artefacts de framework particuliers, forçant leur utilisation - exprès. Mais c'est vraiment l'exception. et réutiliser dans de nombreux contextes.)

Rob
la source
3

Les modèles ne doivent être utilisés que lorsqu'ils peuvent être la meilleure solution ou aider à la création d'une bonne solution (êtes-vous d'accord?).

Je vois les modèles de conception strictement comme des détails d'implémentation. Si vous documentez vos API publiques et votre programme dans cette documentation, en général, peu importe (ou vous affectera beaucoup) où vous avez des modèles de conception. Autrement dit, vous n'allez pas "J'ai un modèle de pont ici, et je vais implémenter un visiteur en plus". Au lieu de cela, c'est "cette classe aura différentes implémentations sur différents systèmes d'exploitation, donc elle sera implémentée en utilisant un modèle de pont". Ensuite, lorsque vous l'utilisez, vous êtes indifférent à sa mise en œuvre en tant que pont - car vous regardez l'API publique, pas un modèle de pont.

combien d'efforts doit-on réellement investir pour créer des conceptions flexibles à couplage lâche?

Un couplage lâche peut être obtenu en suivant un ensemble simple de règles. Si vous les respectez, votre code sera (plus) faiblement couplé au fur et à mesure que vous l'écrivez (c'est-à-dire que tout effort fait déjà partie du processus de développement).

Parmi les règles (liste non exhaustive):

  • définir vos interfaces en pensant (ou en écrivant) le code client (comment la classe sera utilisée), pas ce que la classe fera (c'est-à-dire concevoir l'interface, pas l'implémentation)
  • "dis, ne demande pas"
  • construire des objets à partir de pièces déjà créées
  • passez dans le constructeur les objets réels que vous utiliserez (pas les usines pour les membres, les paramètres pour les usines des paramètres, ou quelque chose comme ça).
  • SEC (si vous avez deux lignes qui apparaissent dans le même ordre à deux endroits, extrayez-les dans une fonction distincte et ainsi de suite).
  • Si la création d'un objet est une opération plus complexe, implémentez la création des pièces intermédiaires en tant que méthode / classe d'usine (c'est-à-dire pas dans le corps du constructeur).
  • YAGNI (créez des choses comme vous en avez besoin, pas avant).

Ces règles sont suivies différemment, selon la langue, la méthodologie de développement suivie par votre équipe (par exemple TDD), les contraintes de budget temps, etc.

Par exemple, en Java, il est recommandé de définir votre interface en tant que interfaceet d'écrire du code client dessus (puis instancier l'interface avec une classe d'implémentation).

En C ++ d'autre part, vous n'avez pas d'interfaces, vous ne pouvez donc écrire que l'interface en tant que classe de base abstraite; Étant donné qu'en C ++ vous n'utilisez l'héritage que lorsque vous en avez une forte exigence (et évitez ainsi la surcharge de fonctions virtuelles inutiles), vous ne définirez probablement pas l'interface séparément, juste l'en-tête de classe).

Ceux qui s'opposent aux modèles de conception affirment que les coûts d'utilisation de ces modèles l'emportent souvent sur les avantages.

Je pense qu'ils le font mal. Si vous écrivez du code faiblement couplé (et SEC), l'intégration de modèles de conception dans celui-ci entraîne un effort supplémentaire minimal. Sinon, vous devrez adapter votre code pour implémenter un modèle de conception.

Si vous devez apporter de nombreuses modifications pour implémenter un modèle de conception, votre problème n'est pas le modèle de conception - c'est votre base de code étant monolithique et étroitement couplée. Il s'agit d'un problème de conception incorrect / sous-optimal, pas d'un problème de modèles de conception.

Ce que j'aimerais savoir, c'est combien d'efforts devrais-je réellement consacrer à la création de niveaux supplémentaires d'abstraction et de conceptions, uniquement pour permettre à mon application de suivre les principes OO tels que le couplage lâche, la programmation à une interface, etc. il? Combien d'efforts dois-je y consacrer?

Vos questions supposent (non déclaré) que le seul avantage du couplage lâche est la possibilité de mettre en œuvre facilement des modèles de conception. Ce n'est pas.

Parmi les avantages du couplage lâche, citons:

  • refactorisation et refonte de la flexibilité
  • moins d'efforts gaspillés
  • testabilité
  • possibilité accrue de réutiliser le code
  • simplicité de conception
  • moins de temps passé dans le débogueur

... et quelques autres qui ne me viennent pas à l'esprit en ce moment.

utnapistim
la source