How far can you push Object Oriented Programming


A getter is a failure to design an object. It violates encapsulation which is a core principle of object oriented programing.

Now please tell me, how do you design a libraries hash table collection under that philosophy?

I recently opened an answer of mine with the previous two lines. They roused a response from one of our long time contributors:

"Now please tell me, how do you design a libraries hash table collection under that philosophy?" – I feel a negative vibe here. I'm not judging, I do that sometimes too. I more than happy to answer, if I feel there's an honest effort to try to understand.

Robert Bräutigam

To which I am responding with this question. Now sure, it may sound like I'm asking two questions since the title and body differ, but I'm trying to grok much more than hash table design here.

I've come to believe that object oriented programming is good. But that not every line of a program can be purely object oriented. And that is fine. Much like you can't write a program free of static methods (you at least need main) but that doesn't mean it all has to be static.

That idea is what my somewhat clumsy example was trying to illustrate. But if that idea is flawed I would love to know why.

One of the practices of OOP is when a method needs data it's better to move the method than to move the data to put them together. This enables encapsulation. State is not something to share, simply something that changes behavior.

However, some boundaries, like library boundaries, make it impossible to move the method and so you move data. Thus getter ridden Data Transfer "Objects" are born. And so OOP ideals are compromised in the face of reality. Rather than give up entirely in the face of this I consider that a compromise to isolate rather than spread. This is why I think of OOP everywhere as unachievable but still think OOP is good when you can do it.

For bonus points, please do show me how a OOP purist would design a hash table without getters.

Best Answer

However, some boundaries, like library boundaries, make it impossible to move the method and so you move data.

I agree. Sometimes you do not (or can not) know the behavior that will be attached to your data, in these cases you'll publish the data.

So, if your question is, whether you can (in a reasonable way) always write code without returning instance variables / internal state, i.e. "getters", my answer is no.

Example: here is a small HTTP/REST library I've written. It has a couple "getters" like ContentResponse.getContent(). As @ced pointed out, the domain is to return "content" from an HTTP call and I don't know how that content is supposed to be used, so a getter is appropriate.

But, and this is my point, these exceptions occur far less then people assume they would. Like orders of magnitude less.

It's like if people would only shower once or twice a month and I'm arguing you should shower every day, while you are saying "he can't mean every single day?".

Like in the library above, there are like 3 getters in total or so, which is unlikely to grow, even with new features of the library.

Even in articles like: Data Boundaries are the root cause of Maintenance Problems, I'm pretty consciously and repeatedly saying this only applies to "inside" the application (or library). It's not to say, that library boundaries can be full of getters. Lots of times you can actually find a suitable behavior instead of giving out data.

My point is, that most designs are riddled with internal, data-oriented boundaries, DTOs, Beans, layers, etc. We can discuss the fine points and the gray areas of OOP, but the truth is, we're not even close to those at the moment for most projects.

So now that we found out it's ok to sometimes have getters in the external interface of a library. A more interesting question would be, is it ok to have a Layered Architecture or Clean Architecture on the inside of an application. And if yes, under what circumstances / requirements.