IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Lors de la conception de systèmes logiciels, faites la chose la plus simple qui puisse fonctionner
Par Sean Goedecke

Le , par Sean Goedecke

258PARTAGES

11  0 
Lors de la conception de systèmes logiciels, faites la chose la plus simple qui puisse fonctionner, par Sean Goedecke.

Lorsque vous concevez des systèmes logiciels, faites la chose la plus simple qui puisse fonctionner.

Il est surprenant de voir jusqu'où vous pouvez aller en suivant ce conseil. Je pense sincèrement que vous pouvez l'appliquer à tout moment. Vous pouvez suivre cette approche pour corriger des bogues, pour maintenir des systèmes existants et pour en concevoir de nouveaux.

De nombreux ingénieurs conçoivent en essayant d'imaginer le système « idéal » : quelque chose de bien pensé, presque infiniment évolutif, élégamment distribué, etc. Je pense que c'est une approche totalement erronée de la conception de logiciels. Au lieu de cela, passez ce temps à comprendre en profondeur le système actuel, puis faites la chose la plus simple qui puisse fonctionner.

La simplicité peut être décevante

La conception de systèmes nécessite la maîtrise de nombreux outils différents : serveurs d'applications, proxys, bases de données, caches, files d'attente, etc. À mesure qu'ils se familiarisent avec ces outils, les ingénieurs juniors ont naturellement envie de les utiliser. C'est amusant de construire des systèmes à partir de nombreux composants différents ! Et c'est très satisfaisant de dessiner des cases et des flèches sur un tableau blanc, comme si vous faisiez de la véritable ingénierie.

Cependant, comme pour de nombreuses compétences, la véritable maîtrise implique souvent d'apprendre à en faire moins, et non plus. Le combat entre un novice ambitieux et un vieux maître est un cliché bien connu des films d'arts martiaux : le novice est un tourbillon de mouvements, de sauts et de pirouettes. Le maître reste quant à lui immobile. Mais d'une manière ou d'une autre, les attaques du novice ne semblent jamais atteindre leur cible, et l'attaque finale du maître est décisive.

En informatique, cela signifie qu'une bonne conception logicielle semble décevante. On dirait qu'il ne se passe pas grand-chose. Vous savez que vous êtes en présence d'une bonne conception logicielle parce que vous commencez à avoir des pensées telles que « oh, je ne m'étais pas rendu compte que le problème était si facile » ou « oh super, vous n'avez en fait rien de difficile à faire ».

Unicorn est une excellente conception logicielle, car elle offre toutes les garanties les plus importantes d'un serveur web (isolation des requêtes, mise à l'échelle horizontale, récupération après panne) en s'appuyant sur les primitives Unix. L'API REST Rails, norme industrielle, est une excellente conception logicielle, car elle vous offre exactement ce dont vous avez besoin pour une application CRUD de la manière la plus ennuyeuse possible. Je ne pense pas que ces logiciels soient impressionnants. Mais ce sont des prouesses impressionnantes en matière de conception, car ils font la chose la plus simple qui puisse fonctionner.

Vous devriez en faire autant ! Supposons que vous ayez une application Golang à laquelle vous souhaitez ajouter une sorte de limitation de débit. Quelle est la chose la plus simple qui puisse fonctionner ? Votre première idée pourrait être d'ajouter une sorte de stockage persistant (par exemple, Redis) pour suivre le nombre de requêtes par utilisateur à l'aide d'un algorithme de type « leaky bucket ». Cela fonctionnerait ! Mais avez-vous besoin d'une toute nouvelle infrastructure ? Et si, à la place, vous conserviez ces nombres de requêtes par utilisateur en mémoire ? Bien sûr, vous perdriez certaines données de limitation de débit lorsque l'application serait redémarrée, mais est-ce important ? En fait, êtes-vous sûr que votre proxy périphérique ne prend pas déjà en charge la limitation de débit ? Pourriez-vous simplement écrire quelques lignes dans un fichier de configuration au lieu d'implémenter la fonctionnalité ?

Peut-être que votre proxy périphérique ne prend pas en charge la limitation de débit. Peut-être que vous ne pouvez pas la suivre en mémoire parce que vous avez trop d'instances de serveur fonctionnant en parallèle, de sorte que la limite de débit la plus stricte que vous pourriez appliquer de cette manière est trop large. Peut-être que la perte des données de limitation de débit serait rédhibitoire, car les utilisateurs sollicitent votre service de manière excessive. Dans ce cas, la solution la plus simple qui pourrait fonctionner serait d'ajouter un stockage persistant, vous devriez donc le faire. Mais si vous pouviez adopter l'une des approches les plus simples, ne le feriez-vous pas ?

