Degré vert

Table des matières

Principes

Principe de fermeture ouverte (OCP)

Principe de fermeture ouverte (OCP)

Pourquoi ?
Parce que le risque d'instabilité d'un système jusque-là sans défaut par de nouvelles fonctionnalités doit être réduit au maximum.
Mutabilité  
Correction  
Efficacité de la production  
Amélioration continue  
Développeur unique

Le site Principe d'ouverture et de fermeture (OCP) stipule qu'une classe doit être ouverte aux extensions, mais fermée aux modifications. C'est un autre des SOLID Les principes. L'exemple de code suivant vise à illustrer où se situe le problème lorsque le principe n'est pas respecté :

public double Preis() {
    const decimal StammkundenRabatt = 0.95m ;
    switch(type de client) {
        case Type de client.client unique :
            return quantity * single price ;
        case Type de client.client régulier :
            return quantité * prix unitaire * remise client régulier ;
        default :
            throw new ArgumentOutOfRangeException() ;
    }
}

Le problème de cette forme d'implémentation est que la classe doit être modifiée si un autre type de calcul de prix est nécessaire. Le risque est que des erreurs soient commises lors de cette modification et que les fonctions déjà existantes ne fonctionnent plus correctement. Même si des tests unitaires et des tests d'intégration automatisés sont disponibles, il existe un risque de laisser de nouveaux bugs, car il n'est pas possible d'atteindre une couverture de test de 100 %. Nous cherchons donc une méthode qui permette d'étendre la classe sans avoir à modifier la classe elle-même. Cela peut se faire par exemple à l'aide du Modèles de stratégie peut être atteint :

interface publique IPCalculatrice de prix {
    double Prix(int quantité, double prix unitaire) ;
}

private IPCalculatrice de prix prixCalculatrice ;

public double Preis() {
    return preisRechner.Preis(quantité, prix unitaire) ;
}

public class Single Customer : IPreisRechner {
    public double Preis(int quantité, double prix unitaire) {
        return quantité * prix unitaire ;
    }
}

public class Stammkunde : IPreisRechner {
    const decimal Client régulierRéduction = 0.95m ;
    
    public double Preis(int quantité, double prix unitaire) {
        return quantity * single price * StammkundenRabatt ;
    }
}

Le calcul concret du prix est externalisé dans d'autres classes via une interface. Il est ainsi possible d'ajouter à tout moment de nouvelles implémentations de l'interface. La classe est ainsi ouverte aux extensions, mais en même temps fermée aux modifications. Le code existant peut être modifié, par exemple à l'aide du refactoring Remplacer Conditionnel par Stratégie être réaménagé de manière à respecter le principe de fermeture ouverte.

Sources

SourceAuteurBrève description
 Robert C. MartinArticle sur l'Open Closed Principle de 1996 publié pour The C++ Report
Tell, don't ask

Tell, don't ask

Pourquoi ?
Une grande cohésion et un couplage lâche sont des vertus. Les détails publics de l'état d'une classe contredisent cela.
Mutabilité  
Correction  
Efficacité de la production  
Amélioration continue  
Développeur unique

En termes un peu provocateurs, les classes ne devraient pas avoir de "property getter". Ceux-ci incitent l'utilisateur d'une classe à prendre des décisions sur la base des valeurs fournies par un objet. Ainsi, au lieu de dire à l'objet ce qu'il doit faire, on l'interroge pour ensuite faire des considérations extérieures sur l'état interne de l'objet.

L'un des principes clés de la programmation orientée objet est le suivant Cacher l'information (voir aussi à ce sujet le degré jaune). Aucune classe ne doit laisser apparaître à l'extérieur des détails indiquant comment elle est implémentée en interne. Si une classe a besoin d'un état interne pour son travail, celui-ci est typiquement stocké dans un champ interne. Si cette valeur est également visible à l'extérieur, les utilisateurs sont tentés d'utiliser l'état interne de l'objet pour prendre leurs propres décisions. La classe est ainsi rapidement reléguée à un simple stockage de données. Une implémentation dans laquelle un objet est informé de ce qu'il doit faire est dans tous les cas préférable. Ainsi, l'utilisateur n'a plus à se soucier de la manière dont la classe effectue la tâche en interne.

