Wie wir wissen, besagt die SRP, dass jede Klasse eine einzige Verantwortung haben sollte und dass die Verantwortung vollständig von der Klasse gekapselt werden muss.
Aber Getter und Setter tun eine andere Verantwortung dienen - sie tun abstrakte Klasse Eigenschaft (Daten) Zugang.
Wenn Setter und Getter auf abstrakte Klasseneigenschaften zugreifen, dienen sie einer anderen Verantwortung .
Also, wenn ich so etwas habe,
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()
{
...
}
}
Ich breche die SRP. Das Problem ist, dass nur so eine Klasse existieren kann.
Die Frage ist also:
In meiner Situation ist es fast unmöglich zu vermeiden setFileLocation()
und getFileLocation()
mit CRUD diejenigen Methoden.
Wenn ich also durch die Kombination von CRUD-Methoden mit der Datenzugriffsabstraktion die SRP unterbreche,
Gibt es eine Möglichkeit, die SRP einzuhalten und gleichzeitig das gemeinsame Konzept der Config-Klasse (CRUD-Operationen) beizubehalten?
Antworten:
Ehrlich gesagt denke ich, dass Sie das Konzept der Einzelverantwortung etwas zu weit führen. Getter und Setter sind für das Funktionieren der Klasse von Bedeutung, unabhängig davon, ob Sie dies durch direkten Zugriff auf öffentliche Mitglieder tun oder Methoden (oder Eigenschaften) verwenden, um dies zu tun.
Sie machen das Argument, dass das Erhalten und Setzen eines Mitglieds der Klasse eine separate Verantwortung ist und daher an einen anderen Ort verlegt werden sollte. Nehmen wir an, wir machen das, und jetzt haben Sie Klassen namens
Config
undConfigAccessor
. Zu diesem Zeitpunkt haben Sie jetzt einen Luftspalt zwischen den beiden Klassen, daConfig
keine Schnittstelle für den Zugriff auf daslocation
Mitglied vorhanden ist. Das macht es unmöglich zu schreibenConfigAccessor
, und Sie haben eine unveränderliche, einmal schreibende Klasse, die überhaupt keinen Nutzen hat. Wenn Sie eine Art Schnittstelle hinzufügen, umConfigAccessor
ihre Arbeit zu erledigen, haben Sie ein rekursives Problem.Die SRP ist, wie viele andere Dinge in diesem Bereich, ein Prinzip, keine feste Regel. Das bedeutet, dass Sie Ihre Situation beurteilen sollten, anstatt zu versuchen, sie bedingungslos zu befolgen. Es gibt eine Grenze zwischen Purist sein und die Arbeit erledigen, und wenn Ersteres Letzteres verhindert, sind Sie auf der falschen Seite.
Wenn ich Ihr Design ein wenig kritisieren kann: Wenn Ihre
Config
Klasse als Schnittstelle zwischen einer auf der Festplatte gespeicherten Konfigurationsdatei und Ihrem Code konzipiert ist, möchten Sie als letztes den Speicherort im Midstream ändern. Wenn Sie das ändern, um denlocation
Zugriff auf eine andere Datei zu starten, sollten Sie das alte Objekt zerstören und ein neues erstellen. Sie haben nicht klargestellt, ob Sie den Inhalt der Datei im Objekt speichern möchten. Wenn Sie damit den Inhalt einer Konfigurationsdatei inhalieren und in eine andere schreiben möchten, sollten Sie eine Methode verwenden, mit der die Daten in ein neues Objekt geklont werden, das auf die neue Datei verweist.quelle
Es gibt zwei verschiedene Ebenen, auf denen Sie die SRP anwenden können.
Die erste Ebene ist die Ebene der einzelnen Funktionen / Methoden. Jeder sollte nur eine Aufgabe ausführen (und nach den Methodennamen zu urteilen, keine der Methoden,
Config
um die SRP zu brechen).Die zweite Ebene ist die Ebene einer Klasse. Hier wird das Konzept einer einzelnen Verantwortung etwas abstrakter, aber ein guter Indikator ist, wenn Sie die Verantwortlichkeiten einer Klasse in einem Satz ohne die (implizite) Verwendung des Wortes und angeben können . Wenn Sie dies mit der Anwesenheit der Getter und Setter tun können, bricht die Klasse die SRP nicht.
Im Allgemeinen Getter und, in geringerem Maße, Einrichter sind jedoch ein Hinweis darauf , dass die Einkapselung einer Klasse gebrochen. Im Fall der
Config
Klasse ist diesetFileLocation
Methode gut, da sieConfig
eine Möglichkeit benötigt, um herauszufinden, wo sich die Daten befinden. Die anderen scheinen jedoch verdächtig zu sein, da sie Informationen offenlegen, die BenutzerConfig
nicht benötigen sollten.quelle
Ihre Konfigurationsklasse hat die Verantwortung, die Konfiguration zu verfolgen, indem private Verweise auf bestimmte Daten gespeichert und über Mutator-Methoden Zugriff darauf gewährt werden. Dies bricht die SRP nicht, da die Klasse selbst immer noch eine einzige Verantwortung hat . Die Mutatoren helfen ihm lediglich dabei, diese Verantwortung zu erfüllen, indem sie den Zugriff auf die Daten abstrahieren. Die Mutatoren haben keine andere Verantwortung als die der Klasse. Sie sind Teil der größeren Verantwortung der Klasse.
quelle