Vous pouvez vraiment créer une application entière à partir de zéro de cette manière : commencez par la chose la plus simple possible, puis ne l'étendez que lorsque de nouvelles exigences vous y obligent. Cela peut sembler ridicule, mais cela fonctionne. Considérez cela comme le principe de conception ultime YAGNI : au-dessus de la responsabilité unique, au-dessus du choix du meilleur outil pour le travail et au-dessus de la « bonne conception ».

Qu'y a-t-il de mal à faire la chose la plus simple ?

Bien sûr, il y a trois gros problèmes à toujours faire la chose la plus simple qui puisse fonctionner. Le premier est qu'en n'anticipant pas les exigences futures, vous vous retrouvez avec un système rigide ou un gros fouillis. Le deuxième est qu'il n'est pas clair ce que signifie « le plus simple », donc au pire, je dis « pour bien concevoir, faites toujours une bonne conception ». Le troisième est que vous devriez construire des systèmes évolutifs, et non des systèmes qui fonctionnent simplement pour le moment. Examinons ces objections dans l'ordre.

Gros enchevêtrements

Pour certains ingénieurs, « faire la chose la plus simple qui puisse fonctionner » revient à leur dire d'arrêter de faire de l'ingénierie. Si la chose la plus simple est généralement un bricolage rapide, cela signifie-t-il que ce conseil mènera inévitablement à un désordre complet ? Nous avons tous vu des bases de code avec des bricolages empilés les uns sur les autres, et elles ne ressemblent certainement pas à une bonne conception.

Mais les hacks sont-ils simples ? Je ne pense pas. Le problème avec un hack ou un kludge, c'est justement qu'ils ne sont pas simples : ils ajoutent de la complexité au code en introduisant un élément supplémentaire dont il faut toujours se souvenir. Les hacks sont simplement plus faciles à imaginer. Trouver la bonne solution est difficile, car cela nécessite de comprendre l'ensemble du code (ou une grande partie de celui-ci). En fait, la solution appropriée est presque toujours beaucoup plus simple que le hack.

Il n'est pas facile de faire la chose la plus simple qui puisse fonctionner. Lorsque vous examinez un problème, les premières solutions qui vous viennent à l'esprit ne sont généralement pas les plus simples. Pour trouver la solution la plus simple, il faut envisager de nombreuses approches différentes. En d'autres termes, cela nécessite un travail d'ingénierie.

Qu'est-ce que la simplicité ?

Les ingénieurs sont en désaccord sur ce qui constitue un code simple. Si « le plus simple » signifie déjà « avec une bonne conception », est-ce une tautologie de dire « vous devriez faire la chose la plus simple qui puisse fonctionner » ? En d'autres termes, Unicorn est-il vraiment plus simple que Puma ? L'ajout d'une limitation de débit en mémoire est-il vraiment plus simple que l'utilisation de Redis ? Voici une définition approximative et intuitive de la simplicité :

  1. Les systèmes simples ont moins de « pièces mobiles » : moins de choses à prendre en compte lorsque vous travaillez avec eux.
  2. Les systèmes simples sont moins connectés en interne. Ils sont composés de composants avec des interfaces claires et simples.

Les processus Unix sont plus simples que les threads (et donc Unicorn est plus simple que Puma) car les processus sont moins connectés : ils ne partagent pas la mémoire. Cela me semble tout à fait logique ! Mais je ne pense pas que cela vous donne les outils nécessaires pour déterminer ce qui est le plus simple dans chaque cas.

Qu'en est-il de la limitation de débit en mémoire par rapport à Redis ? D'un côté, la mémoire est plus simple car vous n'avez pas à vous soucier de tout ce qui est impliqué dans la mise en place d'un service séparé avec une mémoire persistante. D'un autre côté, Redis est plus simple car les garanties de limitation de débit qu'il offre sont plus directes : vous n'avez pas à vous soucier du cas où une instance de serveur considère qu'un utilisateur est limité en débit et une autre non.

