Principe de responsabilité unique en Java

1. Vue d'ensemble

Dans ce didacticiel, nous discuterons du principe de responsabilité unique, en tant que l'un des principes SOLID de la programmation orientée objet.

Dans l'ensemble, nous allons approfondir ce qu'est ce principe et comment le mettre en œuvre lors de la conception de notre logiciel. De plus, nous expliquerons quand ce principe peut être trompeur.

* SRP = Principe de responsabilité unique

2. Principe de responsabilité unique

Comme son nom l'indique, ce principe stipule que chaque classe doit avoir une responsabilité, un seul objectif . Cela signifie qu'une classe ne fera qu'un seul travail, ce qui nous amène à conclure qu'elle ne devrait avoir qu'une seule raison de changer .

Nous ne voulons pas d'objets qui en savent trop et qui ont un comportement sans rapport. Ces classes sont plus difficiles à maintenir. Par exemple, si nous avons une classe que nous changeons beaucoup, et pour différentes raisons, alors cette classe devrait être décomposée en plusieurs classes, chacune traitant une seule préoccupation. Sûrement, si une erreur se produit, elle sera plus facile à trouver.

Considérons une classe qui contient du code qui modifie le texte d'une manière ou d'une autre. Le seul travail de cette classe devrait être de manipuler du texte .

public class TextManipulator { private String text; public TextManipulator(String text) { this.text = text; } public String getText() { return text; } public void appendText(String newText) { text = text.concat(newText); } public String findWordAndReplace(String word, String replacementWord) { if (text.contains(word)) { text = text.replace(word, replacementWord); } return text; } public String findWordAndDelete(String word) { if (text.contains(word)) { text = text.replace(word, ""); } return text; } public void printText() { System.out.println(textManipulator.getText()); } }

Bien que cela puisse sembler correct, ce n'est pas un bon exemple de SRP. Ici, nous avons deux responsabilités : manipuler et imprimer le texte .

Avoir une méthode qui imprime du texte dans cette classe enfreint le principe de responsabilité unique. Pour cela, nous devons créer une autre classe, qui ne gérera que l'impression du texte:

public class TextPrinter { TextManipulator textManipulator; public TextPrinter(TextManipulator textManipulator) { this.textManipulator = textManipulator; } public void printText() { System.out.println(textManipulator.getText()); } public void printOutEachWordOfText() { System.out.println(Arrays.toString(textManipulator.getText().split(" "))); } public void printRangeOfCharacters(int startingIndex, int endIndex) { System.out.println(textManipulator.getText().substring(startingIndex, endIndex)); } }

Maintenant, dans cette classe, nous pouvons créer des méthodes pour autant de variantes d'impression de texte que nous le voulons, car c'est son travail.

3. En quoi ce principe peut-il être trompeur?

L'astuce pour implémenter SRP dans notre logiciel est de connaître la responsabilité de chaque classe.

Cependant, chaque développeur a sa vision de l'objectif de la classe , ce qui rend les choses délicates. Comme nous n'avons pas d'instructions strictes sur la façon de mettre en œuvre ce principe, nous nous retrouvons avec nos interprétations de la responsabilité.

Cela signifie que parfois seuls nous, en tant que concepteurs de notre application, pouvons décider si quelque chose est dans la portée d'une classe ou non.

Lors de l'écriture d'une classe selon le principe SRP, nous devons penser au domaine du problème, aux besoins métier et à l'architecture de l'application. C'est très subjectif, ce qui rend la mise en œuvre de ce principe plus difficile qu'il n'y paraît. Ce ne sera pas aussi simple que l'exemple que nous avons dans ce tutoriel.

Cela nous amène au point suivant.

4. Cohésion

Suivant le principe SRP, nos classes adhéreront à une fonctionnalité. Leurs méthodes et leurs données seront concernées par un objectif clair. Cela signifie une cohésion élevée, ainsi qu'une robustesse, qui réduisent ensemble les erreurs .

Lors de la conception d'un logiciel basé sur le principe SRP, la cohésion est essentielle, car elle nous aide à trouver des responsabilités uniques pour nos classes. Ce concept nous aide également à trouver des classes qui ont plus d'une responsabilité.

Revenons à nos méthodes de classe TextManipulator :

... public void appendText(String newText) { text = text.concat(newText); } public String findWordAndReplace(String word, String replacementWord) { if (text.contains(word)) { text = text.replace(word, replacementWord); } return text; } public String findWordAndDelete(String word) { if (text.contains(word)) { text = text.replace(word, ""); } return text; } ...

Ici, nous avons une représentation claire de ce que fait cette classe: Manipulation de texte.

Mais si nous ne pensons pas à la cohésion et que nous n'avons pas une définition claire de la responsabilité de cette classe, nous pourrions dire que l'écriture et la mise à jour du texte sont deux tâches différentes et séparées. Animés de cette réflexion, nous pouvons conclure que ceux-ci devraient être deux classes distinctes: WriteText et UpdateText .

En réalité, nous obtiendrions deux classes étroitement couplées et faiblement cohésives , qui devraient presque toujours être utilisées ensemble. Ces trois méthodes peuvent effectuer des opérations différentes, mais elles servent essentiellement un seul objectif : la manipulation de texte. La clé est de ne pas trop réfléchir.

L'un des outils qui peuvent aider à atteindre une forte cohésion dans les méthodes est le LCOM. Essentiellement, LCOM mesure la connexion entre les composants de classe et leur relation les uns avec les autres.

Martin Hitz et Behzad Montazeri ont présenté LCOM4, ​​que Sonarqube a mesuré pendant un certain temps, mais qui est depuis obsolète.

5. Conclusion

Même si le nom du principe est explicite, nous pouvons voir combien il est facile de mettre en œuvre de manière incorrecte. Assurez-vous de distinguer la responsabilité de chaque classe lors du développement d'un projet et accordez une attention particulière à la cohésion.

Comme toujours, le code est disponible sur GitHub.