Solution simple vs complexe (mais efficace en termes de performances) - laquelle choisir et quand?

28

Je programme depuis quelques années et je me suis souvent retrouvé face à un dilemme.

Il y a deux solutions -

  • l'une est simple, c'est-à-dire une approche simple, plus facile à comprendre et à maintenir. Cela implique une certaine redondance, un travail supplémentaire (extra IO, extra processing) et n'est donc pas la solution la plus optimale.
  • mais d'autres utilisent une approche complexe, difficile à mettre en œuvre, impliquant souvent une interaction entre beaucoup de modules et est une solution efficace en termes de performances.

Quelle solution devrais-je essayer lorsque je n'ai pas de SLA de performance difficile à respecter et même la solution simple peut répondre au SLA de performance? J'ai éprouvé du dédain chez mes collègues développeurs pour une solution simple.

Est-ce une bonne pratique de trouver la solution complexe la plus optimale si votre SLA de performance peut être atteint par une solution simple?

Dépêche toi
la source
10
voir: Comment éviter les «mauvaises intuitions du développeur»? "Malheureusement, les développeurs ont généralement une horrible intuition sur l'endroit où les problèmes de performances dans une application seront réellement ..."
gnat
1
"Pas le plus optimal" sera-t-il toujours "assez bon"? Alors restez avec ça.
8
Oui. " Le mieux est l'ennemi du bien. " Voltaire. ("Parfait est l'ennemi du bien.") Assez bon est assez bon - jusqu'à ce que les tests de performance disent le contraire.
David Hammen
Je trouve que (en général) simple implique efficace. Il n'est donc souvent pas nécessaire de faire de compromis.
Dan
2
"Il semble que la perfection n'est pas atteinte quand il n'y a plus rien à ajouter, mais quand il n'y a plus rien à supprimer." - Antoine de Saint-Exupéry
keuleJ

Réponses:

58

Quelle solution devrais-je essayer lorsque je n'ai pas de SLA de performance difficile à respecter et même la solution simple peut répondre au SLA de performance?

Le simple. Il répond aux spécifications, il est plus facile à comprendre, il est plus facile à entretenir et il est probablement beaucoup moins bogué.

Ce que vous faites en préconisant la solution efficace en termes de performances, c'est d'introduire une généralité spéculative et une optimisation prématurée dans votre code. Ne fais pas ça! Les performances vont à l'encontre de presque toutes les autres «fonctionnalités» de génie logiciel (fiabilité, maintenabilité, lisibilité, testabilité, compréhensibilité, ...). Rechercher les performances lors des tests indique qu'il est vraiment nécessaire de rechercher les performances.

Ne poursuivez pas les performances lorsque les performances n'ont pas d'importance. Même si cela importe, vous ne devez rechercher les performances que dans les domaines où les tests indiquent qu'un goulot d'étranglement des performances existe. Ne laissez pas les problèmes de performances être une excuse pour remplacer simple_but_slow_method_to_do_X()par une version plus rapide si cette version simple ne se présente pas comme un goulot d'étranglement.

Les performances améliorées sont presque inévitablement gênées par une multitude de problèmes d'odeur de code. Vous en avez mentionné plusieurs dans la question: Une approche complexe, difficile à mettre en œuvre, un couplage plus élevé. Est-ce que cela vaut vraiment la peine d'être traîné?

David Hammen
la source
votre réponse est très utile
MoveFast
1
Aussi simple que possible, mais pas plus simple; Aussi vite que possible, mais pas plus vite; etc
user606723
2
"En cas de doute, utilisez la force brute";)
tdammers
Les commentaires dans le code peuvent être à la fois cathartiques et utiles ici. Un petit commentaire soulignant la solution complexe + rapide, et pourquoi vous ne l'avez pas utilisée, peut vous faire moins sentir que vous avez ignoré l'algorithme optimal. Et cela peut aider les responsables de la maintenance à comprendre votre choix et à les orienter dans la bonne direction si une optimisation est réellement nécessaire plus tard.
TheAtomicOption
12

Réponse courte: préférez les solutions simples aux solutions complexes et souvenez -vous des principes KISS et YAGNI

