Warum werden Datenklassen als Codegeruch betrachtet?

18

Dieser Artikel behauptet, dass eine Datenklasse ein "Codegeruch" ist. Der Grund:

Es ist normal, wenn eine neu erstellte Klasse nur wenige öffentliche Felder enthält (und möglicherweise sogar eine Handvoll Getter / Setter). Die wahre Stärke von Objekten besteht jedoch darin, dass sie Verhaltenstypen oder Operationen für ihre Daten enthalten können.

Warum ist es falsch, dass ein Objekt nur Daten enthält? Wenn die Hauptverantwortung der Klasse darin besteht, Daten darzustellen, würden Sie dann nicht Methoden hinzufügen, die auf die Daten angewendet werden, um das Prinzip der Einzelverantwortung zu verletzen ?

Sipo
quelle
1
Dies wird stark von den Sprachfunktionen abhängen. In Python zum Beispiel gibt es keinen Unterschied zwischen dem "Feld" und seinen Zugriffsmethoden, es sei denn, Sie tun alles, um Java in Python zu schreiben .
jscs
1
Ich denke , einige Daten nur Klassen, die nicht ein Code Geruch per se, aber wenn die meisten Klassen sind so dann reden wir über die „anämisch Domain“ Antipattern en.wikipedia.org/wiki/Anemic_domain_model
Tulains Córdova
1
Ich sehe nicht, wie diese Frage ein Duplikat ist. Bei den anderen Fragen geht es um die Verwendung von Datenklassen in OO, während es um die Nachteile von Datenklassen geht - ganz andere Themen.
Milos Mrdovic
Vielleicht möchten Sie diese Antwort zu Stackoverflow lesen, die viel differenzierter ist als die oben gewählte Antwort, in der die Minderwertigkeit des Rich Domain-Modells postuliert und wie eine nachgewiesene Tatsache dargestellt wird. stackoverflow.com/questions/23314330/...
McLovin

Antworten:

30

Es ist absolut nichts Falsches daran, reine Datenobjekte zu haben. Der Autor des Stücks weiß ehrlich gesagt nicht, wovon er spricht.

Ein solches Denken stammt aus einer alten, fehlgeschlagenen Idee, dass "True OO" der beste Weg zum Programmieren ist und dass es sich bei "True OO" um "Rich Data Models" handelt, bei denen man Daten und Funktionalität mischt.

Die Realität hat uns gezeigt, dass genau das Gegenteil der Fall ist, insbesondere in dieser Welt der Multithread-Lösungen. Reine Funktionen, kombiniert mit unveränderlichen Datenobjekten, sind nachweislich ein besserer Weg, um zu codieren.

David Arno
quelle
1
Ich wollte nur hinzufügen, dass reine Datenobjekte für die Modellierung von Beziehungen, die Validierung und die Kontrolle von Zugriffen / Änderungen von unschätzbarem Wert sein können.
Adrian
2
Obwohl es schön ist, wenn diejenigen reinen Funktionen, die nur eine Instanz des unveränderlichen Datenobjekts als Argument verwenden, als Methoden für das Datenobjekt implementiert werden.
RemcoGerlich
7
Wenn die Funktion ein Argument dieses Datentyps akzeptiert, ist sie bereits mit den Daten gekoppelt.
RemcoGerlich
4
Downvoting, weil das falsch oder bestenfalls Ansichtssache ist. In einer OO-Sprache ist es normalerweise sinnvoll, dass ein Objekt sowohl die Daten (die noch unveränderlich sein können!) Als auch die Methoden enthält, die darauf einwirken. Reine Funktionen und separate Daten sind in anderen Sprachparadigmen großartig, aber wenn Sie OO tun, tun Sie OO vollständig.
Marnen Laibow-Koser
3
Die Realität hat uns viele Dinge gezeigt. -1 für dogmatische Besserwisser "die anderen haben versagt" Meinung. Der Autor sagt auch nicht, dass reine Datenobjekte "falsch" sind, sondern nur, dass es sich um einen "Codegeruch" handelt, der in Frage gestellt werden muss. Ich bedaure nur, dass ich eine Gegenstimme für mein Land abgeben muss. :-)
user949300
7

Es ist absolut nichts Falsches daran, reine Datenobjekte zu haben. Der Autor hat eine Meinung, die von den mir bekannten Softwareentwicklern nicht geteilt wurde.