À la suite du Tell don't ask des objets comportementaux sont créés au lieu d'objets de stockage de données "stupides". L'interaction entre les objets est couplée de manière lâche, car les objets ne doivent pas faire d'hypothèses sur les objets qui collaborent. Mais ce n'est pas tout ! Si les objets ne publient pas leur état, ils conservent leur pouvoir de décision. La cohésion du code décisionnel augmente ainsi, car il est regroupé en un seul endroit.

Un exemple de code typique est présenté ci-dessous. Au lieu de demander tout d'abord si les messages de trace sont activés dans le logging (Ask), il faudrait demander directement à la bibliothèque de logging d'émettre le message de trace (Tell). La bibliothèque doit ensuite décider elle-même en interne si le message doit être logué ou non.

if (_logger.Trace()) {
_logger.TraceMsg("... un message... ") ;
}

Loi de Déméter (LoD)

Loi de Déméter (LoD)

Pourquoi ?
Les dépendances d'objets sur plusieurs maillons d'une chaîne de services entraînent un couplage étroit peu esthétique.
Mutabilité  
Correction  
Efficacité de la production  
Amélioration continue  
Développeur unique

Sur le site Loi de Déméter il s'agit de limiter l'interaction entre les objets à un niveau sain. On peut le décrire de manière simplifiée par "Don't talk to strangers". Selon la loi de Déméter, une méthode ne doit utiliser que les autres méthodes suivantes :

  • Méthodes de sa propre classe
  • Méthodes des paramètres
  • Méthodes des classes associées
  • Méthodes d'objets créés par l'utilisateur

Toutefois : il faut tenir compte du fait que de temps en temps, des classes de conservation de données pures ont également un sens. Il n'est bien sûr pas nécessaire d'appliquer la loi de Demeter à celles-ci. Il peut par exemple être tout à fait judicieux de répartir hiérarchiquement les données de configuration dans plusieurs classes, de sorte qu'il pourrait en résulter au final l'accès suivant à une valeur :

int margin = config.Pages.Margins.Left ;

Si l'on appliquait ici la loi de Demeter, seul l'accès à config.Pages serait autorisé.

Pratiques

Intégration continue (CI)

Intégration continue (CI)

Pourquoi ?
L'automatisation et la centralisation de la production de logiciels rendent plus productif et réduisent le risque d'erreurs lors de la livraison.
Mutabilité  
Correction  
Efficacité de la production  
Amélioration continue  
Équipe

Souvent, l'intégration des composants logiciels est repoussée dans le temps et se fait "à la main", ce qui est coûteux et source d'erreurs. En réalité, le logiciel devrait être entièrement opérationnel à tout moment. L'intégration continue est un processus qui veille à ce que l'ensemble du code soit traduit et testé après la transmission des modifications.

Le processus d'intégration continue est particulièrement important pour les équipes, car il garantit qu'après la transmission des modifications, l'ensemble du code est traduit et testé, et pas seulement la partie sur laquelle un développeur vient de travailler. Les tests automatisés devraient être exécutés par chaque développeur avant de transmettre les modifications au contrôle de version central. L'intégration continue ne change rien à cela. Pour s'assurer que les tests sont effectivement exécutés et que les erreurs sont détectées à temps, ils sont dans tous les cas exécutés sur le serveur d'intégration continue. Cela ne dispense pas le développeur d'exécuter les tests avant le commit, car un code erroné qui a été enregistré dans le contrôle de version entrave toute l'équipe, voire d'autres équipes. Le processus d'intégration continue permet ainsi de garantir que les erreurs sont détectées le plus tôt possible par l'ensemble de l'équipe.

