2009-05-22 2 views
3

Etwas bleibt in meiner Programmierung angezeigt, und es ist, dass zwei Dinge aus einem bestimmten Blickwinkel gleich sind, aber unterschiedlich von anderen. Stellen Sie sich vor, Sie erstellen eine Grafik von Bahnhöfen, die mit Zügen verbunden sind, dann sind die Klassen Vertex und RailStation manchmal gleich, andere nicht.Korrekte OO-Modellierung von Korrespondenzen

Also, stellen Sie sich vor, ich habe eine Grafik, die sehr stark Bahnhöfe und Züge darstellt. Dann übergebe ich dieses Diagramm an ein anderes Objekt, das einige Scheitelpunkte löscht, und dann möchte ich, dass die entsprechenden Bahnhöfe weg sind.

Ich möchte nicht Bahnhöfe "Eigenschaften" von Vertices machen, sie sind nicht. Außerdem ist das Problem symmetrisch: Wenn ich eine Bahnstation lösche, möchte ich, dass die entsprechende Ecke weg ist. Was ist die richtige OO-Art zu modellieren oder Korrespondenzen. Ich bin bereit, einige zusätzliche Meilen zu gehen, indem ich einige Support-Methoden oder Klassen schreibe, wenn am Ende die Gesamtnutzung einfach und leicht ist.

Ich verwende derzeit die Smalltalk-Programmiersprache, aber die Frage ist nicht wirklich Smalltalk-spezifisch, denke ich. Ich erwähne es nur, weil Sie in Smalltalk coole Tricks wie das Untersuchen des Call-Stacks durchführen können, was in diesem Zusammenhang hilfreich sein kann.

Aktualisieren: Nun, RailStations sind keine Vertices! Sind sie?

Ok, lassen Sie uns echten Code betrachten, wie in den Antworten gefordert. Lassen Sie mich eine Person mit Kindern modellieren. Das ist die einfachste Sache, oder? Kinder sollten auch ihre Eltern kennen, also haben wir einen doppelt verbundenen Baum. Um das Auflösen von Eltern von Kindern zu erleichtern, modelliere ich die Beziehung zwischen Eltern und Kind als eine Beziehung mit den Eigenschaften Eltern und Kind.

So konnte ich Eltern >> removeChild implementieren: vielleicht wie diese

removeChild: aChild 
    (parent relationshipWith: aChild) disband. 

So ein Elternteil eine Sammlung von Beziehungen hat, nicht von Kindern. Aber jede Beziehung entspricht einem Kind. Jetzt möchte ich solche Dinge tun:

parent children removeAllSuchThat: [:e | e age < 12] 

, die die Beziehung und das Kind entfernen sollte.

Hier entsprechen Beziehungen und Kinder in gewissem Sinne. Also, was mache ich jetzt? Versteh mich nicht falsch, ich bin mir vollkommen bewusst, dass ich das Problem lösen könnte, ohne Beziehungsklassen einzuführen. Aber tatsächlich teilen Eltern und Kinder tatsächlich eine Beziehung, also warum nicht das modellieren und sie benutzen, um zu helfen, doppelte Verbindungen weniger zwingend zu lösen?

+0

Ich muss Ihre Frage kommentieren: RailStations sind keine Vertices? In Ihrer Frage gibt es nichts, was impliziert, dass Vertices und RailStations unterschiedliche Entitäten auf OO-Art sind. Der einzige Unterschied ist, dass Vertices nur eine visuelle Darstellung von RailStations darstellen. Ist das richtig? – zidane

Antwort

3

In Ihrer Problemdomäne sind Stationen nicht eine Art Vertex? In diesem Fall, warum nicht Station von Vertex ableiten?

Beachten Sie die Verwendung der Phrase "in Ihrer Problemdomäne". Ihr Problem scheint die Verwendung als Bahnhöfe in einer Grafik zu sein. Also ja, in dieser Domäne sind Stationen Eckpunkte. Wenn es eine andere Problemdomäne wäre, sagen wir eine Datenbank über die Bahnhofsarchitektur, könnten sie es nicht sein. Die meisten modernen Sprachen unterstützen eine Idee von Namespaces, damit Sie verschiedene Arten von Entitäten mit denselben Namen in verschiedenen Domänen haben können.

