Quels sont les meilleurs principes de génie logiciel?

Les principes de développement de logiciels sont un ensemble de règles et de recommandations spécifiques que les ingénieurs doivent suivre pendant la mise en œuvre du programme s’ils veulent écrire un code beau, clair et maintenable. Il n’y a pas de baguette magique qui peut transformer un méli-mélo de variables, de classes et de fonctions en un code parfait, mais il existe quelques conseils et astuces qui peuvent aider un ingénieur à déterminer s’il fait la bonne chose.

Passons en revue ces recommandations de base. Certains des principes ci-dessous sont spécifiques à Python, mais la plupart ne le sont pas.

Mesurer deux fois et couper une fois

Je pense que c’est le principe le plus important de tous. Si vous n’apprenez qu’un seul principe de ce post, ce devrait être celui-là. Nous, développeurs /architectes/ gestionnaires, luttons contre le manque d’attention, les erreurs stupides et les fautes d’impression, les problèmes personnels, la mauvaise humeur et le café froid. Rien de tout cela n’est pertinent – le problème doit être résolu. Pour moi, en tant qu’ingénieur, ce principe signifie choisir la bonne solution au problème, choisir la bonne approche du problème, choisir les bons outils pour résoudre le problème, avoir confiance dans la solution construite. Choisir, cela signifie y réfléchir, trouver les ressources nécessaires, constituer la bonne équipe, réfléchir à la conception, réfléchir à l’approche, fixer des tâches, contrôler le résultat et en assumer la responsabilité. C’est cela « l’ingénierie telle quelle ». Je pense que moi-même je ne suis pas prêt à le décrire avec des mots corrects.

Don’t Repeat Yourself (DRY)

C’est un principe assez simple mais très utile qui dit que répéter la même chose à différents endroits est une mauvaise idée. Tout d’abord, il est lié à la nécessité d’un soutien et d’une modification ultérieurs du code. Si un certain fragment de code est dupliqué à plusieurs endroits à l’intérieur d’un programme, il y a une forte probabilité de deux situations catastrophiques :

  1. Lorsque vous apportez des modifications, même minimes, au code source, vous devez modifier le même code à plusieurs endroits. Cela demandera du temps, des efforts et de l’attention supplémentaires(souvent ce n’est pas facile).
  2. Le premier point suit le second. Vous ou un autre développeur de votre équipe peut accidentellement manquer l’un des changements(cela peut arriver simplement en fusionnant les branches dans vcs) et faire face aux bugs subséquents dans l’application. Ces bogues peuvent être frustrants pour vous parce que vous avez entendu qu’un tel bogue a déjà été corrigé.

À cet égard, il y a une recommandation – si un code est trouvé dans le listing plus de deux fois, il devrait être placé de manière séparée. Il s’agit d’une recommandation générale. En fait, vous devriez penser à créer une méthode séparée même si vous rencontrez une répétition une deuxième fois.

Le rasoir d’Occam

C’est une idée très commune, qui est venue à la programmation de la philosophie. Le principe a reçu son nom du moine anglais William d’Oakham. Ce principe dit : « Les entités ne doivent pas être multipliées sans nécessité ». En ingénierie, ce principe est interprété comme suit : il n’est pas nécessaire de créer des entités inutiles sans nécessité. Ainsi, il est toujours bon de réfléchir d’abord aux avantages d’ajouter une autre méthode/classe/outil/processus, etc. Après tout, si vous ajoutez une autre méthode/classe/outil/processus, etc. et que vous n’obtenez aucun avantage autre qu’une complexité accrue, à quoi bon ?

Keep It Simple Stupid (KISS)

Keep It Simple Stupid

C’est un principe très similaire au précédent, mais il a une signification légèrement différente. Ce principe dit que le code doit être aussi simple que possible sans structures complexes, sinon cela compliquera le débogage et la maintenance du code. En outre, il sera plus difficile pour un autre programmeur de comprendre la logique du code, ce qui nécessitera également du temps et des efforts supplémentaires. C’est pourquoi vous devriez toujours essayer d’utiliser des constructions simples qui résolvent le problème autant que possible sans de nombreuses branches, une imbrication profonde et des structures de classe excessivement surchargées. En faisant cela, vous vous faciliterez la vie et celle de vos collègues, car la complexité génère des bugs. Rappelez-vous ce qu’a dit Peter Hintiens : « La simplicité est toujours meilleure que la fonctionnalité ».

You Aren’t Gonna Need It (YAGNI)

Un problème dont souffrent de nombreux programmeurs. Le désir d’implémenter en une fois toutes les fonctionnalités nécessaires (et parfois même inutiles) dès le début du projet. C’est-à-dire, lorsqu’un développeur ajoute toutes les méthodes possibles à la classe dès le début et les implémente, et peut même ne jamais les utiliser à l’avenir. Ainsi, selon cette recommandation, commencez par implémenter uniquement ce dont vous avez besoin, et plus tard, si nécessaire, étendez la fonctionnalité. De cette façon, vous économiserez des efforts, du temps et des nerfs sur le débogage du code qui n’est pas vraiment nécessaire.