De nombreux outils sont disponibles pour le processus d'intégration continue Outils logiciels est disponible. Outre la construction et le test continus, qui ont lieu immédiatement lorsque les modifications sont transférées dans le contrôle de version, l'intégration continue permet également d'automatiser des processus plus longs, comme les tests de base de données. Ceux-ci ne sont alors exécutés que la nuit, par exemple. Dans le degré vert, seul le processus de build et de test est pris en compte. L'installation et le déploiement continus du logiciel n'interviennent que plus tard dans le processus. degré bleu.

Martin Fowler a rédigé un très bon article sur ce sujet, à lire sous http://www.martinfowler.com/articles/continuousIntegration.html

Voir aussi sous Outils.

Analyse de code statique

Analyse de code statique

Pourquoi ?
La confiance, c'est bien, le contrôle, c'est mieux - et plus il est automatique, plus il est facile.
Mutabilité  
Correction  
Efficacité de la production  
Amélioration continue  
Développeur unique

Comment se définit la qualité d'une unité de code, par exemple une classe ou un composant ? Suffit-il qu'elle réponde fonctionnellement aux exigences du client ? Suffit-il qu'elle soit suffisamment rapide et évolutive ? Les tests automatiques et finalement les tests effectués par le client fournissent en effet des informations à ce sujet. Sans une telle conformité aux exigences, le logiciel n'a évidemment pas de qualité pertinente. S'il n'est pas utile au client, toute autre question est superflue.

D'un autre côté, contrairement à une idée encore largement répandue, il ne suffit pas non plus d'être conforme aux exigences. Une qualité élevée ne résulte pas uniquement de la fonctionnalité et, par exemple, de la performance. En effet, outre les exigences fonctionnelles et non fonctionnelles, il existe également une exigence cachée qui n'est généralement pas exprimée : les clients veulent toujours que le logiciel ne réponde pas seulement à leurs exigences actuelles, mais également à celles de demain et d'après-demain. Les clients veulent une protection de leur investissement grâce à l'évolutivité.

Pour les clients, cette exigence est généralement implicite. Ils pensent qu'il va de soi qu'un produit immatériel tel qu'un logiciel peut être adapté à de nouvelles exigences quasiment à l'infini et en appuyant sur un bouton. Même les cadres qui ne sont pas issus du développement de logiciels le croient souvent. Et même les développeurs de logiciels eux-mêmes !

Le malentendu sur les logiciels ne pourrait cependant pas être plus grand. La mutabilité ne va pas de soi dans le sens d'un objectif que tout développeur de logiciels poursuit de toute façon, et elle ne découle pas non plus de quelque chose de quasi automatique. Elle doit être constamment mise en balance avec d'autres valeurs.

Si la conformité aux exigences peut être vérifiée par des tests (automatisés), qu'en est-il de la mutabilité ? La qualité du code en termes de (sur)viabilité peut-elle également être mesurée automatiquement ? En partie. Tous les aspects qui rendent un logiciel évolutif ne peuvent pas être testés automatiquement. Par exemple, il n'est pas possible de déterminer automatiquement si un logiciel est ouvert aux extensions grâce à un concept de module complémentaire.

Néanmoins, il existe MétriquesLa valeur d'un logiciel peut être "calculée". Outils aident dans ce sens. Ces outils devraient donc être utilisés dans chaque projet de logiciel.

  • Pour le code hérité, les outils permettent d'établir le statu quo et de définir ainsi une ligne de base à laquelle comparer l'évolution ultérieure du code (vers une amélioration).
  • Pour le nouveau code qui a été planifié en gardant à l'esprit la mutabilité, une telle analyse statique du code montre s'il répond à l'idéal de la planification.

Les CCD ne se contentent pas de tester le code de manière automatisée. Ils gardent aussi toujours un œil sur sa mutabilité, car ils savent que les clients s'y intéressent tout autant - qu'ils l'aient dit explicitement ou non.

Voir aussi sous Outils.

Inversion du conteneur de contrôle

Inversion du conteneur de contrôle

Pourquoi ?
Seul ce qui n'est pas câblé en permanence peut être reconfiguré plus facilement.
Mutabilité  
Correction  
Efficacité de la production  
Amélioration continue  
Développeur unique