Lorsque je ne sais pas ce qui me « semble » plus simple, j'aime utiliser ce critère décisif : les systèmes simples sont stables. Si vous comparez deux états d'un système logiciel et que l'un nécessite plus de travail continu si aucune exigence ne change, l'autre est plus simple. Redis doit être déployé et maintenu, il peut avoir ses propres incidents, il nécessite sa propre surveillance, il nécessite un déploiement distinct dans tout nouvel environnement dans lequel le service se trouve, etc. Ainsi, la limitation du débit en mémoire est plus simple que Redis.

Pourquoi ne voudriez-vous pas être évolutif ?

Certains ingénieurs s'écrient à présent : « Mais la limitation du débit en mémoire n'est pas évolutive ! » Faire la chose la plus simple qui puisse fonctionner ne permettra certainement pas d'obtenir le système le plus évolutif possible. Cela permettra d'obtenir un système qui fonctionne bien à l'échelle actuelle. Est-ce de l'ingénierie irresponsable ?

Non. À mon avis, le péché capital de l'ingénierie SaaS des grandes technologies est l'obsession de l'évolutivité. J'ai vu tant de souffrances inévitables causées par des systèmes surdimensionnés, conçus pour faire face à plusieurs ordres de grandeur de plus que l'échelle actuelle.

La principale raison de ne pas essayer cela est que cela ne fonctionne pas. D'après mon expérience, pour toute base de code non triviale, vous ne pouvez pas anticiper son comportement face à plusieurs ordres de grandeur de trafic supplémentaires, car vous ne savez pas à l'avance où se trouveront tous les goulots d'étranglement. Tout au plus, vous pouvez essayer de vous assurer que vous êtes prêt à faire face à un trafic deux ou cinq fois supérieur à l'actuel, puis vous tenir prêt à résoudre les problèmes au fur et à mesure qu'ils se présentent.

L'autre raison de ne pas essayer cela est que cela rend votre base de code rigide. Il est amusant de découpler votre service en deux parties afin qu'elles puissent être mises à l'échelle indépendamment (j'ai vu cela se produire peut-être dix fois, et je les ai vues être réellement mises à l'échelle indépendamment peut-être une fois). Mais cela rend certaines fonctionnalités très difficiles à mettre en œuvre, car elles nécessitent désormais une coordination sur le réseau. Dans le pire des cas, elles nécessitent des transactions sur le réseau, ce qui est un véritable problème d'ingénierie. La plupart du temps, vous n'avez tout simplement pas besoin de faire tout cela !

Conclusion

Plus je travaille dans le domaine des technologies, moins je suis optimiste quant à notre capacité collective à prédire l'évolution d'un système. Il est déjà assez difficile de comprendre où en est actuellement un système. Et en fait, c'est là la principale difficulté pratique pour réaliser une bonne conception : obtenir une compréhension précise et globale du système. La plupart des conceptions sont réalisées sans cette compréhension, et la plupart des conceptions sont donc assez mauvaises.

Il existe, en gros, deux façons de développer un logiciel. La première consiste à prédire à quoi pourraient ressembler vos besoins dans six mois ou un an, puis à concevoir le meilleur système pour répondre à ces besoins. La seconde consiste à concevoir le meilleur système pour répondre à vos besoins actuels : en d'autres termes, à faire la chose la plus simple qui puisse fonctionner.

Source : "Do the simplest thing that could possibly work"

Et vous ?

Pensez-vous que ces principes sont crédibles ou pertinents ?
Quel est votre avis sur le sujet ?

Voir aussi :

Les erreurs commises par les ingénieurs logiciels dans les grandes bases de codes établies, par Sean Goedecke

Développement de logiciels à long terme, par Bert Hubert

Le Manifeste anti-héritage : Écrire du code qui dure, par Mensur Durakovic
Vous avez lu gratuitement 2 544 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de skaarj
Membre régulier https://www.developpez.com
Le 12/03/2026 à 11:19
Il existe un mensonge moderne particulièrement pervers : celui qui consiste à appeler « progrès » une complexification systématique de nos outils. On nous vend chaque mise à jour avec la promesse d'une ergonomie accrue, mais la réalité est tout autre. Nous vivons dans l'ère de l'obésité fonctionnelle.

L'exemple de Photoshop est, à ce titre, flagrant. À l'époque de la version 7, le logiciel était un instrument chirurgical. On en connaissait les moindres recoins, on maîtrisait ses raccourcis, on exploitait 100 % de son potentiel. C’était un outil solide, au service de l'utilisateur. Aujourd'hui, le logiciel est devenu une entité tentaculaire, une véritable usine à gaz dopée à l'intelligence artificielle et aux services cloud obligatoires.