In Bezug auf Ihr Eltern/Kind-Problem sind Sie wieder zu allgemein. Wenn ich mathematische Ausdrücke und Unterausdrücke modelliere, würde ich alle Unterausdrücke löschen und löschen wollen, wenn ich einen Elternteil entferne.OTOH, ff Ich habe rechtliche Verantwortungsbeziehungen in der britischen Bevölkerung modelliert, dann, wenn eine Verantwortung aufgelöst wird (sagen wir wegen einer Scheidung), möchte ich nur die Beziehung entfernen und NICHT das Kind löschen/befreien, das seine eigene unabhängige Existenz hat .

+0

Nun, wie für die Kinder, in einigen Kontexten entsprechen sie, in anderen nicht. Das ist mein ganzer Punkt, weshalb ich es einfach unterlassen würde, die Erbschaft zu benutzen. Es hängt vom Kontext ab, ob es identifiziert werden soll oder nicht. Gibt es keine Modellierung, die Kontexten dient? Wenn ich in einem Kontext der Korrespondenz bin, wie modelliere ich diese Korrespondenz? Eine Idee, die ich hatte, war, eine besondere Art von Identifikationssammlung zu machen, die Paare von Railstations und Vertices enthält und auf Railstationen oder Vertices umgestellt werden kann. Das Löschen einer RailStation würde somit auch den Vertex löschen. – nes1983

+0

Und natürlich, indem ich ein Kind entferne, meine ich: es von seinem Elternteil entfernen. Nicht aus dem System. – nes1983

+0

Wie ich in meiner Antwort gesagt habe, versuchen Sie eine Lösung für zwei verschiedene Problembereiche zu erstellen. Außer für sehr einfache Typen wie Ganzzahlen, Strings, Listen usw. ist dies selten eine gute Idee. –

2

Es scheint, als ob Sie wollen, dass RailStation nur von Vertex erbt (is-a-Beziehung). Siehe smalltalk tutorial bei Vererbung. Wenn Sie also ein Diagramm von RailStations haben, würde ein Objekt, das (generisch) mit Graphen von Vertexes zu tun hat, die Dinge auf natürliche Weise behandeln.

Wenn dieser Ansatz nicht funktioniert, seien Sie spezifischer (vorzugsweise mit echtem Code).

2

Von Ihrer Beschreibung des Problems haben Sie eine Eins-zu-Eins-Korrespondenz von Stationen zu Vertices und das Löschen einer Station sollte den entsprechenden Vertex automatisch löschen (und umgekehrt). Sie haben auch erwähnt, dass Sie "eine Graphik von Bahnhöfen bauen, die durch Züge verbunden sind", womit Sie offenbar eine Kurve meinen, in der Stationen Knoten und Züge Kanten sind.

Also, in welcher Weise ist eine Station nicht ein Scheitelpunkt? Wenn die Station nur als Knoten existiert und wenn ein Eckpunkt außer als Station nicht existiert, welchen Nutzen sehen Sie dann darin, sie als zwei getrennte, aber verbundene Einheiten zu erhalten?

Wie ich Ihre Situation verstehe, ist Station-isa-Vertex und Vererbung die Art, das zu modellieren.

+0

Nun, die Sache mit der Bahn ist nur ein Beispiel. Es passiert mir immer wieder, dass ich auf Entsprechungen stoße und nicht ganz weiß, wie ich damit umgehen soll, und während bei den Bahnhöfen die Erbschaft einen billigen Ausweg bietet, fühlt sie sich immer billig und betrügerisch an. Wenn ich eine Grafik von Seaside-Komponenten erstelle, bin ich nicht sicher, ob ich die komplette Seaside-Hierarchie ändern möchte. Was ich wirklich will, ist, Dinge in einem bestimmten Kontext zusammenzufügen und sie in anderen Kontexten getrennt zu lassen. – nes1983

