Comme nous le savons, le SRP indique que chaque classe devrait avoir une responsabilité unique et que la responsabilité doit être entièrement encapsulée par la classe.
Mais setters et getters servent une autre responsabilité - Ils font accès à une classe abstraite (données).
si Setteurs et getters Accédez à la propriété de la classe abstraite, puis ils servent une autre responsabilité .
Donc, si j'ai quelque chose comme ça,
class Config
{
private location;
public function write(array $data)
{
....
}
public function read($key)
{
...
}
public function exists($key)
{
...
}
public function delete($key)
{
...
}
// Below comes property abstraction
// Here I doubt - I CANNOT USE this class without them
// but they seem to break the SRP at the same time!?
public function setFileLocation($location)
{
$this->location = $location;
}
public function getFileLocation()
{
return $this->location;
}
public function setConfigArray(...)
{
...
}
public function getConfigArray()
{
...
}
}
Je brise le SRP. Le problème est que c'est que le seul moyen de classe peut exister.
La question est donc,
Dans ma situation, il est presque impossible d'éviter setFileLocation()
et getFileLocation()
Méthodes avec CRUD.
Donc, si vous combinez des méthodes de crud avec l'abstraction d'accès aux données, je brise le SRP,
Est-ce que je peux adhérer le SRP et garder le concept commun de la classe de configuration (opérations de crud) en même temps?
Honnêtement, je pense que vous prenez un peu trop la responsabilité unique. Les getters and Setters sont accessoires au fonctionnement de la classe si vous le faites par accès direct aux membres publics ou à utiliser des méthodes (ou des propriétés) pour le faire.
Vous faites l'argument selon lequel obtenir et définir un membre de la classe est une responsabilité distincte et devrait donc être déplacé ailleurs. Disons que nous faisons cela, et maintenant vous avez des cours appelés Config
et ConfigAccessor
. À ce stade, vous avez maintenant un écart d'air entre les deux classes, car Config
n'a aucune interface pour accéder à son membre location
. Cela rend impossible d'écrire ConfigAccessor
, et vous êtes laissé avec une classe immuable et une fois écrits qui ne convient pas à ce que ce soit. Si vous ajoutez une sorte d'interface pour permettre ConfigAccessor
de faire son travail, vous vous trouverez avec un problème récursif.
Le SRP, comme beaucoup d'autres choses dans ce domaine, c'est un principe, pas une règle dure et rapide. Cela signifie que vous devriez appliquer un jugement à votre situation au lieu d'essayer de le suivre inconditionnellement. Il y a une ligne entre être un puriste et faire le travail, et lorsque le premier empêche ce dernier, vous êtes du mauvais côté.
Si je peux critiquer votre design un peu: si votre classe Config
_ est conçue pour être une interface entre un fichier de configuration stocké sur le disque et votre code, la dernière chose que vous souhaitez faire est de changer son emplacement Midstream. Si vous modifiez le location
comme moyen de démarrer l'accès à un fichier différent, vous devez détruire l'ancien objet et en créer un nouveau. Vous n'avez pas précisé si vous avez l'intention de stocker le contenu du fichier dans l'objet. Si vous aviez envisagé de l'utiliser comme moyen d'inhaler le contenu d'un fichier de configuration et d'écrire à un autre, envisagez d'utiliser une méthode qui clone les données dans un nouvel objet qui pointe sur le nouveau fichier.
Il y a deux niveaux distincts à laquelle vous pouvez appliquer le SRP.
Le premier niveau est le niveau de fonctions/méthodes individuelles. Chacun devrait faire une seule tâche (et en juger par les noms de méthodes, aucune des méthodes de Config
casser le SRP).
Le deuxième niveau est le niveau d'une classe. Ici, le concept d'une seule responsabilité devient un peu plus abstrait, mais un bon indicateur est si vous pouvez indiquer les responsabilités d'une classe dans une phrase sans l'utilisation (implicite) du mot et. Si vous pouvez le faire avec la présence des getters et des setters, la classe ne casse pas le SRP.
En général, getters et, dans une moindre mesure, des setters sont , cependant, une indication que l'encapsulation d'une classe est cassée. Dans le cas de la classe Config
, la méthode setFileLocation
est bonne, car Config
nécessite un moyen de savoir où se trouve les données, mais les autres semblent suspectes, Parce qu'ils exposent des informations que les utilisateurs de Config
ne devraient pas avoir besoin de nécessité.