Non object-oriented objects

I always feel uncomfortable when I encounter instances of certain classes in the codebase I’m working with. Perhaps uncomfortable is not the right word here; the whole situation is a huge paradox: objects that fail to behave in an object-oriented way. Of course I’m talking about classes like Tuple and Triplet (or whatever name they may have in different libraries).

Now, don’t get me wrong. I’m not talking about classes with two (like HashMap) or three (like BiFunction) generic parameters. There’s nothing wrong with those. The problem starts to manifest when people start grouping two or three (seemingly) totally unrelated “things” into Tuples, Triples or similar ‘object containers’. A Tuple allows its users two put two objects that have nothing in common, into a common container. A possible (not valid, though) use case would be something like Tuple tuple = new Tuple(“John”, “Smith”). In this context, a Triple is far worse, as it lets people do the same thing, but with three “things”. Sticking to the previous example, now we have Triple triple = new Triple(“John”, “Smith”, 21). Well, what’s 21? Does it represent an age? Home runs? Number of tennis matches lost in a row? Nobody knows, because it’s totally context dependent. It can be any of those, or anything else, because it depends on the context, a context that is hidden to the reader.

Good object oriented practices tell us that a class should model/abstract a part of the domain (real world) we have to cope with. However, I cannot imagine a context, in which such general purpose classes are valid or relevant. The example above would have been much better off with something like:

public class Person {
  private String firstName;
  private String lastName;
  private int nrOfFriends;

  //...
}

A person is a real world concept, anybody can imagine a person; but what’s a Tuple in a real world context?

In Apache Commons there are declared objects like MutableTriple and ImmutableTriple (aslo MutablePair and ImmutablePair). They declare methods like getLeft(), getMiddle() and getRight() – this naming convention does not only screams that these left, middle and right “things” should be in an own class, but it’s awful from the readability/understandability point of view.

Once I saw in a project I used to work on some code like the following:

Triple<Double, String, Date> someNameDidNotHelpUnderstandAnything = new MutableTriple<>();
//...
someNameDidNotHelpUnderstandAnything.setLeft(...)
//...
someNameDidNotHelpUnderstandAnything.setMiddle(...)
//...
someNameDidNotHelpUnderstandAnything.setRight(...)

After some time, it turned out that this construct was meant to temporarily hold the price for some currency pair, valid at a given time. Not that clean, right? I think it’s easy to choose between this, or something like:

TempPrice tempPrice = new TempPrice();
tempPrice.setPrice(...)
//...
tempPrice.setCurrencyPair(...)
//...
tempPrice.setDate(...)

While I was writing this post, I was thinking about a valid use case for tuples and triples like this. To be honest, I could not find any. I really think such classes should not exist for Java (or any object-oriented language). They make more harm than good, as they are way too general purpose.

If a situation calls for a Tuple or a Triple, chances are high that the program flow is not very well thought out. In such cases some refactoring could be really beneficial.

As a side note, things are even tougher in Scala. Scala has built in support for tuples with two, three, four … (and so on, up to 22 components). No kidding, Tuple2, Tuple3, … Tuple21, Tuple22 are all valid, implemented classes in Scala. However, as always, there is a big difference when compared to Java. In Scala, thanks to some syntax sugar, you don’t have to create a Triple like val t = new Triple(“John”, “Smith”, 21), but simply val t = (“John”, “Smith”, 21). To access the three members, one would use t._1, t._2, and t._3 (Imagine this for a Tuple22, with t._21 and t._22). Not any more beautiful than getLeft(), getMiddle() and getRight(). Even so, Scala is usually much less verbose than Java; the length of the methods (in many cases) are much shorter, so perhaps in such shortened scopes, they could be present without much complicating the comprehension of the code.

Advertisements

Author: tamasgyorfi

Senior software engineer, certified enterprise architect and certified Scrum master. Feel free to connect on Twitter: @tamasgyorfi

2 thoughts on “Non object-oriented objects”

  1. The start of the article was great, but when I saw TempPrice tempPrice = new TempPrice(); I shrugged. Why would a tempPrice make sense without all its properties set?
    This sort of abstraction only increases complexity and makes the design more brittle since a “triple”‘s constructor at least requires the programmer to supply all the three arguments that make up the triplet. The only advantage this method adds is that at least the ‘thing’ has got a name, but nothing else.

    1. Good catch, constructor parameters would have been better in that case. Anyways, that change never actually made it into the code base (unfortunately).
      The point here was to exemplify that an ‘entity’ with a generic name is less clear than a properly named class. Even better modifications are always welcome 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s