2012-04-21 4 views
6

Ich würde gerne über die One Class, eine Verantwortung Prinzip lernen. Ich habe einige Artikel darüber gefunden, aber ohne Beispiele. Es würde mir helfen, wenn Sie mir ein Beispiel für eine Klasse geben könnten, die gegen das Prinzip verstößt.Was ist das Prinzip der One Class, One Responsibility?

Ich bin vertraut mit der Idee, dass eine Methode nur eine Sache tun sollte, zum Beispiel get und set-Methoden. Es muss nicht dasselbe sein wie Eine Klasse, eine Verantwortlichkeit, weil Set- und Get-Methoden beide in einer Klasse implementiert sind. Bedeutet das also, dass die Klasse die Regel verletzt, weil die Klasse Verantwortung hat, sowohl zu setzen als auch zu bekommen?

Was ist die Eine Klasse, eine Verantwortung Prinzip?

+2

Die einzige Möglichkeit, wirklich zu lernen, wäre, an einem realen Projekt zu arbeiten und Gegenbeispiele zu sehen, sogenannte God-Objects - Objekte, die Code haben, der sich mit zu vielen separaten Anliegen der Programmlogik befasst. Bei einem kleinen Projekt ist dieses Prinzip schwer zu visualisieren. –

+1

http://www.objectmentor.com/resources/articles/srp.pdf –

+1