Étant donné que les exigences initiales du projet et le logiciel ne sont jamais parfaits, ils nécessitent des modifications à mesure que l'application est développée / utilisée. L'approche itérative dans les phases de développement est un très bon moyen de commencer les choses simplement et de l'étendre au besoin. Les solutions les plus simples ont de la flexibilité et sont plus faciles à entretenir.

De plus, essayer d'être intelligent et placer une optimisation supplémentaire lors de la construction de votre application n'est pas une bonne pratique et peut compliquer votre solution de manière excessive. Comme on le sait, "premature optimization is the root of all evil"- du livre de Knuth

EL Yusubov
la source
1
@ManojGumber, aucun problème et c'est vraiment l'essence de ce que nous, en tant que programmeurs, devons nous soucier en premier lieu.
EL Yusubov
8

Prenez une leçon de Knuth ici: "Nous devons oublier les petites efficacités, disons environ 97% du temps: l'optimisation prématurée est la racine de tout mal".

Pensez à vos solutions dans cet ordre: d'abord, toujours, l'exactitude. Deuxièmement, améliorez la clarté et la simplicité. Troisièmement, et seulement lorsque vous pouvez démontrer le besoin, l'efficacité.

Ajouter de l'efficacité vous coûtera presque toujours quelque chose d'important, et ne devrait donc être poursuivi que lorsque vous savez que vous en avez besoin.

Simon
la source
4
Notez que cela ne signifie pas que vous ne devez pas écrire une bonne implémentation en premier lieu.
@ ThorbjørnRavnAndersen: bien sûr, c'est de cela qu'il s'agit pour les deux premiers points.
simon
1
@simon la citation est fréquemment utilisée comme excuse pour choisir avec négligence,
À propos de votre deuxième point: j'ai eu un collègue qui a très souvent déclaré qu'il préférait un code incorrect, bien structuré et propre avant les spaghettis corrects.
Buhb
@ ThorbjørnRavnAndersen les personnes incompétentes utiliseront n'importe quoi pour une excuse. N'a aucun impact sur la valeur de la pensée originale.
simon
7

La simplicité est la condition préalable de la fiabilité . Si vous avez une solution simple qui fonctionne, allez-y certainement! Il est beaucoup plus facile d'optimiser un programme de travail que de faire fonctionner un programme optimisé. N'oubliez pas non plus la loi de Moore : si votre solution simple atteint aujourd'hui les objectifs de performance, elle les écrasera probablement 1 en un an ou deux.


1 Il n'y a aucune garantie, car comme Jimmy Hoffa l'a noté dans son commentaire ci-dessous, la loi de Moore a ses limites.

dasblinkenlight
la source
Vous avez oublié l'autre loi de Moore qui stipule: "Oups, ma première loi .." Désolé patron, la loi de Moore n'est plus (jeu de mots). Je ne suis pas en désaccord avec le reste de votre argument, je voudrais tout au moins mettre en garde cette dernière partie.
Jimmy Hoffa
2
Désolé, mais dans toute mon expérience dans cette industrie. les «ensembles de travail» augmentent beaucoup plus vite que la vitesse de notre matériel, qui est constamment mis à jour. Vraiment, je voudrais simplement supprimer le point de droit de Moore.
user606723
@ user606723 La croissance du point "work set" est orthogonale à la question "optimisée ou simple": la charge de travail les rattrapera quelle que soit la solution qu'ils mettent en œuvre. Le point d'intégrer la loi de Moore dans le mélange était de souligner que même si la solution simple est soumise à une certaine pression de performance au moment de la rédaction, la pression diminuera à mesure que le matériel deviendra plus rapide.
dasblinkenlight
@dasblinkenlight, la croissance du workset n'est pas plus orthogonale à la question que ne l'est la loi de moore. Le point de mettre le sous-projet dans le problème est que si une solution simple est soumise à une certaine pression sur les performances au moment de la publication, les performances seront insuffisantes dans un avenir très proche, car le sous-ensemble croissant démolit toute amélioration des performances obtenue par un matériel amélioré. Bien que je sois pour des logiciels simples, fiables et maintenables, publier un logiciel qui est déjà sous pression de performance à la sortie et s'attendre à ce que la loi de Moore égalise les choses est une philosophie terrible.
user606723
3

Est-ce une bonne pratique de trouver la solution complexe la plus optimale si votre SLA de performance peut être atteint par une solution simple?

