Degré jaune

Table des matières

Principes

Principe de ségrégation des interfaces (ISP)

Pourquoi ? Les descriptions de prestations qui sont indépendantes d'une réalisation concrète rendent indépendant.
Mutabilité   
Correction   
Efficacité de la production   
Amélioration continue   
Développeur unique
Le principe de ségrégation de l'interface (ISP) est un autre SOLID Principe. Ségrégation signifie Séparation. Le principe est qu'un client ne doit pas dépendre de détails d'un service dont il n'a pas besoin. Moins il y a de choses dans son interface, moins le couplage entre les deux composants est important. Imaginons que nous devions concevoir un connecteur permettant de connecter un moniteur à un ordinateur. Nous décidons tout simplement de mettre à disposition tous les signaux qui arrivent dans un ordinateur par le biais d'un connecteur. Le connecteur a certes plusieurs centaines de broches, mais il est très flexible. Malheureusement, le couplage est également maximal. Dans l'exemple du connecteur, il est évident qu'une connexion de moniteur ne doit contenir que les signaux nécessaires à la représentation d'une image sur le moniteur. Il en va de même pour les interfaces logicielles. Elles aussi doivent être aussi petites que possible afin d'éviter tout couplage inutile. Et comme pour le connecteur d'écran, l'interface doit être très cohésive : Elle ne devrait contenir que des choses qui sont vraiment étroitement liées. Pour appliquer le principe de ségrégation des interfaces, les deux refactorisations suivantes sont disponibles Interface d'extraction et Extrait Superclass à disposition.

Sources

Source Auteur Brève description
ObjectMentor Robert C. Martin Article sur l'Interface Segregation Principle de 1996, publié dans l'Engineering Notebook for Le rapport C++

Principe d'inversion de dépendance (DIP)

Pourquoi ? Pour tester avec précision, il faut isoler les classes. L'isolation se produit lorsque les classes ne contiennent plus de dépendances d'implémentations - ni au moment de l'exécution, ni au moment de la traduction. Les dépendances concrètes doivent donc être décidées le plus tard possible. Le mieux est de le faire au moment de l'exécution.
Mutabilité   
Correction   
Efficacité de la production   
Amélioration continue   
Développeur unique
Le principe d'inversion des dépendances (DIP) est un SOLID principe. Il dit ceci
  • Les classes de haut niveau ne doivent pas dépendre des classes de bas niveau, mais toutes deux des interfaces.
  • Les interfaces ne doivent pas dépendre des détails, mais les détails des interfaces.
Si une classe de haut niveau utilise directement une classe de bas niveau, il en résulte un fort couplage entre les deux. Au plus tard, si l'on essaie de tester la classe de haut niveau de manière isolée, on se heurte à des difficultés. C'est pourquoi la classe de haut niveau devrait dépendre d'une interface qui est à son tour implémentée par la classe de bas niveau. Ainsi, la classe de bas niveau peut être testée dans le cadre d'un test unitaire à l'aide d'une interface. Maquette être remplacés. Pour résoudre à l'exécution la dépendance abstraite inversée avec un objet concret, trois possibilités s'offrent en principe :
  • à l'aide des paramètres du constructeur "à la main
  • Utilisation d'un conteneur d'inversion de contrôle (IoC) tel que Castle Windsor
  • Recherche de dépendances
Sur le site degré jaune nous injectons d'abord les dépendances uniquement via les paramètres des constructeurs. Au début, c'est la solution la plus simple et elle fonctionne très bien avec une poignée de classes. Plus tard, dans le degré vert nous utilisons un conteneur IoC et Dependency Lookup.

Sources

Source Auteur Brève description
objectmentor Robert C. Martin Article sur le Dependency Inversion Principle de 1996, publié dans l'Engineering Notebook pour Le rapport C++

Principe de substitution de Liskov (LSP)