Déjà en degré jaune le CCD a appris le Dependency Inversion Principle. Dans ce contexte, les dépendances ont encore été résolues "à la main". L'étape logique suivante consiste à automatiser la résolution des dépendances. Deux méthodes sont disponibles à cet effet :

  • Localisateur
  • Conteneur

Les deux utilisent ce qu'on appelle un Inversion du conteneur de contrôle (conteneur IoC). Avant d'utiliser le conteneur, les classes utilisées doivent être déposées dans le conteneur. Ensuite, le conteneur peut fournir des instances des classes déposées. Pour Localisateur cela se fait explicitement. Cela présente l'avantage que les dépendances ne doivent pas toutes être mentionnées dans le constructeur de la classe. Pour les tâches transversales comme par exemple Enregistrement il s'agit d'une procédure courante. En règle générale, les dépendances sont toutefois listées comme paramètres du constructeur. Cela présente l'avantage que toutes les dépendances sont visibles. Le conteneur est ainsi en mesure de résoudre implicitement les dépendances en instanciant récursivement tous les objets nécessaires via le conteneur.

Les conteneurs IoC deviennent importants dès que le nombre de classes augmente. Si l'on Séparation des préoccupations on obtient de nombreuses petites classes avec des tâches gérables. L'assemblage d'instances de ces classes est d'autant plus complexe. C'est là qu'intervient le conteneur IoC, qui aide à instancier et à relier les nombreux petits objets.

Un autre avantage des conteneurs IoC est le fait que le Cycle de vie d'un objet peut être déterminée par configuration. S'il ne doit y avoir qu'une seule instance d'un objet au moment de l'exécution (Singleton), il est possible d'ordonner au conteneur de toujours fournir une seule et même instance. D'autres cycles de vie, comme par exemple une instance par session sont soutenus.

Pour ne pas être dépendant d'un conteneur IoC particulier lors de l'utilisation d'un localisateur, le Localisateur de services communs Microsoft (voir Outils) peut être utilisé. Celui-ci offre une interface unifiée avec les conteneurs IoC courants.

Pour comprendre la mécanique qui se cache derrière un conteneur IoC, il est utile d'implémenter soi-même la fonctionnalité. Il ne s'agit pas d'implémenter un conteneur complet, mais seulement les fonctions de base.

Voir aussi sous Outils.

Partager l'expérience

Partager l'expérience

Pourquoi ?
Transmettre son savoir, c'est non seulement aider les autres, mais aussi s'aider soi-même.
Mutabilité  
Correction  
Efficacité de la production  
Amélioration continue  
Développeur unique

Un travail professionnel implique bien entendu des connaissances constamment actualisées. Cela ne signifie évidemment pas que n'importe qui peut et doit tout savoir sur le développement de logiciels, ne serait-ce que sur la plate-forme .NET. Les connaissances actuelles se rapportent à ses propres spécialités, quelles qu'elles soient. C'est pourquoi la pratique consistant à s'informer régulièrement par le biais de différents médias fait partie intégrante d'autres degrés.

Cependant, pour plusieurs raisons, cette collecte d'informations ne devrait être qu'une des deux faces de la médaille "apprentissage". L'autre est le transfert d'informations, la transmission des connaissances. Selon nous, le véritable professionnalisme ne se limite pas à la "recherche", mais inclut également l'"enseignement". En effet, ce n'est qu'avec l'"enseignement" qu'ont lieu la véritable réflexion et la pénétration d'un objet.

Appliquer ce que l'on a entendu/lu est une chose. Bien sûr, on remarque aussi des lacunes de compréhension. Mais l'"exploration" d'un objet est naturellement limitée par son utilisation. Celui qui n'explore que dans la mesure où il a besoin d'une technologie/d'un concept sur le moment ne s'immerge pas forcément en profondeur.

En revanche, il en va tout autrement lorsque l'apprentissage se fait sous le signe de la transmission. Celui qui n'apprend pas seulement pour lui-même, mais aussi toujours pour les autres, apprend plus profondément. Cela devient évident lorsque l'on essaie de transmettre ce que l'on a (soi-disant) appris à d'autres. Si l'on ne garde pas cela à l'esprit pendant l'apprentissage, des questions que l'on ne s'est jamais posées soi-même surgissent rapidement. Les autres ont toujours un point de vue complètement différent.

