.Net principes SOLID : Open/Closed principles
Les principes SOLID font partie des principes « de base » de l’informatique qui permettent de faire du code propre, maintenable et évolutif. En effet, cet acronyme décrit 5 principes distincts, que nous allons analyser au fur et à mesure de 5 articles distincts.
Nous continuons notre série avec le O, pour « Open/Closed principle ».
Définition
Le principe Open/Closed est assez simple : votre code doit être ouvert à l’extension mais fermé à la modification. Bien sûr, pour ce dernier point, un petit bémol : la modification du code pour correction de bug est TOUJOURS autorisée… (n’allez pas utiliser cet article pour trouver une excuse à ne pas corriger votre code !)
Le but de ce principe est donc de tendre, non plus vers des objets immuables, mais vers des objets auxquels les clients pourront ajouter de nouveaux comportements sans en modifier la mécanique interne.
Prenons l’exemple suivant : j’ai une classe qui calcule la surface de formes géométriques, et j’ai deux formes de définies :
public class Square
{
public int Side { get; set; }
}
public class Rectangle
{
public int Height { get; set; }
public int Width { get; set; }
}
public class AreaCalculator
{
public int ComputeArea(object shape)
{
if(shape is Square s) return s.Side * s.Side;
else if(shape is Rectangle r) return r.Height * r.Width;
return 0;
}
}On peut voir une succession de if et else if dans la méthode pour gérer les différents cas de figure. Que se passe-t-il si une nouvelle forme fait son apparition ? Il sera nécessaire de modifier la méthode précédent afin de rajouter un else if. Cela devrait vous mettre la puce à l’oreille : on doit modifier notre code pour gérer un nouveau cas !
Solution
Ici, la POO peut nous sauver grâce à l’héritage. Il faudra déplacer le comportement de calcul dans une classe commune à toutes les formes, et faire en sorte que la classe AreaCalculator soit la consommatrice de cette méthode. Ainsi, les nouvelles formes devront déclarer comment leur surface est calculée !
public abstract class Shape
{
public abstract int ComputeArea();
}
public class Square : Shape
{
public int Side { get; set; }
public override int ComputeArea() => Side * Side;
}
public class Rectangle: Shape
{
public int Height { get; set; }
public int Width { get; set; }
public override int ComputeArea() => Height * Width;
}
public class AreaCalculator
{
public int ComputeArea(Shape shape)
{
return shape.ComputeArea();
}
}On voit déjà une amélioration rapide : plus d’utilisation de la classe object (et donc de boxing/unboxing avec des appels potentiellement faux) mais ici une utilisation d’une définition de base commune ! Finalement, ajouter une nouvelle forme n’aura aucun impact sur notre classe AreaCalculator, le cas sera automatiquement géré !
Laisser un commentaire