Je viens de lire le lien de l'article que vous avez publié, je dois dire que Fowler a fait de très bons points et beaucoup de choses qu'il a dit, je plaide avec notre équipe depuis des années.
OMI, si vous faites une conception décente, vous ne devriez pas entrer dans ce qui serait considéré comme une situation sans issue. J'ai toujours considéré les logiciels comme des éléments constitutifs . Je crois toujours en une conception initiale, mais l'objectif principal n'est pas de concevoir le produit dans son ensemble, mais de fournir une architecture / direction globale afin que votre équipe puisse visualiser une image commune vers laquelle nous travaillons tous. Si vous avez un tas de morceaux de cube et de triangle, il est utile d'esquisser la façon dont un château serait assemblé avant de commencer à gifler les morceaux ensemble.
Puisque je viens de la terre OO, pour moi chaque bloc est une classe et la surface de ce bloc est l'interface publique (ce qui est visible par les classes externes ou dérivantes). Si vous suivez les bons principes SOLID, vous vous assurerez que chaque bloc est extrêmement simple et dispose d'une interface publique intuitive. Pour en revenir à mon analogie, vous voulez vous assurer que le code ne crée que des formes simples. Chaque fois que vous créez des classes trop complexes (beaucoup de fonctions, beaucoup de variables), vous créez des formes qui sont difficiles à réutiliser quand les exigences changent.
Je suis d'accord avec Fowler en ce que le plus grand risque / défi pour la conception évolutive est que vous laissez les décisions de conception au temps de codage, et vous vous attendez à ce que chaque développeur individuel prenne ces décisions. C'est là que le système peut tomber en panne si vous n'avez pas de mécanismes de rétroaction appropriés en place. Chaque fois qu'une nouvelle fonctionnalité est demandée, il est extrêmement tentant de simplement trouver la fonction qui doit être étendue, de mettre une sorte de condition à l'intérieur et d'ajouter simplement un tas de code à l'intérieur de cette fonction. Et parfois, c'est peut-être tout ce dont vous avez besoin, mais c'est aussi (IMO) la pratique la plus courante qui conduit à des composants sans issue. Cela n'a rien à voir avec la conception évolutive. C'est ce qu'on appelle "pas de conception".
Tant que vous prenez le temps de prendre du recul et de dire, attendez une minute, cette classe a déjà 15 variables membres, laissez-moi en extraire 6 et les mettre dans leur propre classe autonome, votre logiciel sera composé de très léger -blocs de construction légers, flexibles et réutilisables. Bien sûr, si les PM arrivent et modifient la moitié des exigences de produits pour vous, vous devrez peut-être retirer certains de vos blocs, les remettre sur l'étagère et en dessiner de nouveaux (tout comme lors de la construction d'un château, vous ne pouvez pas utiliser tous vos cylindres). Mais à ce stade, cela ne fait que faire partie des affaires. Les exigences ont changé et en gardant votre code flexible et modulaire, vous devriez pouvoir changer votre produit pour l'aligner avec votre nouvelle direction commerciale.
Je crois que cette approche évolutive de la conception fonctionne avec tous les niveaux de compétence de l'ingénieur. Personnellement, je fais du logiciel depuis très longtemps et avant que notre équipe ne passe à une méthodologie agile, j'étais responsable de l'expédition de plusieurs composants majeurs de mon PC de développement presque directement au client avec pratiquement aucun contrôle qualité. En même temps, ces composants sont toujours restés flexibles et maintenables.
J'essaie seulement de dire que je me considérerais relativement décent dans la conception de logiciels. En même temps, si vous me demandiez de rédiger un document de conception de 100 pages, de le donner à un codeur et de s'attendre à ce qu'il fonctionne, je ne pourrais probablement pas me concevoir à partir d'un sac en papier. Au début du travail, je dessinais parfois quelques diagrammes de type UML (très simplifié, pas en langage complet), mais lorsque je commence à coder, je refactoriserais selon les besoins et mon code final ne ressemblerait jamais à ce que j'avais dessiné à l'origine. Même si je passe un mois ou deux à penser à chaque petit détail, je ne peux pas imaginer que quelqu'un d'autre puisse prendre mes diagrammes et proposer un logiciel solide sans modifier la conception pendant le codage.
À l'autre bout du spectre, actuellement dans mon équipe (maintenant agile et je soutiens pleinement cela), nous avons quelques gars qui nous ont rejoints depuis un terrain intégré où ils n'ont fait que du C pendant les 15 dernières années. J'ai évidemment aidé à la planification initiale et à l'organisation des cours, mais je me suis également assuré de faire un suivi avec des révisions de code régulières et des séances de remue-méninges où nous discutons des applications de SOLID et des principes de conception. Ils ont produit du code de spaghetti qui m'a fait un peu grincer des dents, mais avec juste un petit coup de pouce de ma part, ils ont commencé à refactoriser ce qui était déjà produit et la partie drôle est que l'un d'eux est revenu quelques jours plus tard et dit, je déteste pour le dire, mais après avoir déplacé ce code, cela semble beaucoup plus lisible et compréhensible. Impasse évitée. Point I ' Ce que j'essaie de faire, c'est que même quelqu'un qui est complètement nouveau à OO peut produire du code quelque peu décent, tant qu'il a un mentor avec plus d'expérience, pour lui rappeler que «conception évolutive» n'est pas la même chose que «pas de conception». Et même certaines de ses classes "plus complexes" ne sont pas si effrayantes parce que chaque classe n'a pas beaucoup de responsabilité (c'est-à-dire pas beaucoup de code), donc le pire devient pire, si cette classe "cul-de-sac", nous jetez-le et écrivez une classe de remplacement qui a la même interface publique (jusqu'à présent, je n'ai jamais vu un besoin de cette contingence dans tout ce que nous avons écrit et j'ai fait des révisions de code deux fois par semaine).
Pour terminer, je suis également un fervent partisan des documents de conception (au moins pour les conditions commerciales de mon équipe actuelle), mais l'objectif principal de nos documents de conception est la mémoire organisationnelle , de sorte que les documents réels sont écrits après la production du code et refactorisé. Avant le codage, nous avons généralement une phase de conception rapide (parfois moins rapide) où nous esquissons des cours sur des serviettes / mspaint / visio et je rappelle toujours aux gens que cette phase produit un chemin à suivre, pas un plan directeur et lorsqu'ils commencent à coder, tout ce qui n'a pas de sens devrait être changé. Même avec ces rappels, les nouveaux gars ont tendance à essayer de remettre le code en forme dans le design original, même si cela ne leur semble pas naturel. Cela apparaît généralement dans les revues de code.
Dang, j'ai beaucoup écrit. Désolé pour ça.
Je dirais que le phénomène "impasse de conception" est orthogonal aux méthodes agiles. Ce que je veux dire, c'est qu'il est possible de faire de la cascade, de passer beaucoup de temps à l'avance sur un (mauvais) design. Ensuite, passez beaucoup de temps à le mettre en œuvre pour vous retrouver dans une impasse.
Si quoi que ce soit, les méthodes agiles devraient vous aider à découvrir plus tôt que vous avez fait de mauvais choix de conception. La raison en est que votre carnet de commandes doit avoir les éléments de valeur client les plus élevés en premier et que vous devez vous concentrer sur la fourniture d'incréments utiles du logiciel. Si votre conception vous permet de fournir une valeur et une utilité élevées, c'est déjà bon pour quelque chose :-) En revanche, vous pourriez avoir une mauvaise conception dans une situation de cascade où vous ne découvrirez peut-être pas pendant de nombreuses années que cette conception ne peut pas fournir toute valeur et toute utilité - tout ce que vous avez, c'est l'illusion qu'il s'agit d'un bon design. Comme on dit, la preuve est dans le pudding.
Le revers de la médaille est que même dans les méthodes agiles, il est important d'avoir une vision viable de la conception du système qui guide les décisions d'itération en itération. Je pense que Ken Schwabber a dit quelque chose comme si vous avez une équipe de développeurs terribles, ils produiront les mauvais logiciels de manière cohérente itération par itération. Agile signifie simplement que vous ne passez pas beaucoup de temps à l'avance car vous êtes limité dans ce que vous pouvez apprendre ou imaginer avant de commencer à mettre en œuvre ( et les exigences changent également). Cependant, il y a des situations où vous devez faire un travail initial (par exemple la recherche) et ensuite vous devez le faire.
Comment éviter les impasses?
Je dirais surtout en anticipant les besoins futurs. C'est quelque chose que vous obtenez avec l'expérience et la familiarité avec des projets / produits similaires. Cette anticipation est en partie ce qui vous aide à mettre en place une bonne conception, car vous vous posez beaucoup de questions «et si» sur votre système actuel. Pour moi, c'est l'élément essentiel. Des techniques comme OO vous aident simplement lorsque vous savez déjà ce que vous faites.
Que faites-vous si vous avez une impasse?
Une « impasse » est pas différent de tout autre bloc technique , vous serez frappé pendant le développement de tout ce qui est nouveau. La première chose à réaliser est qu'il n'y a vraiment pas de véritables "impasses" qui vous obligent à revenir en arrière complètement. À tout le moins, c'est votre apprentissage jusqu'à ce point qui vous permet d'avancer afin que l'effort ne soit pas gaspillé. Lorsque vous frappez une impasse, vous avez un problème . Le problème est de savoir ce qui doit changer pour répondre à une nouvelle (ou ancienne) exigence et comment optimiser ce changement. Il ne vous reste plus qu'à résoudre ce problème. Soyez reconnaissant qu'il s'agit d'un logiciel et non, par exemple d'une conception d'avion, car le changement est beaucoup plus facile. Identifiez les problèmes, corrigez-les == refactor == génie logiciel. Parfois, beaucoup de travail est impliqué ...
Si vous utilisez Scrum, ce changement doit naturellement être basé sur les user stories (que retire l'utilisateur de ce changement?). Le processus commencerait à partir d'une histoire qui ne peut pas être facilement adaptée à la conception actuelle (oups) et une discussion aurait lieu avec le propriétaire du produit sur la façon de décomposer cette histoire. Vous continuez d'appliquer des principes agiles grâce à ce changement.
Quelques grands changements d'exigences célèbres du monde du système d'exploitation qui me viennent à l'esprit:
Quelle que soit la façon dont vous les voyez, cela représente beaucoup de travail. La conception originale n'a presque certainement pas pris en compte la possibilité que cela se produise (c'est-à-dire que la portailité n'était pas une grande exigence). Que la conception soit OO ou non n'est probablement pas un facteur énorme non plus. Dans une bonne conception, les parties spécifiques de la plate-forme seraient quelque peu isolées et le travail serait plus facile.
la source
Je refaçonne mes projets en permanence et j'utilise également des diagrammes de classes UML. Je veux dire que je crée un ou plusieurs diagrammes de classes par packages. Chaque diagramme est enregistré à la racine du package. Chaque classificateur UML possède un propre ID qui est mappé à l'ID Java associé. Cela signifie que lorsque j'ouvre mon diagramme, il est automatiquement mis à jour avec les dernières modifications de refactorisation de code. Je peux également modifier directement mes diagrammes de classe au niveau graphique et tout mon projet est immédiatement refactorisé. Cela fonctionne plutôt bien mais ne remplacera jamais l'homme. Mon diagramme de classe UML n'est également qu'une vue graphique de mon code. Il est très important de ne pas mélanger le code et le modèle comme le fait l'éclipse EMF car dès que le refactoring est effectué, les informations du modèle sont également perdues. Je n'utilise jamais de générateur de code Model Driven Development car cela est inutile. Je ne '
Cela dit, avoir plus de 100 diagrammes de classe représentant tous les détails de la structure de mon projet et plein de notes partout est vraiment utile. Je crée uniquement des diagrammes de classes pour les projets, car les développeurs n'ont généralement pas le temps d'apprendre ou d'utiliser d'autres diagrammes. Les diagrammes de classes sont également très bons car mis à jour automatiquement. Les diagrammes de classes peuvent être créés après le code en inversant simplement un package et en ajoutant des notes. Il est rapide et toujours précis et 100% itératif.
Veuillez ne pas confondre le développement piloté par modèle qui est un code générateur de modèle et généralement en utilisant UML comme présentation graphique avec des diagrammes de classes UML mis à jour à partir du code. Seul le code synchronisé UML a une valeur réelle pour moi si plusieurs itérations.
Désolé d'être si long mais je pense que nous devrions donner une seconde chance aux diagrammes de classes UML s'ils ne sont utilisés que comme une vue graphique de notre projet. Cela signifie que UML couvre le projet complet et a un modèle unique composé de grands diagrammes de classe représentant le projet complet. Il serait ridicule d'avoir des centaines de petites vues et un modèle pour chaque vue d'un projet ayant des centaines de vues :-)
la source
J'ai atteint l'impasse de mon code et d'autres codes en raison d'une mauvaise conception, d'un changement de direction, etc. J'ai également vu beaucoup d'autres rencontrer ce problème. La grosse erreur (au moins cela me semble être une erreur) est le désir immédiat de jeter le code de travail et de tout réimplémenter de fond en comble.
J'ai abordé chaque cas de la même manière qui semblait bien fonctionner:
Frais:
Avantages:
la source
Il y a environ un mois ou deux, notre projet actuel est resté un peu bloqué en raison de mauvaises décisions de conception (et du manque de conception en un seul endroit), avec le style de développement SCRUM.
Notre solution (et ce que je crois être la norme pour SCRUM) était de consacrer un sprint entier (~ 2 semaines) à rien d'autre qu'au refactoring. Aucune nouvelle fonctionnalité n'a été ajoutée pendant cette période, mais nous avons pu penser à la base de code actuelle et concevoir un système bien meilleur pour ce que nous faisions.
Nous avons maintenant dépassé cet obstacle et avons ajouté de nouvelles fonctionnalités.
la source
La clé pour limiter le coût des modifications de conception est de garder le code aussi SEC que possible. Cela conduira la plupart du code d'application à un niveau très élevé, où la plupart du code exprime directement l'intention et spécifie relativement peu de mécanisme. Si vous procédez ainsi, les décisions de conception auront la plus petite expression possible dans le code et les modifications de conception auront le coût le plus faible possible.
la source
La clé pour éviter les impasses de conception est de reconnaître le plus tôt possible quand votre conception doit changer, et de la modifier ensuite. Les plus gros problèmes ne viennent pas en faisant évoluer continuellement votre conception, mais en refusant de faire évoluer votre conception jusqu'à ce que ce soit un énorme problème.
Par exemple, Netflix a une fonction de profil, où différents membres de la famille peuvent facturer au même plan, mais ont des files d'attente distinctes. Il y a quelques années, ils ont annoncé qu'ils devraient annuler cette fonctionnalité, car seulement 10% de leurs utilisateurs l'utilisaient, mais en raison du piratage de la mise en œuvre, elle consommait une quantité excessive de travaux de maintenance. Après un tollé, ils ont mordu la balle et ont fait une refonte coûteuse afin de garder ces clients.
Je suis sûr que certains ingénieurs ont reconnu une conception sous-optimale lorsqu'ils ont ajouté cette fonctionnalité pour la première fois. S'ils l'avaient changé à l'époque, cela n'aurait pas été aussi grave.
la source
N'est-ce pas Fred Brooks qui a dit quelque chose comme "Prévoyez de jeter le premier"? Ne vous sentez pas trop sombre à ce sujet, les conceptions sans issue apparaissent également dans des projets qui essaient de faire tout le design à l'avance également. Les remaniements se produisent dans tous les types de développement, que ce soit parce que c'était une conception inapplicable dès le départ (les 20% restants qui sont passés sous silence - "le diable est dans les détails") ou parce qu'un client change d'orientation. Il n'y a pas vraiment besoin de sonnettes d'alarme, ne vous inquiétez pas trop.
la source