Pourquoi ? Quiconque a affaire à des héritiers ne veut pas avoir de surprises s'il est familier avec les testateurs.
Mutabilité   
Correction   
Efficacité de la production   
Amélioration continue   
Développeur unique
Le principe de substitution de Liskov (LSP) est un SOLID principe. Il stipule que les sous-types doivent se comporter comme leur type de base. Cela semble banal au premier abord. L'exemple des exceptions montre clairement les problèmes qui surviennent lorsque ce principe est violé : Si le type de base ne déclenche pas d'exception lors de l'exécution d'une méthode, tous les sous-types doivent se conformer à cette règle. Si la méthode d'un sous-type déclenche néanmoins une exception, cela poserait des problèmes aux utilisateurs qui attendent un objet du type de base, car ils ne sont pas préparés à cela. Si le type de base ne déclenche pas d'exception à cet endroit, l'utilisateur n'est pas préparé à devoir gérer des exceptions. De manière plus générale, on peut également exprimer le principe de la manière suivante : un sous-type ne peut qu'étendre la fonctionnalité d'un type de base, mais pas la restreindre. Si une méthode du type de base est définie sur une plage de valeurs donnée, le sous-type peut reprendre cette plage de valeurs ou l'étendre, mais il ne peut en aucun cas la restreindre. Le principe de substitution de Liskov recommande également de réfléchir très attentivement à l'héritage. Dans la plupart des cas, la composition est préférable à l'héritage (Favor Composition over Inheritance). En ce qui concerne l'héritage, il convient dans tous les cas de réfléchir au comportement, et pas seulement à la structure. Au lieu d'utiliser l'héritage commeis-a relation et de ne considérer que la structure (des données), il vaut mieux parler d'une behaves-as et tenir compte du comportement de la classe.

Sources

Source Auteur Brève description
objectmentor Robert C. Martin Article sur le principe de substitution de Liskov de 1996, publié dans Engineering Notebook pour Le rapport C++

Principe de moindre astonisation

Pourquoi ? Si, par surprise, un composant se comporte différemment de ce qui était prévu, son utilisation devient inutilement compliquée et sujette à des erreurs.
Mutabilité   
Correction   
Efficacité de la production   
Amélioration continue   
Développeur unique
Le développement de logiciels est, dans une large mesure, un processus créatif. Dans ce processus, il est important de se plonger dans le flux (flow en anglais). Une fois cet état atteint, le code jaillit. Toute perturbation du flux entraîne des interruptions et, en fin de compte, peu de code est produit dans le temps imparti ou la qualité du code n'est pas optimale. En effet, après chaque interruption, le développeur doit d'abord reprendre la route et se remettre dans le flux. Les surprises constituent des perturbations. Elles entraînent des interruptions et des erreurs. Prenons un exemple : Si l'affectation des touches dans l'environnement de développement est telle qu'une combinaison de touches habituelle, comme par exemple Ctrl-C, a une signification totalement différente, cela gêne le développeur. Un développeur s'énervera à chaque fois qu'il utilisera la "mauvaise" combinaison de touches. Cela entrave le travail créatif. Les logiciels devraient être implémentés sans surprise. Si une méthode de requête appelée GetValue() ne fournit pas seulement une valeur, mais modifie en même temps l'état du système, le développeur évitera cette méthode dans le meilleur des cas, car il s'attend à de mauvaises surprises. Dans le pire des cas, il ne remarquera pas à temps ce comportement étrange. (Les méthodes d'interrogation qui modifient l'état sont contraires à la loi sur la protection des données. Séparation des requêtes de commande principe). Le développement piloté par les tests favorise les interfaces sans surprise, car l'interface est conçue et mise en œuvre du point de vue de son utilisation.

Principe de dissimulation de l'information

Pourquoi ? En masquant les détails dans une interface, les dépendances sont réduites.
Mutabilité   
Correction   
Efficacité de la production   
Amélioration continue   
Développeur unique
Lors de la conception d'une interface, il convient de se demander quels détails doivent absolument être visibles à l'extérieur. Par interface, on entend ici non seulement les interfaces au sens orienté objet, mais aussi les interfaces implicites. Chaque classe a nécessairement une interface implicite - elle contient tous les détails visibles de l'extérieur. Plus les détails sont visibles de l'extérieur, plus le couplage entre la classe et ses utilisateurs est élevé. Une fois que les utilisateurs d'une classe utilisent un détail, il devient difficile de modifier ce détail. Cela va à l'encontre de l'évolutivité du logiciel.

