Wie kann man eine einzelne Verantwortung verwalten, wenn die Verantwortung geteilt wird?


10

Ich habe Basis zwei Klassen, Operationund Trigger. Jede hat eine Reihe von Unterklassen, die sich auf bestimmte Arten von Operationen oder Triggern spezialisiert haben. A Triggerkann eine bestimmte auslösen Operation. Während ein Operationvon einem bestimmten ausgelöst werden kann Trigger.

Ich muss den Code schreiben, der eine Vorgabe Operationeiner Vorgabe zuordnet Trigger(oder umgekehrt), bin mir aber nicht sicher, wo ich sie ablegen soll.

In diesem Fall gehört der Code nicht eindeutig zu der einen oder anderen Klasse. In Bezug auf ein Prinzip der Einzelverantwortung bin ich mir nicht sicher, wo der Code hingehören soll.

Ich kann drei Optionen sehen, die alle funktionieren würden. Während 1 & 2 nur eine Wahl der Semantik zu sein scheinen, repräsentiert 3 einen völlig anderen Ansatz.

  1. Am Abzug z bool Triggers(Operation o).
  2. Auf die Operation, z bool TriggeredBy(Trigger t).
  3. In einer völlig neuen Klasse, die das Mapping verwaltet, z bool MappingExists(Trigger t, Operation o).

Wie soll ich entscheiden, wo der Code für die gemeinsame Zuordnung in Bezug auf ein Prinzip der Einzelverantwortung platziert werden soll?

Wie kann man eine einzelne Verantwortung verwalten, wenn die Verantwortung geteilt wird?


Bearbeiten 1.

Der eigentliche Code sieht also so aus. Alle Eigenschaften, sind entweder ein string, Guid, collection<string>, oder enum. Sie stellen im Grunde nur kleine Daten dar.

Geben Sie hier die Bildbeschreibung ein

Bearbeiten 2.

Der Grund für den Rückgabetyp von bool. Eine andere Klasse wird eine Sammlung von Triggerund eine Sammlung von konsumieren Operation. Es muss wissen, wo eine Zuordnung zwischen a Triggerund a besteht Operation. Diese Informationen werden zum Erstellen eines Berichts verwendet.


Warum der Bool-Typ?
Tulains Córdova

@ user61852, um ein Ergebnis an den aufrufenden Code zurückzugeben
James Wood

1
Was macht der aufrufende Code mit dem Booleschen Wert? Je nachdem, was Sie auf diese Frage beantworten, habe ich möglicherweise die Lösung.
Tulains Córdova

@ user61852, siehe meine Änderungen.
James Wood

1
Es hat also nichts damit zu tun, den Trigger der Operation tatsächlich auszuführen?
Tulains Córdova

Antworten:


4

Ich würde es so sehen: Wie wird bestimmt, welche Operation bewirkt, dass welcher Trigger ausgelöst wird? Es muss ein Algorithmus sein, der sich im Laufe der Zeit ändern oder sich zu mehreren Algorithmen entwickeln kann. Wenn Sie es entweder in Trigger- oder Operation-Klassen einfügen, bedeutet dies, dass diese Klassen in Zukunft solche Szenarien verarbeiten können. Beachten Sie, dass ich es nicht so einfach wie eine Zuordnung sehe, da möglicherweise mehr dahinter steckt.

Meine Wahl wäre, eine Klasse mit geeigneten Methoden wie GetOperationForTrigger (Trigger t) zu erstellen. Dies ermöglicht es dem Code, sich zu einer Reihe solcher Klassen zu entwickeln, deren Auswahl zur Laufzeit oder von anderen Variablen (z. B. Strategiemuster) abhängen kann.

Beachten Sie, dass die Hauptannahme in dieser Denkrichtung darin besteht, minimalen Code zu schreiben (dh heute drei Klassen), aber größere Umgestaltungen zu vermeiden, wenn die Funktionalität in Zukunft erweitert werden muss, indem nicht davon ausgegangen wird, dass es immer genau einen Weg gibt Bestimmen Sie, welcher Trigger welche Operation verursacht.

