Comment gérez-vous un saut de complexité?

13

Il semble une expérience peu fréquente mais courante que parfois vous travaillez sur un projet et que soudainement quelque chose se présente de manière inattendue, jette une clé massive dans les travaux et augmente la complexité beaucoup.

Par exemple, je travaillais sur une application qui parlait aux services SOAP sur diverses autres machines. J'ai préparé un prototype qui fonctionnait bien, puis j'ai développé un front-end régulier et généralement tout est opérationnel de manière agréable, assez simple et facile à suivre. Cela a très bien fonctionné jusqu'à ce que nous commencions à tester sur un réseau plus large et soudainement, les pages ont commencé à expirer car la latence des connexions et le temps requis pour effectuer des calculs sur des machines distantes ont entraîné des demandes de délai d'expiration aux services soap. Il s'est avéré que nous devions changer l'architecture pour faire tourner les demandes sur leurs propres threads et mettre en cache les données retournées afin qu'elles puissent être mises à jour progressivement en arrière-plan plutôt que d'effectuer des calculs demande par demande.

Les détails de ce scénario ne sont pas trop importants - en effet, ce n'est pas un bon exemple car il était assez prévisible et les gens qui ont écrit beaucoup d'applications de ce type pour ce type d'environnement auraient pu l'anticiper - sauf qu'il illustre une manière on peut commencer avec une prémisse et un modèle simples et avoir soudainement une escalade de complexité bien dans le développement du projet.

Quelles stratégies avez-vous pour faire face à ces types de changements fonctionnels dont le besoin se fait sentir - souvent en raison de facteurs environnementaux plutôt que de changements de spécifications - plus tard dans le processus de développement ou à la suite de tests? Comment équilibrez-vous entre éviter les risques d'optimisation / YAGNI / de suringénierie prématurés de la conception d'une solution qui atténue les problèmes possibles mais pas nécessairement probables , par opposition à l'élaboration d'une solution plus simple et plus facile qui sera probablement aussi efficace mais n'incorporera pas de préparation pour toutes les éventualités possibles?

Edit: La réponse de Crazy Eddie comprend "vous le sucer et trouver le moyen le moins cher de mettre en œuvre la nouvelle complexité." Cela m'a fait penser à quelque chose qui était implicite dans la question, mais je n'ai pas soulevé spécifiquement.

Une fois que vous avez touché cette bosse et que vous avez intégré les changements nécessaires. Faites-vous ce qui gardera le projet aussi proche que possible du calendrier mais qui peut affecter la maintenabilité ou revenez-vous à votre architecture et la retravaillez à un niveau plus détaillé qui peut être plus maintenable mais qui repoussera tout pendant le développement?

glénatron
la source

Réponses:

8

Ce qui me vient à l'esprit en lisant ceci est l'adage agile: abordez les tâches les plus risquées et / ou les moins bien comprises d'abord dans le cycle de vie du projet . C'est-à-dire essayer de rassembler un squelette de travail du projet le plus tôt possible, pour prouver que le concept fonctionne. Cela permet également d'exécuter toute sorte de tests cruels pour détecter si l'architecture tient vraiment ses promesses dans des circonstances réelles. De plus, s'il y a une nouvelle technologie / plate-forme / outil inconnu inclus dans la solution, prenez-le dès le début sur la plaque.

Si l'architecture de base est OK, les fonctionnalités individuelles peuvent être ajoutées et testées de manière incrémentielle, et refactorisées si nécessaire, avec un coût relativement moindre. La nécessité de changer l'architecture est le gros risque, que l'on devrait traiter dès le départ. Cela donne un retour rapide: dans le pire des cas, si tout le concept s'effondre, nous le savons tôt et pouvons abandonner le projet avec un minimum de pertes.

Péter Török
la source
6

Votre exemple a touché certains des aspects les plus difficiles de la programmation, à savoir l' informatique distribuée et la programmation simultanée , qui sont de plus en plus utilisés et rendent les programmeurs de plus en plus difficiles.

