Die Grundidee hinter OOP ist, dass Daten und Verhalten (auf diesen Daten) untrennbar sind und sie durch die Idee eines Objekts einer Klasse gekoppelt sind. Objekte haben Daten und Methoden, die damit arbeiten (und andere Daten). Offensichtlich werden nach den Prinzipien von OOP Objekte, die nur Daten sind (wie C-Strukturen), als Anti-Muster betrachtet.
So weit, ist es gut.
Das Problem ist, dass ich bemerkt habe, dass mein Code in letzter Zeit immer mehr in Richtung dieses Anti-Patterns zu gehen scheint. Mir scheint, je mehr ich versuche, Informationen zwischen Klassen und lose gekoppelten Entwürfen zu verbergen, desto mehr werden meine Klassen eine Mischung aus reinen Datenklassen ohne Verhalten und allen Verhaltensklassen ohne Daten.
Im Allgemeinen gestalte ich Klassen so, dass sie sich der Existenz anderer Klassen möglichst wenig bewusst werden und die Schnittstellen anderer Klassen möglichst wenig kennen. Ich setze dies besonders von oben nach unten durch, Klassen mit niedrigerem Level wissen nichts über Klassen mit höherem Level. Z.B:
Angenommen, Sie haben eine allgemeine Kartenspiel-API. Du hast eine Klasse Card
. Jetzt muss diese Card
Klasse die Sichtbarkeit für die Spieler bestimmen.
Eine Möglichkeit ist, boolean isVisible(Player p)
am Card
Unterricht teilzunehmen.
Ein weiterer Grund ist zu haben , boolean isVisible(Card c)
auf Player
Klasse.
Ich mag den ersten Ansatz nicht besonders, da er Wissen über eine höhere Player
Klasse einer niedrigeren Card
Klasse verleiht .
Stattdessen habe ich mich für die dritte Option entschieden, bei der wir eine Viewport
Klasse haben, die Player
anhand von a und einer Liste von Karten bestimmt, welche Karten sichtbar sind.
Allerdings raubt dieser Ansatz sowohl Card
und Player
Klassen einer möglichen Memberfunktion. Sobald Sie dies für andere Sachen als die Sichtbarkeit von Karten zu tun, werden Sie mit links Card
und Player
Klassen , die rein Daten enthalten , wie alle Funktionen in anderen Klassen implementiert, die ohne Daten meist Klassen sind nur Methoden, wie die Viewport
oben.
Dies ist eindeutig gegen die Grundidee von OOP.
Welches ist der richtige Weg? Wie soll ich vorgehen, um die Klassenabhängigkeiten zu minimieren und das angenommene Wissen und die Kopplung zu minimieren, ohne jedoch mit dem seltsamen Design aufzuhören, bei dem alle Klassen auf niedriger Ebene nur Daten enthalten und Klassen auf hoher Ebene alle Methoden enthalten? Hat jemand eine dritte Lösung oder Perspektive für das Klassendesign, die das ganze Problem vermeidet?
PS Hier ist ein weiteres Beispiel:
Angenommen, Sie haben DocumentId
eine unveränderliche Klasse, die nur ein einziges BigDecimal id
Mitglied und einen Getter für dieses Mitglied hat. Jetzt müssen Sie irgendwo eine Methode haben, die eine DocumentId
Rückgabe Document
für diese ID aus einer Datenbank liefert .
Machst du:
- Fügen Sie
Document getDocument(SqlSession)
derDocumentId
Klasse eine Methode hinzu , die plötzlich Kenntnisse über Ihre Persistenz ("we're using a database and this query is used to retrieve document by id"
), die API für den Zugriff auf die Datenbank und dergleichen vermittelt. Auch diese Klasse benötigt nun eine Persistenz-JAR-Datei, um kompiliert zu werden. - Fügen Sie eine andere Klasse mit der Methode hinzu
Document getDocument(DocumentId id)
und lassen Sie dieDocumentId
Klasse als tot, ohne Verhalten, strukturähnliche Klasse.