Le principe de responsabilité unique est que votre code ne fait qu'une seule chose et vous pouvez diviser toutes les fonctionnalités en plusieurs classes qui sont toutes destinées à faire 1 chose spécifique. Un exemple est une classe spécifique pour la validation, faire de la logique métier, enrichir un modèle, récupérer des données, mettre à jour des données, navigation, etc.
La séparation des préoccupations concerne le fait que votre code n'est pas étroitement couplé à d'autres classes / systèmes. L'utilisation d'interfaces dans votre code aide beaucoup, de cette façon, vous pouvez coupler de manière lâche les classes / systèmes à votre code. Un avantage de cela est qu'il est plus facile de tester également votre code. Il existe de nombreux frameworks (IoC) qui peuvent vous aider à y parvenir, mais vous pouvez également implémenter une telle chose vous-même.
Un exemple de quelque chose de SoC, mais sans SRP
public class Foo
{
private readonly IValidator _validator;
private readonly IDataRetriever _dataRetriever;
public Foo(IValidator validator, IDataRetriever dataRetriever)
{
_validator = validator;
_dataRetriever = dataRetriever;
}
public NavigationObject GetDataAndNavigateSomewhereIfValid()
{
var data = _dataRetriever.GetAllData();
if(_validator.IsAllDataValid(data))
{
object b = null;
foreach (var item in data.Items)
{
b = DoSomeFancyCalculations(item);
}
if(_validator.IsBusinessDataValid(b))
{
return ValidBusinessLogic();
}
}
return InvalidItems();
}
private object DoSomeFancyCalculations(object item)
{
return new object();
}
private NavigationObject ValidBusinessLogic()
{
return new NavigationObject();
}
private NavigationObject InvalidItems()
{
return new NavigationObject();
}
}
Comme vous pouvez le voir, ce code n'est pas étroitement couplé à des classes ou à d'autres systèmes, car il n'utilise que certaines interfaces pour faire des choses. C'est bon d'un point de vue SoC.
Comme vous pouvez le voir, cette classe contient également 3 méthodes privées qui font des choses fantaisistes. D'un point de vue SRP, ces méthodes devraient probablement être placées dans certaines classes qui leur sont propres. 2 d'entre eux font quelque chose avec la navigation, ce qui correspondrait à une classe d'INavigation. L'autre fait quelques calculs fantaisistes sur un élément, cela pourrait probablement être placé dans une classe IBusinessLogic.
Ayant quelque chose comme ça, vous avez tous les deux le SoC et le SRP en place:
public class Foo
{
private readonly IValidator _validator;
private readonly IDataRetriever _dataRetriever;
private readonly IBusinessLogic _businessLogic;
private readonly INavigation _navigation;
public Foo(IValidator validator, IDataRetriever dataRetriever, IBusinessLogic businessLogic, INavigation navigation)
{
_validator = validator;
_dataRetriever = dataRetriever;
_businessLogic = businessLogic;
_navigation = navigation;
}
public NavigationObject GetDataAndNavigateSomewhereIfValid()
{
var data = _dataRetriever.GetAllData();
if(_validator.IsAllDataValid(data))
{
object b = null;
foreach (var item in data.Items)
{
b = _businessLogic.DoSomeFancyCalculations(item);
}
if(_validator.IsBusinessDataValid(b))
{
return _navigation.ValidBusinessLogic();
}
}
return _navigation.InvalidItems();
}
}
Bien sûr, vous pourriez débattre si toute cette logique devrait être placée dans la GetDataAndNavigateSomewhereIfValid
méthode. C'est quelque chose que vous devez décider vous-même. Pour moi, il semble que cette méthode fasse beaucoup trop de choses.
En ce qui concerne le SRP appliqué uniquement au niveau de la classe, dans ses livres, Robert C. Martin (pour autant que je sache qu'il a popularisé sinon proposé le concept) déclare:
Code propre, page. 138 : "Le principe de responsabilité unique (PRS) stipule qu'une classe ou un module doit avoir une et une seule raison de changer."
Dans Agile Principles, Patterns and Practices in C #, page 116 : "[...] et associez la cohésion aux forces qui font changer un module ou une classe".
Je souligne.
Dans APPP, il parle plus longuement de SRP et se concentre presque entièrement sur le niveau de la classe. Bien qu'il semble se concentrer sur le niveau de la classe, je pense que le principe est également dirigé vers les modules et autres constructions de niveau supérieur.
Pour une telle raison, je ne qualifierais pas SRP de SoC au niveau de la classe comme vous le suggérez dans votre question.
la source
Vous trouverez ici une courte vidéo expliquant clairement la différence entre ces terminologies. https://www.youtube.com/watch?v=C7hkrV1oaSY
Séparation des préoccupations (SoC). Divisez votre application en fonctionnalités distinctes avec le moins de chevauchement de fonctionnalités possible. (Microsoft).
"Concern" = "caractéristique distincte" = "section distincte"
«Concern» fonctionne à des niveaux élevés et faibles
Le principe de responsabilité unique stipule que chaque module ou classe doit avoir la responsabilité d'une seule partie des fonctionnalités fournies par le logiciel, et que la responsabilité doit être entièrement encapsulée par la classe. Tous ses services devraient être étroitement alignés sur cette responsabilité. (Définition Wikipedia)
«Responsabilité» = «raison de changer»
changer quoi? «Une seule partie des fonctionnalités fournies par le logiciel» = Unité de base
Conclusion
Le principe de responsabilité unique fonctionne sur les unités de base -> fonctionne à bas niveau
La séparation des préoccupations fonctionne à des niveaux élevés et faibles
SRP et SoC travaillent ensemble pour séparer les préoccupations. Ils sont exactement les mêmes à bas niveau
la source
Voici ma compréhension de ces principes.
La séparation des préoccupations (SoC) - consiste à diviser un système logiciel en modules plus petits, chacun de ces modules est responsable d'une seule préoccupation. Une préoccupation, dans ce cas, est une fonctionnalité ou un cas d'utilisation d'un système logiciel. Un module possède une API (interface) bien définie, ce qui rend l'ensemble du système très cohérent. Il existe deux types principaux: horizontal et vertical.
Principe de responsabilité unique (SRP) - est un principe de conception qui stipule que chaque bloc de construction (il peut s'agir d'une classe, d'un module, d'un objet ou même d'une fonction) d'un système ne devrait avoir qu'une seule responsabilité. Robert C. Martin. Martin décrit une responsabilité comme une raison de changer. En général, il est préférable d'avoir une seule classe / un seul objet qui a la responsabilité d'une seule partie de la fonctionnalité au lieu de pouvoir exécuter un grand nombre de fonctions, parfois même sans rapport, ce qui rend cette classe grande et étroitement couplée, donc- appelé «objet de Dieu».
J'ai également décrit ces principes plus en détail dans mon article de blog, veuillez jeter un œil.
https://crosp.net/blog/software-architecture/srp-soc-android-settings-example/
la source