Pratiques

Tests d'unité automatisés

Pourquoi ? Seuls les tests automatisés sont exécutés de manière cohérente. Plus ils testent le code avec précision, mieux c'est.
Mutabilité   
Correction   
Efficacité de la production   
Amélioration continue   
Développeur unique
Sur le site degré orange nous avons introduit les tests d'intégration, nous nous intéressons maintenant aux tests unitaires. Contrairement aux tests d'intégration, les tests unitaires consistent à tester une seule unité fonctionnelle (surtout des classes, mais aussi des méthodes ou des composants) de manière isolée. Pour cela, il est nécessaire de pouvoir libérer cette unité fonctionnelle de ses dépendances. Si les tests unitaires doivent être complétés a posteriori pour le code existant, des refactorisations sont souvent nécessaires. Grâce aux tests d'intégration, nous avons la certitude de ne pas intégrer d'erreurs à cette occasion. Les tests automatisés offrent un double avantage :
  • Vous gagnez du temps
  • Ils prennent peur
Plus une base de code est en cours de modification, plus le gain de temps se fait sentir. Car là où le code change, il faut toujours tester les nouveautés et les anciens (tests de régression). L'automatisation permet tout simplement de gagner du temps. Et plus le code est complexe, plus la réduction de l'anxiété est importante. En effet, lorsqu'un code complexe doit être modifié - pour ajouter des fonctionnalités, l'optimiser ou tout simplement le corriger -, le risque d'introduire involontairement des erreurs est élevé. Des tests automatisés à petite échelle permettent toutefois de les détecter, de sorte qu'il n'y a aucune raison de craindre de "détériorer". Voir aussi sous Outils.

Mockups

Pourquoi ? Sans tests factices, pas de tests facilement contrôlables.
Mutabilité   
Correction   
Efficacité de la production   
Amélioration continue   
Développeur unique
En règle générale, les composants utilisent d'autres composants. Si l'on veut tester un composant de manière isolée, ces dépendances doivent être séparées. Nous nous intéressons ici uniquement à la fonctionnalité du composant à tester (Système sous test (SUT)). Et nous nous intéressons à la manière dont le composant interagit avec les autres. Lors de l'isolation, nous utilisons ce que l'on appelle des mockups. Celles-ci sont utilisées à la place des composants réels. Ainsi, pendant les tests, le système Under Test interagit avec des modèles factices bien contrôlables plutôt qu'avec des composants réels. La littérature connaît encore d'autres désignations pour les leurres, telles que Stub, Mannequin ou Fauxqui sont parfois utilisés comme synonymes de mockup, mais qui peuvent tout à fait être utilisés pour les différents modes de fonctionnement sont en place. Avant d'utiliser un framework de mock, comme par exemple Rhino Mocks il est préférable d'implémenter d'abord un mockup "à la main". Cela permet de mieux comprendre le mécanisme. Voir aussi sous Outils.

Analyse de la couverture de code