C'est pourquoi nous pensons que seul celui qui s'expose régulièrement à l'enseignement, à la transmission et au partage de connaissances apprend de manière vraiment solide. Seul celui qui ne se contente pas d'appliquer ce qu'il a appris, mais qui le formule avec ses propres mots pour un public, remarque au cours du processus la profondeur réelle de ses connaissances. Car si les points d'interrogation s'accumulent chez les "élèves", c'est que quelque chose ne va pas encore.

Un public réel est bien sûr le meilleur pour cela. Chaque CCD devrait donc chercher le plus régulièrement possible des occasions de partager ses connaissances oralement (par exemple lors d'événements entre collègues ou de réunions de groupes d'utilisateurs). Il est ainsi assuré d'un retour immédiat. L'expression écrite des compétences est également une bonne alternative ou un complément. Un blog peut être créé en cinq minutes et les revues spécialisées sont constamment à la recherche de nouveaux auteurs. Le feed-back n'est pas aussi direct, mais la formulation textuelle des connaissances est un très bon exercice.

Les développeurs Clean Code à partir du niveau vert n'apprennent donc pas seulement "passivement" en absorbant des informations, mais "activement" en transmettant leurs connaissances par le biais de présentations ou de textes. Cela peut paraître inhabituel - mais l'intégration continue l'est peut-être aussi. Dans tous les cas, la transmission active des connaissances est un bon exercice pour approfondir ses propres compétences, selon la devise : "Fais le bien et parles-en" ;-)

Il va de soi que "l'enseignement" présente également des avantages pour les auditeurs/lecteurs. Les avantages pour les autres ne sont toutefois pas aussi motivants que les avantages personnels. C'est pourquoi nous insistons ici surtout sur les avantages de la transmission de connaissances pour le développeur Clean Code.

Mesure de l'erreur

Mesure de l'erreur

Pourquoi ?
Seuls ceux qui connaissent le nombre d'erreurs peuvent modifier leur approche de manière à réduire le taux d'erreurs.
Mutabilité  
Correction  
Efficacité de la production  
Amélioration continue  
Équipe

Des erreurs se produisent pendant le développement de logiciels. Elles se produisent à toutes les étapes : des exigences mal comprises ou formulées de manière peu claire entraînent des erreurs, tout comme des implémentations défectueuses. Au final, tout est une erreur, ce qui fait que le client reçoit un logiciel qui ne correspond pas à ses exigences. L'approche itérative et la réflexion sont deux éléments qui servent à améliorer le processus. Toutefois, pour savoir si une amélioration est effectivement en cours, il faut disposer d'un indicateur de mesure qui permette de constater une évolution vers une amélioration.

La mesure des erreurs peut se faire par comptage ou par chronométrage. La précision n'est pas au premier plan, tant que la méthode de mesure fournit des données comparables. La tendance de développement sur plusieurs itérations doit être visible. En outre, il ne s'agit pas de déterminer la responsabilité d'une erreur. Au final, peu importe qui est à l'origine de l'erreur, tant que l'équipe en tire des enseignements et améliore son processus.

Quelles sont les erreurs à mesurer ? Ce ne sont pas les erreurs qui surviennent pendant le développement. Elles sont inévitables et permettent, espérons-le, de livrer un produit sans défaut à la fin d'une itération. Il s'agit plutôt des erreurs signalées par le client ou son représentant (par exemple le chef de produit ou le support) après une itération. Ce sont des erreurs qui entravent la mise en œuvre de nouvelles exigences. Les erreurs à mesurer sont donc celles qui se produisent quand on pense qu'elles ne devraient pas exister ;-) Le moment où une équipe atteint ce point dans le processus et se met à jurer parce qu'il y a encore une erreur dans le reste du travail, doit être déterminé individuellement pour chaque équipe.

On continue avec le degré bleu.

fr_FRFrançais