Même la programmation "normale" (thread unique sur une seule machine) est si massivement complexe pour tout programme non trvial, qu'il faut une grande compétence et des années d'expérience pour obtenir quelque chose de bon - mais toujours loin d'être "résolu". Même à ce niveau, les complexités, principalement dues à une explosion combinatoire , dépassent de loin la capacité du cerveau humain à saisir et à comprendre pleinement. Penser autrement est stupide.

L'informatique distribuée et la programmation simultanée ajoutent deux dimensions supplémentaires à la taille de l'espace de "complexité", qui croît au moins en cubique (sp?) (N ^ 3) par rapport à la programmation "normale". Par exemple, pensez à de nouveaux ensembles de problèmes et d' erreurs auxquels nous devons faire face. Pour même jouer avec une idée, que vous pourriez comprendre les interconnexions et les effets secondaires à cette échelle est risible.

Je n'ai clairement pas de balles d'argent, mais je suis sûr que la plus grande erreur que l' on puisse faire est de penser que vous avez tout compris et résolu le problème.

Quelques idées sur la façon de faire face à tout cela, en plus de ce que d'autres réponses ont déjà couvert:

  • Grande humilité
  • Acceptez que votre système / programme est imparfait, impermanent et incomplet .
  • Se préparer aux erreurs
  • Embrasser le changement
  • Planifier la redondance
  • Pensez à l' épreuvage futur
  • Regarder (ou étudier) la biologie ou la sociologie sur le comportement des systèmes complexes
  • Faites de votre mieux pour éviter un état mutable. Optez pour des protocoles sans état (comme REST et HTTP).
  • La programmation fonctionnelle pourrait atténuer une partie de la douleur

Je suppose que je pourrais continuer encore et encore. Sujet très intéressant :)

Maglob
la source
Regardez (ou étudiez) la biologie ou la sociologie comment se comportent les systèmes complexes - Allez. Le reste de votre réponse était solide, mais cela a une telle application périphérique au problème décrit.
Jim
1
@ Jim G. Peut-être. La biologie n'aidera pas à optimiser vos boucles, mais si vous souhaitez proposer de nouvelles perspectives, des idées ou des abstractions efficaces (sur le développement de logiciels), elle vous aide à sortir de votre bac à sable. Arguant que la biologie (ou la sociologie) n'a rien à voir avec la programmation, il ne reste que quelques sauts pour affirmer que la POO ou les modèles de conception n'ont rien à voir avec la programmation. Par exemple: POO : biologie -> Alan Kay -> POO / Smalltalk. Ou Design Patterns : sociologie -> design urbain -> Christopher Alexander -> A Pattern Language -> Design Patterns.
Maglob
@Jim G. Cont. Quelques citations, Alan Kay: "Je pensais que les objets étaient comme des cellules biologiques et / ou des ordinateurs individuels sur un réseau, seulement capables de communiquer avec des messages", et Wikipedia: "[Design Pattern] L'idée a été introduite par l'architecte Christopher Alexander dans le domaine de l'architecture [1] et a été adapté pour diverses autres disciplines, y compris l'informatique "
Maglob
Bien. Je vous donne un +1 pour Essayez de votre mieux pour éviter l'état mutable et autres pépites. Mon point est que si votre manager vous a demandé de réduire la complexité, vous appliqueriez certainement le rasoir d'Occam au problème et vous mettriez au travail. Je ne pense pas que vous ou quelqu'un d'autre "feriez appel à la biologie" pour obtenir de l'aide avec le problème immédiat.
Jim G.12
2

Je suis en désaccord avec l'esprit de la réponse de @ Péter Török car elle suppose qu'une équipe (ou un individu) peut nécessairement prévoir les éléments les plus risqués au début du cycle de vie du projet. Par exemple, dans le cas du PO, l'équipe ne pouvait pas prévoir l'escalade de la complexité attachée à la solution multi-thread jusqu'à ce que leur dos soit contre le mur.

La question du PO est bonne, et elle parle d'un problème que de nombreux ateliers de développement de logiciels ont.

Voici comment je traiterais le problème:

  1. Suivez les conseils de Fred Brooks et organisez vos développeurs comme une équipe de chirurgie .
  2. Choisissez un maître-chirurgien sage et "bienveillant" qui peut à la fois: A) obtenir la confiance et le respect de ses pairs; et B) prendre des décisions difficiles en temps opportun.
  3. Attendez-vous à ce que le maître-chirurgien réduise la complexité à l'avant et à l'arrière du processus de développement.