Grosse conception en amont

Mesurer deux fois et couper une fois

Avant de commencer à développer une fonctionnalité, vous devriez d’abord penser à l’architecture de l’application et concevoir l’ensemble du système jusqu’à des détails suffisamment petits, et seulement ensuite passer à la mise en œuvre selon un plan prédéfini. Le principe a le droit d’exister, mais ces derniers temps, il a fait l’objet de nombreuses critiques. Elles sont tout d’abord liées à l’obsolescence du plan pendant la conception et l’élaboration. Dans ce contexte, il est nécessaire de procéder encore à des modifications ultérieures. Mais elle présente aussi des avantages indéniables : lors d’une conception correcte, il est possible de réduire considérablement le coût du débogage ultérieur et de la correction des erreurs. En outre, de tels systèmes d’information, en règle générale, sont plus laconiques et architecturalement corrects.

Aviter l’optimisation prématurée

« L’optimisation prématurée est la racine de tous les maux (ou du moins la plupart) dans la programmation » – Donald Knuth

L’optimisation est un processus très correct et nécessaire pour accélérer le programme ainsi que pour réduire la consommation des ressources du système. Mais chaque chose a son propre temps. Si l’optimisation est effectuée aux premiers stades du développement, elle peut faire plus de mal que de bien. Tout d’abord, cela est lié au fait que le développement d’un code optimisé nécessite plus de temps et d’efforts pour le développement et le support. Dans ce cas, il faut souvent vérifier dans un premier temps l’exactitude de l’approche de développement choisie. C’est pourquoi, au début, il est plus rentable d’utiliser une approche simple mais pas la plus optimale. Et plus tard, lorsque vous évaluez à quel point cette approche ralentit le travail d’une application, passez à un algorithme plus rapide ou moins gourmand en ressources. En outre, tant que vous implémentez initialement l’algorithme le plus optimal, les exigences peuvent changer et le code ira à la poubelle. Il n’est donc pas nécessaire de perdre du temps sur une optimisation prématurée.

Principe du moindre étonnement

Ce principe signifie que votre code doit être intuitif et évident, et ne pas surprendre un autre développeur lors de la révision du code. Par exemple, si la méthode s’appelle « faire des cookies » mais que vous obtenez des pommes de terre comme résultat, ce code est mauvais (évidemment). En outre, vous devriez essayer d’éviter les effets secondaires et les documenter si vous ne pouvez pas les éviter.

S.O.L.I.D.

SOLID

« SOLID » est en fait un groupe de principes de conception orientés objet. Chaque lettre de « SOLID » représente un des principes, qui sont :

  • La responsabilité unique stipule que chaque module ou classe doit avoir la responsabilité d’une seule partie de la fonctionnalité fournie par le logiciel et que cette responsabilité doit être entièrement encapsulée par la classe ;
  • L’ouverture-fermeture stipule que les entités logicielles (classes, modules, fonctions, etc.) doivent être ouvertes à l’extension, mais fermées à la modification ;
  • La substitution Liskov stipule que la classe héritée doit compléter, et non remplacer, le comportement de la classe de base ;
  • La ségrégation d’interface stipule qu’aucun client ne doit être forcé de dépendre de méthodes qu’il n’utilise pas ;
  • L’inversion de dépendance dit que le programmeur doit travailler au niveau de l’interface et non au niveau de l’implémentation.

Appliqués ensemble, ces principes aident un développeur à créer un code facile à maintenir et à étendre dans le temps.

Loi de Déméter

L’idée de base de ce principe est de diviser les domaines de responsabilité entre les classes et d’encapsuler la logique dans une classe, une méthode ou une structure. De ce principe, on peut distinguer plusieurs recommandations :

  1. Les classes ou entités doivent être indépendantes
  2. Il faut essayer de réduire le nombre de connexions entre les différentes classes (ce qu’on appelle le couplage).
  3. Les classes associées doivent être dans un seul module/package/répertoire (on parle aussi de cohésion.

En suivant ces principes, l’application devient plus flexible, compréhensible et facile à maintenir.

Conclusion

Camarades développeurs, soyons des ingénieurs ! Pensons à la conception et construisons des systèmes robustes et bien implémentés, plutôt que de faire pousser des monstres organiques. Les principes énumérés sont hautement corrélés et connectés dans leur essence. Bien sûr, je ne les ai pas créés, mais un petit rappel ne fait pas de mal, du moins ma mémoire n’est certainement pas parfaite.

Livres recommandés

  • Code propre de Robert C. Martin
  • Architecture propre de Robert C. Martin

.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.