Hoffe das hilft. Obwohl die Antwort der von user61852 ähnlich ist, ist die Argumentation anders. Infolgedessen unterscheidet sich die Implementierung (dh es werden explizite Methoden verwendet, anstatt Gleiche zu überschreiben, sodass sich die Anzahl der Methoden im Laufe der Zeit je nach Bedarf ändern kann).


5

Kenne ich schon.

Option 3.

Ich weiß nicht, welche Sprache Sie verwenden werden, aber ich werde einen Pseudocode verwenden, der Java sehr ähnlich ist. Wenn Ihre Sprache C # ist, haben Sie wahrscheinlich ähnliche Schnittstellen und Strukturen.

Haben Sie eine Mapping-Klasse oder Schnittstelle:

public interface Mapping {
    public void setObject1(Object o);
    public void setObject2(Object o);
    public Object getObjecto1();
    public Object getObjecto2();
}
  • Überschreiben Sie die equals()Methode, Mappingdamit Sammlungen von Mappingabgefragt werden können, ob sie eine bestimmte Zuordnung enthalten.
  • Die spezialisierten Objekte sollten ebenfalls über geeignete equals()Methoden verfügen .
  • Implementieren Sie auch die Schnittstelle Comparable, damit Sie Berichte sortieren können.

Sie können einfach eine Zuordnung in eine Sammlung einfügen

List<Mapping> list = new ArrayList<Mapping>();
Hat hat = new Hat();
Bag bag = new Bag();
list.add(new Mapping(hat,bag));

Später können Sie fragen:

// let's say you have a variable named x which is of type Mapping

if ( list.contains(x) ){
    // do some thing
}

0
  1. Teilen Sie Ihren Code in kleinere Teile auf.

Derzeit haben Sie Klasse A, die über Klasse B Bescheid weiß, und Klasse B, die über Klasse A Bescheid weiß. Das ist eine Menge Kopplung.

Per Definition führt A mindestens seine eigene Operation durch UND prüft, ob B ausgeführt werden soll. Das Gegenteil ist bei B der Fall. Unabhängig davon, welche Klasse zuerst aufgerufen wurde, sollte es möglich sein, das Ergebnis zu überprüfen und festzustellen, ob weitere Dinge ausgeführt werden müssen.

Versuchen Sie, diese Kopplung zu lösen, indem Sie Ihre Klassen in kleinere Komponenten aufteilen. Ich möchte oben in jeder Klasse einen Kommentar einfügen, der im Klartext erklärt, was er tut. Wenn Sie Wörter wie AND verwenden müssen oder ein oder zwei Sätze überschreiten, müssen Sie in Betracht ziehen, sie aufzuschlüsseln. In der Regel sollte alles nach einem "und" in einer eigenen Klasse sein

Überprüfen Sie auch, ob Sie eine Schnittstelle definieren können, die die Funktionen von Trigger und Operation abdeckt. Wenn Sie das nicht können, ist das ein weiterer Hinweis darauf, dass Ihre Klasse zu groß wird. Dadurch wird auch die Kopplung zwischen Ihren Klassen unterbrochen.


1
Ehrlich gesagt bin ich mir nicht sicher, ob ich meinen Code weiter aufschlüsseln kann. Ich habe meine Frage mit den Klassensignaturen aktualisiert, damit Sie sehen können, aber im Grunde handelt es sich um ziemlich leichte Datenobjekte, in denen jeweils einige Eigenschaften gespeichert sind. In Bezug auf die Kopplung ist das ja etwas problematisch, da effektiv a Triggeran a gekoppelt wäre Operation. Aber so sehen die Daten der realen Welt aus. Sie sind gekoppelt, weil es eine Zuordnung gibt, z. B. müssen sie voneinander wissen, um eine Bedeutung zu haben.
James Wood
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.