Plus sur le point # 3:

  1. Le maître-chirurgien doit faire un effort conscient pour proposer la solution la plus simple qui fonctionnera. Des années d'expérience significative devraient mettre le maître-chirurgien en mesure de le faire.
  2. L'organisation plus large, c'est-à-dire les supérieurs du maître-chirurgien, devrait donner à l'équipe suffisamment de temps et de ressources pour réduire la complexité après la date d'expédition. Cela permettra à l'équipe de développement d'expédier le code en temps opportun et d'exécuter le kaizen pour réduire la complexité de manière continue.
Jim G.
la source
À mon humble avis, dans le cas du PO, ils auraient dû commencer à tester plus tôt, pour découvrir comment (et si) leur architecture fonctionnait dans des circonstances réelles. BTW en suggérant d'avoir un « maître chirurgien », vous semblez dire essentiellement qu'il ya des gens qui peuvent prévoir les risques techniques du projet - le point exact que vous prétendez être en désaccord avec.
Péter Török
@ Péter Török: ... En suggérant d'avoir un "maître chirurgien", vous semblez impliquer essentiellement qu'il y a des gens qui peuvent prévoir les risques techniques du projet : Non, je ne le suis pas. Je dis que ces personnes sont à la fois: A) mieux adaptées pour éviter entièrement la complexité en premier lieu; et B) Le mieux adapté pour sortir une équipe de la complexité après l'expédition du code.
Jim G.
À mon humble avis, nous parlons de la même chose. L'expérience qui aide votre «maître chirurgien» à choisir la solution la plus simple qui peut éventuellement fonctionner est construite à partir des souvenirs de projets et de solutions passés, et de savoir quelle solution a fonctionné (ou non) dans quel cas spécifique. En d'autres termes, il examine les solutions applicables à des problèmes spécifiques et évalue les avantages et les risques potentiels de chacun. C'est ce qui l'aide à choisir la bonne pour la situation actuelle, évitant ainsi les chemins les plus risqués .
Péter Török
1
Cela me rappelle une citation du défunt grand entraîneur de chevaux Ray Hunt: "Comment obtenez-vous un bon jugement? Expérience. Comment obtenez-vous de l'expérience? Mauvais jugement."
glenatron
1

Code aux interfaces

Lors de l'écriture de nouvelles fonctionnalités s'interfaçant avec d'autres fonctionnalités, tracez une frontière sous la forme d'une interface (du type Java) à travers laquelle toutes passent. Cette volonté

  1. assurez-vous d'avoir un contrôle total sur les fonctionnalités utilisées
  2. vous permettent d'avoir plusieurs implémentations de la même fonctionnalité.
  3. réduisez la complexité globale car les modules ne sont que faiblement connectés au lieu d'être complètement entrelacés.

la source
0

on peut commencer avec une prémisse et un modèle simples et avoir soudainement une escalade de complexité bien dans le développement du projet

Pas étonnant.

Il s'agit de développement logiciel. Si vous n'inventez rien de nouveau, vous téléchargez une solution existante et éprouvée.

Il y a peu de compromis.

Si vous inventez quelque chose de nouveau, il doit y avoir au moins une fonctionnalité que vous ne comprenez pas complètement. (Pour bien le comprendre, vous devez avoir une implémentation fonctionnelle, que vous utiliserez simplement.)

Comment gérer ça?

  1. Ayez des attentes réalistes. Vous inventez quelque chose de nouveau. Il doit y avoir des parties que vous ne comprenez pas.

  2. Ayez des attentes réalistes. Si cela semble fonctionner correctement la première fois, vous avez oublié quelque chose.

  3. Ayez des attentes réalistes. Si c'était simple, quelqu'un d'autre l'aurait fait en premier, et vous pourriez simplement télécharger cette solution.

  4. Ayez des attentes réalistes. Vous ne pouvez pas très bien prédire l'avenir.

S.Lott
la source
2
Attendez, alors ce que vous dites est: avez-vous des attentes réalistes?
glenatron
0