[Satzzeichen] (http://en.wikipedia.org/wiki/Punctuation) ist dein Freund – keyser

Antwort

1

Ich bin kein 100% Experte in diesem Entwurfsmuster, aber hier ist, wie ich darüber denke - wenn ich ein Objekt erstellen, ist es verantwortlich für genau eine Sache. Wenn es etwas anderes tun muss, aber abhängig von der Situation mit einem anderen Objekt verbunden ist, würde ich Vererbung oder Schnittstellen verwenden.

Es ist ein Konzept, das ziemlich einfach scheint; Stellen Sie sicher, dass ein bestimmtes Objekt (oder eine Methode) einen Teil der Logik verarbeitet. Wenn es mehr behandelt, benötigen Sie ein anderes Objekt (oder Methode).

+0

Ich habe eine andere Frage, warum Singleton Methode Muster verletzt die One Class, One Verantwortung Prinzip ?? ist es, weil seine Aufgabe ist, ein Objekt zu erstellen und zu überprüfen, ob es ein Objekt erstellt hat, so dass nur ein Objekt erstellt wird? Wie kannst du das trennen? – user1348869

0

Das Prinzip ist genau das, was es sagt, nicht viel mehr. Eine Klasse sollte nur eine Verantwortung haben. Es kann jedoch schwierig sein, Verantwortlichkeiten zu definieren. Ein Beispiel könnte eine "DatabaseHandler" -Klasse sein, die alle Datenbankanforderungen in einer Anwendung behandelt.

Weiterführende Literatur: cohesion.

0

Auf dem Prinzip des Aspekts nicht Mischen von Verantwortlichkeiten.

Wenn Sie eine InvoiceProcessor-Klasse haben, die eine Rechnung verarbeitet, Berechnungen nach Geschäftsregeln durchführt, eine PDF-Datei mit der Rechnung erstellt und die Datenbank mit der Registrierung zusätzlicher Bonuspunkte für den Verkäufer verarbeitet, dann müssen Sie eindeutig trennen Bedenken. In diesem Fall ist eine klare Trennung oder gar Delegation an andere Klassen fällig.

Aber eine Klasse - eine Verantwortung ist noch subtiler und abscheulich. Wenn Sie eine Lösung für die Rechnungsverarbeitung bereitstellen müssen und mehrere Ziele erfüllen müssen, wie diese Bonuspunkte, können Sie eine verletzende Funktion haben, die mehrere Ziele erfüllt: Bonuspunkte für Verkäufer und Rabatt des Kunden berechnen. Wenn Sie eine Klasse mit ihren Datenstrukturen haben, wie eine Prioritätswarteschlange oder was auch immer, und mischen Sie sie gleichzeitig mit Datenstrukturen, um ein Teil zwischenzuspeichern, indem Sie z. B. eine Liste und eine Map verwenden, dann An einigen Stellen manipulieren Sie Daten für verschiedene Zwecke, vielleicht sogar innerhalb der Cache-Liste, so dass die Datenstrukturen ineinandergreifen. Wenn Sie dann eine Funktion haben, die die Priorität ändert und den Caching-Zustand ändert, wird es schwierig werden, die Prozesse in einer Zukunft zu verstehen.

Ich stoße oft auf Verstöße, bei denen verschiedene Aspekte implementiert werden müssen, und sie werden in einer Klasse erledigt. Die API hat dann Aufrufe mit verschiedenen Abstraktionsebenen oder einer schwierigen Semantik.

0

Nehmen wir an, Sie schreiben Ihr eigenes Logger-Dienstprogramm, und weil es einfach beginnt (ein Singleton mit Methoden, die auf stdout schreiben), entscheiden Sie sich, all seine Funktionalität in eine Klasse einzuordnen.Wie Sie das Sie denken mehr Funktionen verwenden, um es hinzuzufügen:

  • Sie, um verschiedene Dinge protokollieren können, wollen (auf stderr in eine Datei, in eine Warteschlange, was auch immer)

  • Sie wollen in der Lage sein, die Formatierung für Nachrichten zu ändern

  • Sie wollen getrennte Logger für verschiedene Kategorien

  • Sie Nachrichten zu filtern, für eine Kategorie von Protokollebene in der Lage sein

  • Sie wollen in der Lage Protokolliergrade on the fly

  • fügen Sie neue Protokollebenen (ERROR, WARN, INFO, DEBUG, usw.)

usw. zu ändern, und Sie hinzufügen die Implementierung für jede Funktion derselben Klasse, mit der Sie begonnen haben. Jede Änderung, die Sie vornehmen, bedeutet, in die gleiche Klasse zurückzukehren, sie zu sortieren, um zu sehen, was relevant ist, und dann Ihre Änderungen vorzunehmen. Da der gesamte Code in einer Klasse zusammengepackt ist und Methoden Code enthalten, der verschiedene Funktionen implementiert, kann es schwierig sein, alle relevanten Teile für Ihre Änderung aufzuspüren, und es besteht immer die Möglichkeit, dass sich eine Änderung unbeabsichtigt auf eine andere Funktion auswirkt dass einige bereits vorhandene Features unter bestimmten Umständen nicht mehr funktionieren. Sie müssen also alle Features in der Klasse und noch schlimmer alle Kombinationen aller Features testen, um diese Fehler zu erkennen. Das bedeutet, dass der Test unvollständig ist und sich Fehler einschleichen können.

Schauen Sie sich jetzt an, wie ein echtes Projekt wie log4j mit diesem Zeug umgeht. Es gibt eine Trennung von Belangen, bei der verschiedene Klassen die Formatierung handhaben, die Ausgabe der Ausgabe übergeben, einen Logger für eine Kategorie bereitstellen und die Interaktion zwischen all diesen Teilen klar definiert ist, mit dem Ergebnis, dass wenn man an einem Teil bastelt oder ersetzt betrifft nicht die anderen Stücke. Benutzer können ihre eigenen Klassen erstellen, die Funktionen hinzufügen, die sie benötigen (wo sie nicht alles über das Logframework wissen müssen, sie müssen nur den Vertrag für die bestimmte Art von Stück kennen, die sie hinzufügen wollen) und sie einstecken und Benutzer können verschiedene Plugins mischen und anpassen. Wenn ein Plugin kaputt ist, erstreckt sich dieser Bruch nicht über dieses Plugin hinaus und Änderungen an einzelnen Teilen gefährden nicht die Integrität des gesamten Projekts. In dem Maße, in dem Verträge die Interaktion der Teile regeln, müssen Sie nicht alle verschiedenen Kombinationen bestimmter Merkmale testen.

Mit dem Single-Class-Ansatz könnten Sie das nie tun, jedes bisschen neue Funktionalität, die jemand hinzugefügt hat, wäre eine Abzweigung des Projekts. Der Grundsatz des Single-Responsibility-Prinzips und der anderen SOLID-Regeln besteht darin, eine Gesamtstrategie zu bieten, die es ermöglicht, Software auf kontrollierte Weise zu ändern, ohne die Dinge zu stören.

0

Jedes Ding in einer Klasse sollte sich darauf beziehen, wofür die Klasse verantwortlich sein sollte.

Wenn es eine Klasse namens MailSender ist, sollte es nur wissen, wie die Mail zu senden ist. Code, der den Mail-Inhalt erstellt, sollte nicht darin enthalten sein.