Optimal est un mot ambigu!

En fin de compte, s'il y a beaucoup de risques à devoir maintenir le complexe, et si le simple est "assez bon", je me tromperais toujours du côté du simple.

Ajoutez à cela le risque que le complexe ne soit pas assez bon, alors KISS est probablement la bonne réponse.

Andrew
la source
2

Je préfère le simple. À mon avis, les optimisations prématurées causent autant de problèmes qu'elles en résolvent. Dans de nombreux cas, une bonne conception vous permet de modifier des implémentations données à l'avenir, si elles deviennent des goulots d'étranglement.

Donc en fin de compte - je vais le concevoir aussi flexible que possible, mais ne sacrifierai pas trop la simplicité pour la flexibilité.

Tsvetomir Dimitrov
la source
2

Lequel coûte le moins cher?

La plupart du temps, une solution simple légèrement plus lente sera parfaitement acceptable en termes de performances, et la simplicité rend son développement, sa maintenance et son remplacement moins coûteux.

D'un autre côté, la vitesse est parfois très importante, et le gain financier qui résulte de même de petites améliorations de vitesse peut être bien plus important que le coût accru d'une solution plus compliquée. Par exemple, une réduction de 0,01 s sur le temps pour achever une transaction peut rendre un système d'échange de titres beaucoup plus rentable. Une amélioration de 10% de l'efficacité d'un système prenant en charge plusieurs millions d'utilisateurs pourrait signifier une réduction significative des coûts de serveur.

Donc, la question que vous devez vous poser est la suivante: l' utilisation de la solution complexe a-t-elle suffisamment d'impact sur le résultat net pour payer son coût supplémentaire? En fait, vous devriez probablement demander à votre client de décider car il paie les factures et en profite. Une bonne option consiste à opter d'abord pour la solution simple et à proposer la solution la plus complexe en tant qu'amélioration possible. Cela vous permet de faire fonctionner votre système et donne à votre client quelque chose pour commencer les tests, et cette expérience peut éclairer la décision d'implémenter (ou de ne pas implémenter) la solution la plus compliquée.

Caleb
la source
2

Lors de l'évaluation de deux approches, l'une étant plus simple mais moins efficace tandis que l'autre étant plus complexe et plus efficace, il faut considérer le problème et le domaine du projet.

Considérons un projet logiciel de plusieurs milliards de dollars pour l'industrie des soins de santé qui prévoit une durée de vie de plus de 15 ans de maintenance et +20 ans d'utilisation. Dans un tel projet, la performance ne sera certainement pas une préoccupation, mais la complexité et la structure du projet peuvent causer des problèmes majeurs pour la maintenance du projet, qui dure au moins 15 ans. La maintenabilité et la simplicité passent avant tout.

Ensuite, considérons un autre exemple. Un moteur de jeu de console qui est censé alimenter les prochains jeux de la société pour les 5+ prochaines années. Parce que les jeux sont des programmes extrêmement limités en ressources, l'efficacité passe avant la maintenabilité dans de nombreux cas. L'écriture de vos propres structures de données et algorithmes très spécifiques pour certaines tâches peut être très importante même si elle va à l'encontre de tout type de "meilleures pratiques" de développement logiciel. Un bon exemple de cela pourrait être la conception orientée données dans laquelle vous stockez vos données dans des tableaux de données similaires, plutôt que dans des objets réels. Cela permet d'augmenter la référence de la localité et, en tant que tel, d'augmenter l'efficacité du cache du processeur. Pas pratique, mais très crucial dans le domaine donné.

zxcdw
la source
1

C'est toujours une question difficile et je vois les réponses osciller dans un sens, donc je vais jouer le jeu pour l'autre côté, bien que je ne prétende pas que l'une ou l'autre réponse soit correcte, c'est un sujet très doux et au cas par cas.

Une chose à propos d'une solution complexe mais à hautes performances est que vous pouvez toujours simplement documenter les problèmes qui en découlent. Je suis généralement un fan de code auto-documenté, mais je suis aussi un fan de logiciels qui répondent dans un laps de temps qui me donne l'impression que cela ne me ralentit pas. Si vous optez pour la solution complexe mais hautes performances, réfléchissez à ce que vous pouvez faire pour la rendre moins mauvaise:

Enveloppez-le dans une interface, mettez-le dans un assemblage seul, peut-être même un processus à lui tout seul. Faites-le aussi lâchement couplé que possible avec un mur d'abstraction aussi épais que possible pour éviter les fuites . Écrivez de nombreux tests unitaires pour enregistrer les régressions à l'avenir.

Documentez-le dans le code, pensez même à écrire de la vraie documentation. Pensez aux structures de données complexes et à la façon dont elles sont documentées, imaginez essayer de comprendre la mise en œuvre de l'une d'entre elles à partir du code sans un livre de structures de données / article wikipedia pour l'expliquer. Et pourtant, nous acceptons tous que ces structures de données complexes sont en fait de bonnes choses et il est avantageux que quelqu'un les ait mises en œuvre dans nos langues.

N'oubliez pas que nous envoyons tous des messages sur une pile TCP / IP qui est probablement aussi difficile que le code puisse obtenir si l'un d'entre nous le regarde, expressément pour qu'il fonctionne de la manière dont nous en avons tous besoin. Peut-être que votre problème ne nécessite pas ce niveau d'optimisation, peut-être, mais faites attention lorsque vous abordez cette question, comme nous le devons tous de temps en temps: il y a des dragons là-bas.

Jimmy Hoffa
la source
0

J'arrive à ce travail dans des domaines où il n'y a pas de SLA de performance. En ce qui concerne les moteurs de rendu hors ligne en infographie, il n'y a pas de "performances satisfaisantes" pour les utilisateurs, car ils dépensent déjà d'énormes sommes d'argent pour répartir l'informatique sur les clouds et rendre les batteries de serveurs, même avec les moteurs de rendu les plus modernes. pour produire des images et des images de qualité production pour des films, par exemple

Mais je dois dire en tant qu'entreprise travaillant dans ce domaine depuis de nombreuses années que toute solution qui dégrade considérablement la maintenabilité en faveur de l'efficacité fonctionne en fait contre les exigences de performance en constante évolution. Parce que si vous ne pouvez pas maintenir efficacement votre solution pendant des années à venir alors que les choses changent sous vos pieds (à la fois en termes de code environnant et de ce que les utilisateurs attendent que les concurrents continuent de se surpasser les uns les autres), alors votre solution travaille déjà vers l'obsolescence et besoin de remplacement en gros.

Je ne vois pas le but ultime de profileurs comme VTune comme un moyen d'accélérer l'exécution de mon code. Leur valeur ultime est de m'assurer que je ne dégrade pas ma productivité pour répondre à des exigences de performance en constante augmentation. Si je dois absolument appliquer une micro-optimisation grossière, le profileur, combiné à son exécution sur des cas d'utilisateurs réels (et non à un cas de test, j'imagine peut- être important), s'assure que j'applique une telle apparence inévitablement grossière optimisations très, très judicieusement uniquement aux meilleurs hotspots qui apparaissent ainsi que de les documenter très soigneusement car je devrai inévitablement les revoir, les maintenir et les modifier et les modifier pour les années à venir si cette solution reste viable.

Et surtout si votre solution optimisée implique plus de couplage, je serais vraiment réticent à l'utiliser. Parmi les mesures les plus précieuses que j'apprécie dans les domaines les plus critiques de la base de code, le découplage (comme pour minimiser la quantité d'informations que quelque chose doit fonctionner, ce qui minimise également la probabilité qu'il nécessite des modifications à moins qu'il n'ait directement besoin de modifications) ), car ces domaines critiques multiplient considérablement les raisons pour lesquelles les choses changent. Ce qui signifie que moins il faut d'informations pour fonctionner, moins il y a de raisons de changer et minimiser les raisons du changement est vraiment une partie énorme de l'amélioration de la productivité dans mes domaines de concentration particuliers parce que les choses vont devoir constamment changer de toute façon (nous deviendra obsolète dans un an sinon),

Pour moi, les solutions les plus grandes et les plus efficaces que j'ai trouvées sont celles où l'efficacité, la maintenabilité et la productivité ne sont pas diamétralement opposées. La quête pour moi est d'essayer de rendre ces concepts aussi harmonieux que possible.

Dragon Energy
la source