Concevoir et coder en pensant à l'obsolescence. Supposons que ce que vous codez aujourd'hui devra être supprimé et remplacé demain.

Ian
la source
0

L'environnement doit faire partie de la spécification. Ainsi, un changement d'environnement EST un changement de spécification. Si, en revanche, vous avez basé votre prototype et votre conception sur un environnement autre que celui qui figurait dans les spécifications, vous avez fait une erreur stupide. Quoi qu'il en soit, vous aspirez et trouvez le moyen le moins cher d'implémenter la nouvelle complexité.

Edward Strange
la source
0

Comme pour la plupart des problèmes de programmation, cela dépend , à mon avis. Ce problème est tellement intrinsèque au travail créatif que vous ne devez pas oublier que des échecs vont se produire, et c'est OK . La programmation est un problème grave, et vous ne connaissez généralement pas la bonne solution au problème tant que vous ne l'avez pas déjà résolu.

Cependant, il existe une multitude de facteurs locaux spécifiques qui pourraient entrer en jeu ici, tels que:

  • Les objectifs de ce système. Est-ce une chose unique? Avez-vous l'intention de faire fonctionner ce système à moyen ou long terme?

Pour les choses à court terme, il ne vaut peut-être pas la peine d'y penser plus que suffisant pour le faire fonctionner. Le refactoring coûte cher, et c'est quelque chose qui ne crée pas de valeur finale immédiate pour votre utilisateur. pourtant, il n'y a pratiquement aucun cas auquel je peux penser autre que le logiciel absolu à jeter, où il est si court terme qu'il ne vaut pas la peine d'améliorer votre conception. Il est beaucoup plus important de pouvoir comprendre ce que vous avez fait et de le réparer rapidement que de terminer maintenant. Si c'est pour le plus long terme, cela finira très probablement par payer (et peut-être beaucoup plus tôt que ne le pensent toutes les personnes impliquées), ou l'inverse (ne pas le faire causera de la douleur très rapidement au lieu de "quand nous devons le réparer"). Je suis presque tenté de dire "prenez toujours le temps de l'améliorer", mais il y a des cas où ce n'est pas possible.

  • Les objectifs de l'équipe. S'agit-il plutôt d'un genre de chose "faites-le maintenant, à tout prix" ou "faisons-le bien"?

Cela devrait influencer énormément vos décisions. Votre équipe soutiendra cette décision soit en vous donnant des ressources pour la refonte, soit elle exigera la solution rapide à faire maintenant. À mon avis, si vous constatez que l'équipe vous pousse constamment dans la mauvaise direction, c'est un énorme drapeau rouge. J'ai vu ce genre de chose se retrouver dans un scénario où il y a constamment une extinction d'incendie, où il n'y a jamais de temps pour repenser parce que vous résolvez toujours les problèmes que votre mauvaise conception crée. Il peut aussi y avoir un juste milieu: "du ruban adhésif" maintenant, corrigez le plus tôt possible (mais faites-le réellement).

  • Votre compréhension du problème. Pourquoi la solution précédente n'a-t-elle pas fonctionné?

Vraiment important. Réfléchissez à l'erreur ou au problème et pourquoi il se produit. Ce type de situation est une excellente occasion de trouver des hypothèses, des contraintes et des interactions défectueuses (ou manquantes). En général, privilégiez toujours une meilleure compréhension de votre problème au lieu de résoudre le problème actuel. C'est probablement votre meilleure défense contre YAGNI / overengineering. Si vous comprenez assez bien votre problème, alors vous résoudre ce et pas d' autres problèmes.

Enfin, essayez de construire les choses de la bonne façon . Je ne parle pas des erreurs et des problèmes que vous rencontrez lorsque vous comprenez mieux le problème ou votre erreur humaine inhérente. Je ne veux pas dire "ne faites pas d'erreurs et soyez parfait la première fois" - c'est impossible. Je veux dire, essayez de bien gérer la complexité dans votre travail quotidien, réparez les fenêtres cassées, restez aussi simple que possible, améliorez votre code et votre réflexion tout le temps. De cette façon, lorsque (pas si) changez de frappe à votre porte, vous pouvez l'accueillir à bras ouverts au lieu d'un fusil de chasse.

Juan Carlos Coto
la source