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.
quelle
Antworten:
Was Sie beschreiben, wird als anämisches Domänenmodell bezeichnet . Wie bei vielen OOP-Konstruktionsprinzipien (wie Law of Demeter usw.) lohnt es sich nicht, sich nach hinten zu bücken, nur um eine Regel zu erfüllen.
Es ist nichts Falsches daran, Tüten voller Werte zu haben, solange sie nicht die gesamte Landschaft durcheinander bringen und sich nicht auf andere Objekte verlassen, um die Hausarbeit zu erledigen, die sie für sich selbst erledigen könnten .
Es wäre sicherlich ein Codegeruch, wenn Sie eine separate Klasse nur zum Ändern der Eigenschaften von
Card
- hätten, wenn vernünftigerweise zu erwarten wäre, dass sie sich von selbst darum kümmert.Aber ist es wirklich eine Aufgabe
Card
zu wissen, für wenPlayer
es sichtbar ist?Und warum implementieren
Card.isVisibleTo(Player p)
, aber nichtPlayer.isVisibleTo(Card c)
? Oder umgekehrt?Ja, Sie können versuchen, eine Art Regel dafür zu finden, wie Sie es getan haben -
Player
als höheres Niveau als einCard
(?) -, aber es ist nicht so einfach zu erraten, und ich muss an mehr als einer Stelle nachsehen um die Methode zu finden.Im Laufe der Zeit kann es zu einem schlechten Designkompromiss bei der Implementierung
isVisibleTo
auf beidenCard
und auf derPlayer
Klasse kommen, was meiner Meinung nach ein Nein-Nein ist. Warum so? Denn ich stelle mir schon den beschämenden Tag vor, an demplayer1.isVisibleTo(card1)
ein anderer Wert zurückkommt alscard1.isVisibleTo(player1).
ich denke - es ist subjektiv - dies sollte durch das Design unmöglich gemacht werden .Gegenseitige Sichtbarkeit von Karten und Spieler sollten besser durch eine Art von einem Kontextobjekt geregelt werden - sei es
Viewport
,Deal
oderGame
.Es ist nicht gleichbedeutend mit globalen Funktionen. Schließlich kann es viele gleichzeitige Spiele geben. Beachten Sie, dass dieselbe Karte für viele Tabellen gleichzeitig verwendet werden kann. Sollen wir
Card
für jedes Pik-As viele Instanzen erstellen ?Ich könnte implementieren immer noch
isVisibleTo
aufCard
, aber ein Kontextobjekt , um es passieren und machenCard
delegieren die Abfrage. Programm zur Schnittstelle, um eine hohe Kopplung zu vermeiden.Wie für Ihr zweites Beispiel - wenn die Dokument-ID nur aus a besteht
BigDecimal
, warum überhaupt eine Wrapper-Klasse dafür erstellen?Ich würde sagen, Sie brauchen nur eine
DocumentRepository.getDocument(BigDecimal documentID);
Übrigens gibt es
struct
in C # zwar kein Java, aber s.Sehen
http://msdn.microsoft.com/en-us/library/ah19swz4.aspx
http://msdn.microsoft.com/en-us/library/0taef578.aspx
als Referenz. Es ist eine sehr objektorientierte Sprache, aber niemand macht eine große Sache daraus.
quelle
Interface iObj = (Interface)obj;
, der das VerhalteniObj
der nicht betroffen iststruct
oderclass
Statusobj
(außer dass es eine Box sein Exemplar bei dieser Zuordnung , wenn es sich um einstruct
).Sie machen den allgemeinen Fehler anzunehmen, dass Klassen ein grundlegendes Konzept in OOP sind. Klassen sind nur ein besonders beliebter Weg, um eine Kapselung zu erreichen. Aber wir können zulassen, dass das abrutscht.
GUTE HIMMEL NR. Wenn du Bridge spielst, fragst du die Sieben der Herzen, wann es Zeit ist, die Hand des Dummys von einem Geheimnis, das nur dem Dummy bekannt ist, zu einem Geheimnis, das allen bekannt ist, zu ändern? Natürlich nicht. Das ist überhaupt kein Problem der Karte.
Beide sind schrecklich; Tu beides nicht. Weder der Spieler noch die Karte sind für die Umsetzung der Bridge-Regeln verantwortlich!
Ich habe noch nie Karten mit einem "Ansichtsfenster" gespielt, daher habe ich keine Ahnung, was diese Klasse verkapseln soll. Ich habe Karten mit ein paar Kartenspielen, einigen Spielern, einem Tisch und einer Kopie von Hoyle gespielt. Welches dieser Dinge repräsentiert Viewport?
Gut!
Nein; Die Grundidee von OOP ist, dass Objekte ihre Anliegen zusammenfassen . In Ihrem System kümmert sich eine Karte nicht viel. Weder ist ein Spieler. Dies liegt daran, dass Sie die Welt genau modellieren . In der realen Welt sind die Eigenschaften von Karten, die für ein Spiel relevant sind, außerordentlich einfach. Wir könnten die Bilder auf den Karten durch die Zahlen von 1 bis 52 ersetzen, ohne das Spiel zu verändern. Wir könnten die vier Leute durch Schaufensterpuppen mit den Bezeichnungen Nord, Süd, Ost und West ersetzen, ohne das Spiel zu verändern. Spieler und Karten sind die einfachsten Dinge in der Welt der Kartenspiele. Die Regeln sind kompliziert, und in der Klasse, die die Regeln darstellt, sollte die Komplikation liegen.
Wenn einer Ihrer Spieler eine KI ist, kann sein interner Zustand extrem kompliziert sein. Aber diese KI bestimmt nicht, ob sie eine Karte sehen kann. Die Regeln bestimmen das .
So würde ich Ihr System entwerfen.
Erstens sind Karten überraschend kompliziert, wenn es Spiele mit mehr als einem Deck gibt. Sie müssen sich die Frage stellen: Können die Spieler zwei Karten mit demselben Rang unterscheiden? Wenn Spieler 1 eines der sieben Herzen spielt und dann etwas passiert und Spieler 2 eines der sieben Herzen spielt, kann Spieler 3 dann feststellen, dass es die gleichen sieben Herzen waren? Betrachten Sie dies sorgfältig. Abgesehen von dieser Sorge sollten die Karten sehr einfach sein. Sie sind nur Daten.
Was ist nun die Natur eines Spielers? Ein Spieler verbraucht eine Folge sichtbarer Aktionen und führt eine Aktion aus .
Das Objekt rules ist das, was all dies koordiniert. Die Regeln erzeugen eine Abfolge von sichtbaren Aktionen und informieren die Spieler:
Und bittet dann den Spieler um eine Aktion.
Und so weiter.
Trennen Sie Ihre Mechanismen von Ihren Richtlinien . Die Richtlinien des Spiels sollten in einem Richtlinienobjekt und nicht in den Karten enthalten sein . Die Karten sind nur ein Mechanismus.
quelle
Sie haben Recht, dass die Kopplung von Daten und Verhalten die zentrale Idee von OOP ist, aber es steckt noch mehr dahinter. Beispiel: Kapselung : OOP / modulare Programmierung ermöglicht es uns, eine öffentliche Schnittstelle von Implementierungsdetails zu trennen. In OOP bedeutet dies, dass die Daten niemals öffentlich zugänglich sein sollten und nur über Accessoren verwendet werden sollten. Nach dieser Definition ist ein Objekt ohne Methoden in der Tat unbrauchbar.
Eine Klasse, die keine anderen Methoden als Accessoren bietet, ist im Wesentlichen eine überkomplizierte Struktur. Dies ist jedoch nicht schlecht, da OOP Ihnen die Flexibilität gibt, interne Details zu ändern, was eine Struktur nicht tut. Anstatt beispielsweise einen Wert in einem Mitgliedsfeld zu speichern, könnte er jedes Mal neu berechnet werden. Oder ein Backing-Algorithmus wird geändert und damit der Zustand, der verfolgt werden muss.
Während OOP einige klare Vorteile hat (insbesondere gegenüber der einfachen prozeduralen Programmierung), ist es naiv, nach "reinem" OOP zu streben. Einige Probleme lassen sich nicht gut auf einen objektorientierten Ansatz abbilden und lassen sich leichter durch andere Paradigmen lösen. Wenn Sie auf ein solches Problem stoßen, bestehen Sie nicht auf einem minderwertigen Ansatz.
Erwägen Sie, die Fibonacci-Sequenz objektorientiert zu berechnen . Ich kann mir keinen vernünftigen Weg vorstellen, das zu tun. einfache strukturierte Programmierung bietet die beste Lösung für dieses Problem.
Ihre
isVisible
Beziehung gehört zu beiden Klassen oder zu keiner oder tatsächlich: zum Kontext . Verhaltenslose Datensätze sind typisch für einen funktionalen oder prozeduralen Programmieransatz, der am besten zu Ihrem Problem zu passen scheint. Es ist nichts falsch mitund es ist nichts falsch daran
Card
, keine Methoden jenseitsrank
undsuit
Accessoren zu haben.quelle
fibonacci
Methode für eine Instanz von aufinteger
. Ich möchte Ihren Punkt betonen, dass es bei OO um die Verkapselung geht, auch an scheinbar kleinen Orten. Lassen Sie die Ganzzahl herausfinden, wie die Arbeit erledigt wird. Später können Sie die Implementierung verbessern und Caching hinzufügen, um die Leistung zu verbessern. Im Gegensatz zu Funktionen folgen Methoden den Daten, sodass alle Aufrufer von einer verbesserten Implementierung profitieren. Möglicherweise werden Ganzzahlen mit beliebiger Genauigkeit später hinzugefügt. Sie können transparent wie normale Ganzzahlen behandelt werden und über eine eigenefibonacci
Methode zur Leistungsoptimierung verfügen .Fibonacci
eine Unterklasse der abstrakten Klasse istSequence
, wird die Sequenz von einer beliebigen Zahlenmenge verwendet und ist für das Speichern von Startwerten, Status, Caching und einem Iterator verantwortlich.Dies ist eine schwierige Frage, da sie auf einigen fehlerhaften Prämissen beruht:
Ich werde nicht viel auf # 1-3 eingehen, da jeder seine eigene Antwort hervorbringen könnte und dies zu vielen meinungsbasierten Diskussionen einlädt. Besonders beunruhigend finde ich jedoch die Idee, dass es bei OOP um die Kopplung von Daten und Verhalten geht. Dies führt nicht nur zu # 4, sondern auch zu der Idee, dass alles eine Methode sein sollte.
Es gibt einen Unterschied zwischen den Operationen, die einen Typ definieren, und den Möglichkeiten, wie Sie diesen Typ verwenden können. Die Fähigkeit, das
i
th-Element abzurufen , ist für das Konzept eines Arrays von entscheidender Bedeutung, aber das Sortieren ist nur eines der vielen Dinge, die ich mit einem tun kann. Das Sortieren muss nicht mehr eine Methode sein als "ein neues Array erstellen, das nur die geraden Elemente enthält".Bei OOP geht es um die Verwendung von Objekten. Objekte sind nur ein Weg zur Abstraktion . Abstraktion ist ein Mittel, um unnötige Kopplungen in Ihrem Code zu vermeiden und kein Selbstzweck. Wenn Ihre Vorstellung von einer Karte nur durch den Wert ihrer Suite und ihres Ranges definiert ist, ist es in Ordnung, sie als einfaches Tupel oder Datensatz zu implementieren. Es gibt keine unwesentlichen Details, von denen ein anderer Teil des Codes eine Abhängigkeit bilden könnte. Manchmal hast du einfach nichts zu verbergen.
Sie würden keine
isVisible
Methode dieserCard
Art entwickeln, da es für Ihre Vorstellung von einer Karte wahrscheinlich nicht wesentlich ist, sichtbar zu sein (es sei denn, Sie haben sehr spezielle Karten, die durchscheinend oder undurchsichtig werden können ...). Sollte es eine Methode desPlayer
Typs sein? Nun, das ist wahrscheinlich auch keine definierende Eigenschaft der Spieler. Sollte es ein Teil irgendeinerViewport
Art sein? Dies hängt wiederum davon ab, wie Sie ein Ansichtsfenster definieren und ob die Prüfung der Sichtbarkeit von Karten ein wesentlicher Bestandteil der Definition eines Ansichtsfensters ist.Es ist sehr viel möglich,
isVisible
sollte nur eine freie Funktion sein.quelle
Nein, das sind sie nicht. Plain-Old-Data-Objekte sind ein vollkommen gültiges Muster, und ich würde sie in jedem Programm erwarten, das sich mit Daten befasst, die zwischen bestimmten Bereichen Ihres Programms persistent sein oder kommuniziert werden müssen.
Während Ihre Datenebene beim Einlesen aus der Tabelle möglicherweise eine vollständige
Player
KlassePlayers
spoolt, kann es sich stattdessen nur um eine allgemeine Datenbibliothek handeln, die einen POD mit den Feldern aus der Tabelle zurückgibt, der an einen anderen Bereich Ihres Programms übergeben wird, der konvertiert ein Spieler POD zu Ihrer konkretenPlayer
Klasse.Die Verwendung von Datenobjekten, entweder typisiert oder nicht typisiert, ist in Ihrem Programm möglicherweise nicht sinnvoll, macht sie jedoch nicht zu einem Anti-Pattern. Wenn sie sinnvoll sind, verwenden Sie sie, und wenn nicht, tun Sie es nicht.
quelle
Plain-Old-Data objects are a perfectly valid pattern
Ich habe nicht gesagt, dass dies nicht der Fall ist. Ich sage, es ist falsch, wenn sie die gesamte untere Hälfte der Anwendung ausfüllen.Persönlich denke ich, dass Domain Driven Design dazu beiträgt, Klarheit in dieses Problem zu bringen. Die Frage, die ich stelle, ist, wie beschreibe ich das Kartenspiel den Menschen? Mit anderen Worten, was modelliere ich? Wenn das, was ich modelliere, wirklich das Wort "Ansichtsfenster" und ein Konzept enthält, das seinem Verhalten entspricht, dann würde ich das Ansichtsfensterobjekt erstellen und es tun lassen, was es logisch sollte.
Wenn ich jedoch das Konzept des Ansichtsfensters nicht in meinem Spiel habe, und es ist etwas, von dem ich denke, dass ich es brauche, weil sich der Code sonst "falsch anfühlt". Ich denke zweimal darüber nach, mein Domain-Modell hinzuzufügen.
Das Wort Modell bedeutet, dass Sie eine Darstellung von etwas erstellen. Ich warne davor, eine Klasse einzufügen, die etwas Abstraktes darstellt, das über das hinausgeht, was Sie darstellen.
Ich werde hinzufügen, dass es möglich ist, dass Sie das Konzept eines Ansichtsfensters in einem anderen Teil Ihres Codes benötigen, wenn Sie eine Schnittstelle mit einer Anzeige benötigen. In DDD-Begriffen wäre dies jedoch ein Infrastrukturproblem und würde außerhalb des Domänenmodells bestehen.
quelle
Normalerweise mache ich keine Eigenwerbung, aber Tatsache ist, dass ich viel über OOP-Designprobleme in meinem Blog geschrieben habe . Um mehrere Seiten zusammenzufassen: Sie sollten nicht mit Klassen beginnen. Beginnend mit Interfaces oder APIs und Shape-Code von dort haben Sie höhere Chancen, aussagekräftige Abstraktionen bereitzustellen, Spezifikationen anzupassen und zu vermeiden, dass konkrete Klassen mit nicht wiederverwendbarem Code überladen werden.
Wie dies anzuwenden
Card
-Player
Problem: Erstellen einerViewPort
Abstraktion Sinn macht , wenn Sie denkenCard
undPlayer
als zwei unabhängige Bibliotheken zu sein (was bedeuten würde ,Player
manchmal ohne verwendet wirdCard
). Ich bin jedoch geneigt zu denken , einePlayer
hältCards
und bieten sollteCollection<Card> getVisibleCards ()
Accessor zu ihnen. Diese beiden Lösungen (ViewPort
und meine) sind besser als das BereitstellenisVisible
einer MethodeCard
oderPlayer
im Hinblick auf das Erstellen verständlicher Codebeziehungen.Eine Lösung von außerhalb der Klasse ist viel, viel besser für die
DocumentId
. Es gibt wenig Motivation, eine komplexe Datenbankbibliothek (im Grunde genommen eine Ganzzahl) abhängig zu machen.quelle
Ich bin nicht sicher, ob die vorliegende Frage auf der richtigen Ebene beantwortet wird. Ich hatte den Weisen im Forum dringend gebeten, hier aktiv über den Kern der Frage nachzudenken.
U Mad führt eine Situation an, in der er glaubt, dass die Programmierung nach seinem Verständnis von OOP im Allgemeinen dazu führen würde, dass viele Blattknoten Daten enthalten, während seine API der oberen Ebene den größten Teil des Verhaltens ausmacht.
Ich denke, das Thema ging ein wenig tangential dahin, ob isVisible für Card vs Player definiert wird. es war nur ein illustriertes Beispiel, wenn auch naiv.
Ich hatte die hier erfahrene drängen, um das vorliegende Problem zu betrachten. Ich denke, es gibt eine gute Frage, auf die U Mad gedrängt hat. Ich verstehe, dass Sie die Regeln und die betreffende Logik auf ein eigenes Objekt übertragen würden. aber wie ich verstehe ist die frage
Meine Sicht:
Ich denke, Sie stellen eine Frage der Granularität, die in der objektorientierten Programmierung nur schwer richtig zu stellen ist. Nach meiner kleinen Erfahrung würde ich keine Entität in mein Modell aufnehmen, die selbst kein Verhalten enthält. Wenn ich müsste, hätte ich wahrscheinlich eine Struktur verwendet, die so konzipiert ist, dass sie eine solche Abstraktion enthält, im Gegensatz zu einer Klasse, die die Idee hat, Daten und Verhalten zu kapseln.
quelle
Point
mitgetX()
Funktion vor. Sie könnten sich vorstellen, dass es eines seiner Attribute bekommt, aber es könnte auch von der Festplatte oder aus dem Internet gelesen werden. Erhalten und Setzen ist Verhalten, und Klassen zu haben, die genau das tun, ist völlig in Ordnung. Datenbanken erhalten und setzen nur Daten fwiwEine häufige Ursache für Verwirrung in OOP ist die Tatsache, dass viele Objekte zwei Aspekte des Zustands einschließen: die Dinge, die sie kennen, und die Dinge, die sie kennen. Diskussionen über den Objektzustand ignorieren häufig den letzteren Aspekt, da es in Frameworks, in denen Objektreferenzen promiskuitiv sind, keine allgemeine Möglichkeit gibt, zu bestimmen, was die Dinge über ein Objekt wissen könnten, dessen Referenz jemals der Außenwelt ausgesetzt war.
Ich würde vorschlagen, dass es wahrscheinlich hilfreich wäre, ein
CardEntity
Objekt zu haben, das diese Aspekte der Karte in separaten Komponenten kapselt. Eine Komponente würde sich auf die Markierungen auf der Karte beziehen (z. B. "Diamantenkönig" oder "Lavaschlag; Spieler haben die AC-3-Chance auszuweichen oder 2D6-Schaden zu erleiden"). Man könnte sich auf einen einzigartigen Aspekt des Zustands beziehen, wie z. B. die Position (z. B. im Deck oder in Joes Hand oder auf dem Tisch vor Larry). Ein dritter könnte sich darauf beziehen, kann es sehen (vielleicht niemand, vielleicht ein Spieler oder vielleicht viele Spieler). Um sicherzustellen, dass alles synchron bleibt, werden Orte, an denen sich eine Karte möglicherweise befindet, nicht als einfache Felder, sondern alsCardSpace
Objekte eingekapselt . um eine Karte auf ein Feld zu verschieben, würde man ihr einen Verweis auf das richtige gebenCardSpace
Objekt; es würde sich dann aus dem alten Raum entfernen und sich in den neuen Raum versetzen).Die explizite Verkapselung von "Wer weiß über X Bescheid?" Es ist manchmal Vorsicht geboten, um Speicherlecks zu vermeiden, insbesondere bei vielen Assoziationen (z. B. wenn neue Karten entstehen und alte Karten verschwinden). Man muss sicherstellen, dass Karten, die aufgegeben werden sollten, nicht dauerhaft an langlebigen Objekten hängen bleiben ) aber wenn das Vorhandensein von Referenzen auf ein Objekt einen relevanten Teil seines Zustands ausmacht, ist es völlig richtig, dass das Objekt selbst solche Informationen explizit kapselt (selbst wenn es die eigentliche Verwaltung an eine andere Klasse delegiert).
quelle
Und wie ist das schlecht / schlecht beraten?
Um eine ähnliche Analogie zu Ihrem Kartenbeispiel zu verwenden, betrachten Sie a
Car
, aDriver
und Sie müssen feststellen, ob dasDriver
Laufwerk das kannCar
.OK, also hast du entschieden, dass du nicht
Car
wissen willst , ob dasDriver
Auto den richtigen Autoschlüssel hat oder nicht, und aus einem unbekannten Grund hast du auch beschlossen, dass du nichtDriver
über dieCar
Klasse Bescheid wissen willst (du bist nicht ganz Fleisch geworden) dies auch in Ihrer ursprünglichen Frage). Daher haben Sie eine Zwischenklasse, die derUtils
Klasse ähnelt und die Methode mit Geschäftsregeln enthält , um einenboolean
Wert für die obige Frage zurückzugeben.Ich denke das ist in Ordnung. Die Zwischenklasse muss jetzt möglicherweise nur noch nach Autoschlüsseln suchen, kann jedoch überarbeitet werden, um zu prüfen, ob der Fahrer einen gültigen Führerschein besitzt, unter Alkoholeinfluss steht oder in einer dystopischen Zukunft auf DNA-Biometrie prüft. Durch die Verkapselung gibt es wirklich keine großen Probleme, wenn diese drei Klassen zusammen existieren.
quelle