Insbesondere für das Datenbank-Mapping haben Sie im Allgemeinen Entitätsklassen, die nur die in der Datenbank gespeicherten Felder sowie Getter und Setter enthalten. Wikipedia Hibernate (Framework)

Die Grundidee von Java-Beans, die von vielen Tools / Frameworks verwendet werden, basiert auf Datenklassen, die als Beans bezeichnet werden und nur Felder und die zugehörigen Getter und Setter enthalten. Wikipdia JavaBeans

Fazit:
Wenn jemand behauptet, etwas sei 'schlecht' oder 'ein Codegeruch ', sollten Sie immer nach den angegebenen Gründen suchen. Wenn die Gründe nicht überzeugen, fragen Sie jemanden nach besseren Gründen oder einer anderen Meinung. (Wie du es in diesem Forum getan hast)

MrSmith42
quelle
Der Autor sagt nicht, dass reine Datenobjekte "falsch" sind. Sie sagen, dass reine Datenobjekte ein "Code-Geruch" sind, was bedeutet, dass Sie zweimal darüber nachdenken sollten, sie zu verwenden.
user949300
1
@ user949300, Sie scheinen verwirrt zu sein. Wenn der Autor sie als Code-Geruch bezeichnet, weist er darauf hin, dass möglicherweise etwas mit ihnen nicht stimmt. Da sie heutzutage weithin als sehr gute Praxis anerkannt sind, sind sie eindeutig kein Codegeruch. MrSmith42 hat also Recht: Sie haben absolut nichts auszusetzen.
David Arno
4

Ein gutes Argument, warum von Martin Fowler:

"Tell-Don't-Ask ist ein Prinzip, mit dem sich die Menschen daran erinnern, dass es bei der Objektorientierung darum geht, Daten mit den Funktionen zu bündeln, die auf diese Daten angewendet werden. Es erinnert uns daran, dass wir ein Objekt nicht nach Daten fragen und auf diese Daten reagieren müssen." sollte stattdessen einem Objekt mitteilen, was zu tun ist. Dies ermutigt dazu, das Verhalten in ein Objekt zu verschieben, das zu den Daten passt. "

https://martinfowler.com/bliki/TellDontAsk.html

Curtis Yallop
quelle
1
Das Problem hierbei ist, dass Fowler "Tell Don't Ask" künstlich einschränkt, indem Funktionen von der Abfrage eines breiteren Bereichs zur Abfrage des Objektbereichs geändert werden. Sie fragen immer noch. "Tell don't ask" kann in der Tat noch einen Schritt weiter gehen, indem man diese Funktionen über ihre Argumente-Listen wirklich erzählt. Und so kommen wir zu Datenobjekten und separaten (datenweisen) Funktionen, die die wahre Implementierung von "Tell Don't Ask" sind. Anstatt also ein gutes Argument für die Behauptung zu sein, dass Datenklassen ein Codegeruch sind, beweist es tatsächlich das Gegenteil.
David Arno
2
@DavidArno Du vergisst das Einkapseln und Verstecken. Sie weisen ein Objekt an, eine Member-Methode auszuführen, und die Member-Methode wird in die Blackbox des Objekts verschoben und unternimmt alles, um die Antwort zu erhalten. Wenn Sie ein Objekt von außen fragen, haben Sie keinen Zugriff auf seinen privaten Status, sodass das Objekt entweder mehr Status als sinnvoll anzeigt, oder der Fragesteller muss durch mehr Rahmen springen, als erforderlich sein sollte. Ich verstehe nicht, warum Sie jemals ein Objekt in einer OO-Umgebung "fragen" würden. (Andere Programmierparadigmen erfordern möglicherweise natürlich andere Ansätze.)
Marnen Laibow-Koser
2
@DavidArno Natürlich Sie können passieren bazals Parameter zu einer statischen Methode, sondern das zu tun, müssen Sie zunächst fragen , das Objekt für sie. Vielleicht ist dies in einem Programmierparadigma, in dem Methoden primär waren (wie zum Beispiel funktionale Programmierung), sinnvoll, aber in einer OO-Umgebung absolut nicht, da Objekte primär sind und sowohl die Daten als auch die Funktionen enthalten sollten, auf die sie angewendet werden sollen. Ihre Behauptung, dass das Entfernen der Methode aus dem Objekt zu einer erhöhten Verkapselung geführt hat, ist meines Erachtens ebenfalls genau rückwärts , da Sie jetzt bazaußerhalb des Objekts erscheinen.
Marnen Laibow-Koser
1
@ MarnenLaibow-Koser, ich behaupte nicht "mache OO". Ich schreibe Code und verwende dafür gute Techniken. Es interessiert mich nicht, ob diese Techniken aus dem funktionalen Paradigma oder dem OO-Paradigma oder dem Who-give-a-Damn-Paradigma stammen. Ein Paradigma zu wählen und sich so weit wie möglich daran zu halten, ist ein reines Dogma. Es ist schlecht. Es ist lächerlich. Es unterdrückt Sie und führt zu minderwertigem Code. Tu es nicht.
David Arno
1
@DavidArno Im Gegensatz dazu erhalten Sie leistungsstarke Abstraktionen auf hoher Ebene und logisch konsistenten, wartbaren Code, wenn Sie sich vollständig einem Paradigma (einem anständigen Paradigma, nicht nur OO) verpflichten. Ich sage das nicht als dogmatisch, sondern eher als pragmatisch. Ich habe zu viel Code gesehen und gepflegt, der anscheinend mit einer Einstellung wie Ihrer erstellt wurde, bei der sich der Autor nicht wirklich auf die logische Konsistenz des verwendeten Systems festgelegt hat. Es ist schwer zu verstehen, schwer zu warten und schwer zu modifizieren. Kein Paradigma ist perfekt, aber im Allgemeinen ist eine Mischung (sofern nicht sorgfältig überlegt) schwerer zu verstehen.
Marnen Laibow-Koser
2