+0

In diesem Fall klingt es wie ein Job für Aggregation/Delegierung - Railstation/Seaside hat einen Vertex, der im Konstruktor rs/ss erstellt und von seinem Destruktor zerstört wird. Sie müssen nur daran denken, den Scheitelpunkt in diesem Szenario nicht manuell zu zerstören, es sei denn, Sie erstellen eine OwnedVertex-Unterklasse, die ihren Besitzer vor dem Sterben benachrichtigt, so dass sich die rs/ss zusammen mit ihm selbst zerstören können. –

1

Ein Beziehungsobjekt ist eine gute Idee.

Ich denke, die geeignete Frage hier ist "welcher Gebrauch sollte davon gemacht werden?".

Wahrscheinlich Eltern und Kind Klassen erweitern die gleiche Person Superklasse, so dass sie einige Attribute gemeinsam haben, Alter zum Beispiel.

In meiner Idee kann ich Folgendes sehen: Eltern und Kind Objekte müssen einander kennen, also müssen beide Klassen eine Verbindung zu der gleichen Beziehung halten. Das Relationship-Objekt behält eine Eins-zu-viele-Beziehung zwischen einem einzelnen übergeordneten Element und einer bestimmten Anzahl von untergeordneten Elementen bei. Es behält einen Verweis auf jedes Person-Objekt.

Auf diese Weise können Sie die gesamte auflösende Logik innerhalb des Relationship-Objekts implementieren, mehr oder weniger anspruchsvoll, wie Sie es wünschen. Sie können das Beziehungsobjekt abfragen, um zu erfahren, welche Mitglieder der Familie Ihren Anforderungen entsprechen, um etwas zu tun. Sie können die Beziehung sicher auflösen (und zerstören), da sie alle Mitglieder kennt und sie bitten würde, die Referenz zu brechen. Dann wäre sie bereit zu zerstören oder bittet ein Mitglied, die Familie zu verlassen und das Beziehungsobjekt beizubehalten am Leben.

Aber das ist nicht alles. Beziehung sollte wirklich eine Oberklasse sein, erweitert um HierarchicalRelationship und PeerRelationship (oder FriendRelationship).

Mit dieser Spezialisierung können Sie Parent (s) und Child (ren) verwenden, um vollständig traversal zwischen anderen Hierarchien zu verknüpfen. Das wahre Konzept dahinter ist, dass Ihre Relationship-Objekte der Schlüssel sind, um die gesamte Gruppe von Person-Objekten (oder Vertex-Objekten) in einer skalierbaren und strukturierten Weise abzufragen und zu organisieren, sodass die gesamte Datendomäne verwendbar ist in jedem Sinne magst du, ob du Gruppen auflösen oder einen bestimmten Weg (oder eine Eisenbahn) zwischen ihnen gehen willst.

Sorry für die große Menge von Metaphoren.

+0

Eigentlich stimme ich sehr Ihrer Art zu denken zu, es räumt viel auf, was ich in meinem Kopf hatte. Ich weiß immer noch nicht genau, wie ich das machen soll, aber ja, ich sehe die Implikationen für Fragen (in der Tat bin ich so zu der Frage gekommen). – nes1983

+0

Ok Niko, lass es mich wissen, wenn du mehr Hilfe brauchst. Ich kenne Smalltalk nicht, sondern Objective-C und C++. Vielleicht können wir auch OO-Konzepte ohne direkte sprachliche Implikationen ausdrücken. –

1

einen Blick auf Ruhm Nehmen http://www.squeaksource.com/Fame.html

Wir verwenden eine spezielle Unterklasse von Collection, die das entgegengesetzte Ende aktualisiert sehen, wenn Sie Elemente hinzufügen oder entfernen. Sie können Ihre Klassen auch mit Pragmas annotieren, um Beziehungen zu kommentieren. Diese Pragmas werden vom Fame-Framework verwendet, um alle möglichen netten Dinge zu erledigen.