17

This article claims that a data class is a "code smell". The reason:

It's a normal thing when a newly created class contains only a few public fields (and maybe even a handful of getters/setters). But the true power of objects is that they can contain behavior types or operations on their data.

Why is it wrong for an object to contain only data? If the core responsibility of the class is to represent data, wouldn't add methods that operate on the data break the Single Responsibility Principle?

  • 1
    This is going to depend strongly on language features. In Python, for example, there's no distinction between the "field" and its accessors, unless you go out of your way to write Java in Python. – Josh Caswell Dec 15 '16 at 11:39
  • 1
    I think having some data only classes is not a code smell per se, but if most classes are like that then we are talking about the "anemic domain" antipattern en.wikipedia.org/wiki/Anemic_domain_model – Tulains Córdova Dec 15 '16 at 12:03
  • 1
    I don't see how this question is a duplicate. The other questions is about the use of data classes in OO, while this one is about the downsides of data classes - entirely different subjects. – Milos Mrdovic May 18 '18 at 10:04
  • You may want to read this answer on stackoverflow which is much more differentiated than the top voted answer here that postulates the inferiority of the rich domain model and present it like a proven fact. stackoverflow.com/questions/23314330/… – McLovin Mar 28 at 13:58
30

There is absolutely nothing wrong with having pure data objects. The author of the piece quite frankly doesn't know what he's talking about.

Such thinking stems from an old, failed, idea that "true OO" is the best way to program and that "true OO" is all about "rich data models" where one mixes data and functionality.

Reality has shown us that actually the opposite is true, especially in this world of multi-threaded solutions. Pure functions, combined with immutable data-objects, is a demonstrably better way to code.

  • 1
    Just wanted to add that pure data objects can be invaluable for modeling relationships, validation, controlling access/changes. – Adrian Dec 15 '16 at 11:28
  • 2
    Although it is nice if those pure functions that only take an instance of the immutable data object as argument are implemented as methods on the data object. – RemcoGerlich Dec 15 '16 at 11:41
  • 6
    If the function takes an argument of that data type, it is already coupled to the data. – RemcoGerlich Dec 15 '16 at 11:48
  • 3
    Downvoting because this is incorrect, or at best a matter of opinion. In an OO language, it usually makes sense to have an object contain both the data (which can still be immutable!) and the methods that act on it. Pure functions and separate data are great in other language paradigms, but if you’re doing OO, do OO fully. – Marnen Laibow-Koser Mar 25 at 23:36
  • 3
    Reality has shown us a lot of things. -1 for dogmatic know-it-all "the others have failed" opinion. Also, the author does not say that pure data objects are "wrong", just that they are a "code smell" and worthy of questioning. I only regret that I have one downvote to give for my country. :-) – user949300 Mar 26 at 0:07
6

There is absolutely nothing wrong with having pure data objects. The author has an opinion not shared by the software developers I know.

Especially for database mapping you in general have entity classes which only contain the fields stored in the data base and getters and setters. Wikipedia Hibernate (framework)

The hole idea of Java beans used by a lot of tools / frameworks is based on data classes called beans that only contain fields and the related getters and setters. Wikipdia JavaBeans

Fazit:
If someone claims that something is 'bad' or 'a code smell' you should always look for the reasons given. If the reasons do not convince you ask someone else for better reasons or a different opinion. (Like you did in this forum)

  • The author does not say that pure data objects are "wrong". They say that pure data objects are a "code smell", which means that you should think twice about using them. – user949300 Mar 26 at 0:09
  • 1
    @user949300, you seem confused. If the author refers to them as a code smell, then he indicates there might be something wrong with them. As they are widely recognised these days as very good practice, they clearly aren't a code smell. Thus MrSmith42 is correct: there is absolutely nothing wrong with them. – David Arno Mar 26 at 8:46
3

A good argument why by Martin Fowler:

"Tell-Don't-Ask is a principle that helps people remember that object-orientation is about bundling data with the functions that operate on that data. It reminds us that rather than asking an object for data and acting on that data, we should instead tell an object what to do. This encourages to move behavior into an object to go with the data."

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

  • 1
    The problem here is that Fowler artificially restricts "tell don't ask" by changing functions from asking a wider scope to just asking the object scope. They are still asking. "Tell don't ask" can in fact be taken a step further by truly telling those functions via their argument lists. And thus we arrive at data objects and separate (data wise) functions being the true implementation of "tell don't ask". So rather than being a good argument for the claim that data classes are a code smell, it in fact further proves the opposite. – David Arno Mar 26 at 9:59
  • 1
    @DavidArno You’re forgetting about encapsulation and hiding. You tell an object to execute a member method, and the member method goes into the black box of the object and does whatever it has to to get the answer. If you ask an object from outside, you don’t have access to its private state, and so either the object exposes more state than is wise, or the asker has to jump through more hoops than should be necessary. I don’t see why you’d ever “ask” an object in an OO environment. (Other programming paradigms may call for different approaches, of course.) – Marnen Laibow-Koser Mar 26 at 22:09
  • @MarnenLaibow-Koser, no Marnen, you may rest assured that I've in no way forgotten about encapsulation. Let's take an example. I have a public method, Foo. It calls a private method, Bar. Bar needs access to a piece of data, baz. With Fowler's take on "tell, don't ask", baz will be a private field inside the object that was passed in via the constructor and Bar will access it, ie Bar asks the object for baz. There's no true "tell" going on beyond the object being told. In this obsession with thinking objects we've forgotten the poor method. It's relegated to 2nd class. – David Arno Mar 27 at 8:14
  • 1
    @DavidArno Of course you can pass baz in as a parameter to a static method, but to do that, you first need to ask the object for it. Perhaps in a programming paradigm where methods were primary (like, say, functional programming) this makes sense, but in an OO environment, it absolutely does not, because objects are primary and should contain both the data and the functions to act on it. Your claim that removing the method from the object has increased encapsulation is also exactly backwards, as far as I can tell, because it means that you now have baz appearing outside the object. – Marnen Laibow-Koser Mar 27 at 11:48
  • 1
    @MarnenLaibow-Koser, I don't claim to "be doing OO". I write code and I use good techniques to do so. Whether those techniques come from the functional paradigm, or the OO paradigm, or who-gives-a-damn paradigm is of no interest to me. Picking a paradigm and sticking to it as fully as possible is pure dogma. It is bad. It is ridiculous. It stifles you and results in inferior code. Don't do it. – David Arno Mar 27 at 11:58
0

What you need to understand is that there are two kinds of objects:

  • Objects that have behavior. These should refrain from giving public access to most/any of their data members. I expect only very few accessor methods defined for these.

    An example would be a compiled regex: The object is created to provide a certain behavior (to match a string against a specific regex, and to report the (partial) matches), but how the compiled regex does its work is none of the user's business.

    Most classes that I write are in this category.

  • Objects that are really just data. These should just declare all of their members public (or provide the full set of accessors for them).

    An example would be a class Point2D. There is absolutely no invariant that needs to be ensured for the members of this class, and users should be able to just access the data via myPoint.x and myPoint.y.

    Personally, I don't use such classes much, but I guess there is no larger piece of code that I've written that doesn't use such a class somewhere.

Becoming proficient with object orientation includes realizing that this distinction exists, and learning to classify a class' function into one of these two categories.


If you code in C++, you can make this distinction explicit by using class for the first category of objects, and struct for the second. Of course, the two are equivalent, except that class means that all members are private by default, while struct declares all members public by default. Which is exactly the sort of information you want to communicate.

  • An explanation for the downvote would be cool... – cmaster Apr 25 at 7:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.