Was Sie verstehen müssen, ist, dass es zwei Arten von Objekten gibt:

  • Objekte, die Verhalten haben . Diese sollten es unterlassen, den meisten ihrer Datenmitglieder öffentlich zugänglich zu machen. Ich erwarte nur sehr wenige Accessormethoden, die für diese definiert sind.

    Ein Beispiel wäre ein kompilierter regulärer Ausdruck: Das Objekt wird erstellt, um ein bestimmtes Verhalten bereitzustellen (um eine Zeichenfolge mit einem bestimmten regulären Ausdruck abzugleichen und die (Teil-) Übereinstimmungen zu melden), aber wie der kompilierte reguläre Ausdruck seine Arbeit tut, ist nicht Sache des Benutzers Geschäft.

    Die meisten Klassen, die ich schreibe, sind in dieser Kategorie.

  • Objekte, die eigentlich nur Daten sind . Diese sollten lediglich alle ihre Mitglieder für öffentlich erklären (oder ihnen den vollständigen Zugriffssatz zur Verfügung stellen).

    Ein Beispiel wäre eine Klasse Point2D. Es gibt absolut keine Invariante, die für die Mitglieder dieser Klasse sichergestellt werden muss, und Benutzer sollten nur über myPoint.xund auf die Daten zugreifen können myPoint.y.

    Persönlich verwende ich solche Klassen nicht viel, aber ich denke, es gibt keinen größeren Code, den ich geschrieben habe und der nicht irgendwo eine solche Klasse verwendet.

Um mit der Objektorientierung vertraut zu sein, muss man erkennen, dass es diese Unterscheidung gibt, und lernen, die Funktion einer Klasse in eine dieser beiden Kategorien einzuteilen.


Wenn Sie in C ++ codieren, können Sie diese Unterscheidung explizit vornehmen, indem Sie classfür die erste Kategorie von Objekten und structfür die zweite Kategorie verwenden . Natürlich sind die beiden gleich, außer dass dies classbedeutet, dass standardmäßig alle Mitglieder privat sind, während standardmäßig structalle Mitglieder öffentlich sind. Welches ist genau die Art von Informationen, die Sie kommunizieren möchten.

In cmaster stellst du Monica wieder her
quelle
1
Eine Erklärung für die Ablehnung wäre cool ...
cmaster - monica wieder einsetzen
Danke für die Antwort. Ich hasse es, wenn Leute ohne Grund abstimmen. Wenn Sie ein Problem mit einer Antwort haben, erklären Sie warum .
Sipo