Le constat est amer : alors que les fonctionnalités ont été multipliées par dix, la plupart d'entre nous n'en utilisent plus qu'un infime pourcentage. Nous nous retrouvons à naviguer dans un cockpit d'avion pour simplement effectuer des retouches qui étaient plus rapides et plus instinctives il y a vingt ans.

Cette complexité ne sert pas l'efficacité, elle sert la dépendance :

Saturation cognitive : Trop de menus, trop d'options, trop de distractions.
Perte de maîtrise : On ne manipule plus l'image, on demande à un algorithme de le faire pour nous.
Lourdeur système : Pour faire la même chose qu'avant, il faut désormais une puissance de calcul démesurée.

Le slogan « Encore plus simple » est le masque d'une industrie qui a peur du vide. Au lieu de perfectionner la robustesse d'un outil, on préfère empiler des gadgets pour justifier des abonnements mensuels. En fin de compte, ce faux sentiment de simplicité cache une réalité brutale : l'outil ne nous appartient plus, c'est nous qui appartenons à l'outil.
9  0 
Avatar de
https://www.developpez.com
Le 10/03/2026 à 18:09
KISS
5  0 
Avatar de didier.cabale
Membre confirmé https://www.developpez.com
Le 11/03/2026 à 11:46
1. Pourquoi faire compliqué quand on peut faire simple.
2. KISS est toujours ce que je m'évertue à faire depuis toujours (40+ ans de développement), quitte à ce qu'on veuille me faire passer pour le moins productif, çad "celui qui produit le moins de ligne de code".
3. Quand je vois une complexité technique qui me tend les bras, je me demande toujours ce qu'elle apporte, par rapport aux emmerdements qu'elle pourrait provoquer.
.. Cependant, dans la vraie vie, on code rarement depuis une page blanche; on code /debogue sur une base de code existante (legacy), dont la structure est imposée, et là le problème essentiel n'est pas de trouver la solution la plus simple, mais de savoir si on a bien compris l'architecture en place.
4  0 
Avatar de thierryc
Membre régulier https://www.developpez.com
Le 27/03/2026 à 9:55
L'auteur propose de faire simple, et aussitôt il se contredit en tentant d'expliquer que les solutions vraiment simples sont des "hacks" et donc ne sont pas simples.

Il faut une conception, et de bonnes pratiques, et des motifs de conception solides, et une approche partagée du développement au sein d'une équipe, ainsi qu'une approche partagée de la documentation et des tests. Etc.

En réalité, l'approche simpliste est ce qui a conduit à l'absence d'une démarche d’ingénierie logicielle ces 20 ou 30 dernières années, avec la conséquence inévitable de l'obsolescence non-nécessaire de nombreux développements, lorsque ceux-ci ont réussi par chance à arriver en production.

J'ai pu expérimenter une approche de conception/développement par composants avec un fort élément de programmation défensive, ainsi que d'autre pratiques. Le tout mis en place par un gros travail de formation et de tutorat des équipes. Le résultat est une programmation simple, mais pas simpliste, efficace, et extraordinairement rentable dès lors que l'horizon économique du projet est à 3 ans ou plus. L'approche composants et la qualité mise en place conduit à une extraordinaire réutilisation dépassant les 90% au bout de deux ans, et les coûts de maintenance deviennent négligeables.

Évidemment, le problème aujourd'hui n'est qu'aucun client ne sait plus raisonner à 3 ans sur son informatique. Dans ce cadre, le "hack" est bien suffisant, malheureusement. Sans raisonnement d'ingénieur, sérieux, prenant en compte les aspects économiques, technologiques et humains, le développement informatique ne peut qu'être victime de l'air du temps. A commencer par la soi-disant "intelligence" soi-disant "artificielle" qui saurait produire du logiciel à la place d'un professionnel. Du "hack", sans doute.
1  0 
Avatar de Artemus24
Expert éminent sénior https://www.developpez.com
Le 11/03/2026 à 18:05
Salut à tous.

Il n'y a rien de plus compliqué que de vouloir faire simple.
Celui qui n'arrive pas à faire simple, à l'esprit compliqué.
Je reconnais qu'il est facile d'affirmer cela, mais dans la réalité, c'est tout autre car il faut maitriser son sujet, ce qui n'est pas à la porté de tous.
2  2