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 CardKlasse die Sichtbarkeit für die Spieler bestimmen.
Eine Möglichkeit ist, boolean isVisible(Player p)am CardUnterricht teilzunehmen.
Ein weiterer Grund ist zu haben , boolean isVisible(Card c)auf PlayerKlasse.
Ich mag den ersten Ansatz nicht besonders, da er Wissen über eine höhere PlayerKlasse einer niedrigeren CardKlasse verleiht .
Stattdessen habe ich mich für die dritte Option entschieden, bei der wir eine ViewportKlasse haben, die Playeranhand von a und einer Liste von Karten bestimmt, welche Karten sichtbar sind.
Allerdings raubt dieser Ansatz sowohl Cardund PlayerKlassen einer möglichen Memberfunktion. Sobald Sie dies für andere Sachen als die Sichtbarkeit von Karten zu tun, werden Sie mit links Cardund PlayerKlassen , die rein Daten enthalten , wie alle Funktionen in anderen Klassen implementiert, die ohne Daten meist Klassen sind nur Methoden, wie die Viewportoben.
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 DocumentIdeine unveränderliche Klasse, die nur ein einziges BigDecimal idMitglied und einen Getter für dieses Mitglied hat. Jetzt müssen Sie irgendwo eine Methode haben, die eine DocumentIdRückgabe Documentfür diese ID aus einer Datenbank liefert .
Machst du:
- Fügen Sie
Document getDocument(SqlSession)derDocumentIdKlasse 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 dieDocumentIdKlasse als tot, ohne Verhalten, strukturähnliche Klasse.