Pourquoi ? Ne te fie qu'aux tests dont tu sais qu'ils couvrent réellement la zone de test.
Mutabilité   
Correction   
Efficacité de la production   
Amélioration continue   
Développeur unique
Les tests unitaires doivent, dans la mesure du possible, couvrir tous les chemins de notre code. C'est la seule façon de nous assurer que le code fonctionne correctement. Pour savoir quelles parties du code n'ont pas encore été testées, nous utilisons l'outil de test de l'unité. Analyse de la couverture de code. Celle-ci sert à découvrir les zones du code qui ne sont pas encore exécutées lors des tests automatisés. Les tests unitaires devraient en principe couvrir 100% du code à tester. Certes, cela ne signifie pas automatiquement qu'il existe suffisamment de tests, mais moins de 100% de couverture de code indique qu'il existe encore des poches de code sur lesquelles il n'est pas du tout possible de faire des déclarations d'exactitude. Il faut donc toujours viser une couverture de code de 100%. Dans la pratique, il s'avère toutefois que la couverture de code de 100% ne peut pas toujours être atteinte avec un effort immédiatement justifiable. Comme dans la vie, l'effort pour les derniers 2,3,4 % peut croître de manière disproportionnée. C'est pourquoi, après une analyse précise de la situation en matière de couverture, il peut être acceptable de se contenter de moins de 100%. Toutefois, en dessous de 90%, la couverture est alors tellement trouée qu'elle peut être considérée comme non professionnelle. Celui qui commence à faire des tests automatiques devrait donc toujours mesurer en même temps la couverture du code. Sinon, il n'est pas possible de se prononcer sur la qualité des tests. Il existe deux indicateurs simples pour mesurer la couverture de code, appelés indicateurs C0 et C1. Le ratio C0 mesure la couverture des instructions, tandis que le ratio C1 mesure la couverture des décisions ou des branches.
C0 = (nombre d'instructions testées / nombre d'instructions totales) * 100%
C1 = (nombre de décisions/branches testées / nombre de décisions/branches totales) * 100%
C1 est le ratio le plus fort, car 100% de recouvrement de décision ou de recouvrement de branche implique 100% de recouvrement d'instruction. L'inverse n'est pas vrai. Le test de recouvrement d'instructions et le test de recouvrement de branches fonctionnent sur la base d'un graphe de flux de contrôle, voir http://de.wikipedia.org/wiki/KontrollflussgraphLe test de couverture de décision est quant à lui directement basé sur le code source. Le test de couverture des instructions et le test de couverture des branches sont très bien décrits dans la section http://de.wikipedia.org/wiki/Kontrollflussorientierte_Testverfahren décrites. Voir aussi sous Outils.

Participation aux événements professionnels

Pourquoi ? C'est par les autres et en communauté que nous apprenons le mieux.
Mutabilité   
Correction   
Efficacité de la production   
Amélioration continue   
Développeur unique
Pour ne pas rester "dans son jus", il est important de discuter régulièrement avec d'autres développeurs de logiciels et d'échanger des expériences. Pour voir plus loin que le bout de son nez, l'échange avec des développeurs devrait avoir lieu en dehors de sa propre équipe, de sa routine quotidienne. Les groupes d'utilisateurs, que l'on trouve dans toutes les régions d'Allemagne, conviennent parfaitement. Les groupes d'utilisateurs régionaux mettent l'accent sur l'échange d'expériences. C'est important. Mais plus il a lieu au sein du même groupe, plus on connaît ses interlocuteurs, plus les opinions se rapprochent, même au sein d'un groupe d'utilisateurs. C'est pourquoi il est important de toujours regarder plus loin que le bout de son nez. Les conférences interrégionales de développeurs offrent à cet effet de nouvelles idées et des discussions avec des développeurs très différents. Pour l'échange d'idées et l'inspiration, un CCD doit donc garder à l'esprit trois niveaux : sa propre équipe de développeurs, le groupe d'utilisateurs régional et la conférence interrégionale. Chaque niveau a son propre rythme : quotidien, mensuel, annuel. Liens :

Refactorings complexes

Pourquoi ? Il n'est pas possible d'écrire directement du code sous sa forme ultime.
Mutabilité   
Correction   
Efficacité de la production   
Amélioration continue   
Développeur unique
Déjà en degré rouge de simples refactorisations ont été introduites. Mais Renommer et Extraire la méthode ne suffisent pas à améliorer le code - des interventions plus importantes sont souvent nécessaires. La classification en refactorisations simples et complexes est judicieuse, car les refactorisations complexes ne peuvent être réalisées efficacement et sans risque qu'avec des tests automatisés existants. Sans tests, on ne saurait pas, après la refactorisation, si le code est toujours correct. Voir aussi sous refactoring-legacy-code.net ainsi que sur Outils. On continue avec le degré vert
fr_FRFrançais