Questioning OO
After a decade+ using Java, I find myself questioning the big 3 OO principles (the most over-used interview question ever): inheritance, encapsulation, and polymorphism. Or maybe more precisely I question the typical Java expression of these principles.
Encapsulation sounds great and all but in Java as typically practiced it’s mostly a joke. We create our objects with private (mutable!) data but expose most of it through public getters and setters. We then struggle to properly manage that mutable state in the face of concurrency problems.
Inheritance sounds great but in a single-inheritance language is a very strong coupling. Inheritance creates issues in equality, in patterns like the template method, in just simply modeling many common domains.
Polymorphism sounds great and it actually is pretty great. :) Any Java developer worth his bytecode knows how important the use of interfaces is in writing modular, maintainable code. Interface-oriented programming is the cornerstone of dependency injection and the key to most of the design patterns we use every day. My only complaint about interface-oriented Java is that it typically results in large number of classes and interfaces, thus increasing the surface area of your code base.
As I dig into Clojure more and more I see that it fares pretty well in providing the best of Java OO (polymorphism via multimethods and in the future protocols) without the downsides of encapsulation and inheritance. I wish I knew Smalltalk so I could defend OO better as I suspect the issues above are more due to OO in Java than OO as concept.
Must go find my flame-resistant suit now…. :)

Hi! My name is Alex Miller and I live in St. Louis. I write code for a living and currently work for
I completely agree with all your points. I found similar satisfaction when I moved to python from Java. Specifically ,
Encapsulation : Idiomatic python has all public member attributes. If some getter/setters are required around the member access, such can be transparently introduced by using properties
Inheritance : Python supports multiple inheritance. Moreover it allows introducing mixin capabilities through class decorators as well (some work required).
Polymorphism : Being duck typed all you need is to have a quack() method without having an interface which requires a quack() method to be implemented. Thats the simple essense of polymorphism.
While it is a multi paradigm language, it does support OO quite well. IMO at least two aspects you refer to (inheritance and polymorphism) are quite nicely available in many dynamically typed OO languages. So I would wonder if you are questioning OO or discussing (static/dynamic) typing ?
Cannot agree more about inheritance, encapsulation failure I think is more about the bean default most Java programmers seem to have – immutable objects win here.
I like the Magic Scaling Sprinklies take on Java’s good bits: http://magicscalingsprinkles.wordpress.com/2010/02/08/why-i-love-everything-you-hate-about-java/
Glad that you are questioning OOP. I would say that your criticism of encapsulation does not really make sense. Seems like you are saying “Encapsulation is not a good idea because nobody actually follows the principle.” Maybe that is true, i.e. encapsulation is impractical or too complex, so nobody applies it, but I don’t think that was the point you were getting at.
In my own experience, the most sound OO systems rely heavily on getter/setter-less interfaces, only use “extends” on abstract classes (and that is even rare), and wind up using encapsulation quite a bit because they really have to. You definitely wind up with a lot of code, especially in Java or C-languages.
Good question.
After around ten years of Java/OO, I recently switched to Erlang and thought that I would miss OO like hell.
It appears not.
And I don’t think I was doing OO too bad. I despised accessors as much I could and frowned upon inheritance so much that my forehead is marked forever.
But it appears that OO is just a matter of organizing your code and that it takes the exact same amount of discipline to produce good code without OO than with OO.
Hence, as other as commented, you’re maybe questioning developers’ practices and not OO ;-)
Encapsulation:
I love it, but as you said it is largely not practiced correctly. Additionally, it is not used at a low enough level. Developers are afraid of creating lots of objects, so they don’t want to wrap a value they could represent as an int with an Object to reflect the business rules around the int. They’d rather litter their code with range checks.
Inheritance:
It is evil. Java doesn’t make extension by composition nearly as easy, but it is the better approach. Thankfully, tooling makes this easier.
Polymorphism:
I generally don’t create an interface until I have two separate implementations that require it. (Unless I’m trying to future-proof myself for a library or extensible app.) This cuts down on the repetition. Tooling helps here, as well.
All oop langs melt state and identity (rich hickey dixit) and this the root of the oop itself and its weakness. And forces you to model the world with objects (state+identity+behavior) and it isn always fits the domain of the application. You can have interfaces, “encapsulation” and polymorphism without objects…
@Heath: it’s not all about you :-).
Whether or not to use interfaces should *not* be just an issue of whether *you* have two or more implementations of that interface to deal with. What if your application’s customers want to extend the application in ways you didn’t anticipate? What you are doing with an interface based programming style, especially when you couple it with a DI environment like Guice or Spring, is declaring “here is an extension point of my application, that you are free to leverage, even if I didn’t think about what you are trying to do in the first place.”
The downside of this, in Java, is that interface evolution pretty much sucks. Adding a method breaks all existing implementations (although you can also offer an abstract base class and *encourage* people to “extends AbstractFoo” instead of “implements Foo”) to mitigate the disruption).
But that is actually a low level detail. The key question to ask yourself is this: do *I* know, for an absolute fact, that there will *never* be a user of my application that doesn’t need to specialize the implementation of this particular API? Scripting language devotees will scoff at such a question, because their APIs are always mutable. Indeed, this is where a lot of the power of programming in languages like Ruby and Python comes from — duck typing lives!. But there’s definitely value in considering this question when you are using strongly typed languages, with the ability to define formal interfaces, and leverage your compiler to detect impedance mismatches, like what Java offers.
If you don’t know the answer to that (and, in the case of typical large scale applications, the answer is almost always “NO WAY do I know what my customers will ultimately want do do”), then you are far better off defining interfaces that you *are* willing to support, and then delighting in the serendipity of finding out that people have specialized your software in ways that you had no idea would ever happen.
(Of course, this puts an *extreme* emphasis on good API design, but I digress …)
Java is old and has to be (mostly) retro-compatible, that’s why in my opinion it cannot compete with new programming concepts and languages.
But it is also a good compromise between high level and low level languages, it has the best IDE, and numerous libraries. For me its most important advantage is that it is easy!
I may not be following the thread properly, so apologies if I just misunderstood.
Encapsulation is not the same as immutability. It may be appropriate to discuss here the Open/Closed principle if you want, but saying that “encapsulation in java is a joke” because classes are not immutable by default sounds like pears and oranges to me.
@Nacho: My point was that encapsulation as practiced is not really giving us much encapsulation because we expose all of our state through Java bean style setters anyways. The concurrency implications of mutability are a secondary problem.
My thinking, driven to some degree by Scala ;), is towards using objects for well defined (algebraic?) types and composition (e.g., the Cake Pattern for component composition http://programming-scala.labs.oreilly.com/ch13.html#DependencyInjectionInScala), and using “functional” collections for everything else.
My favorite whipping boy is the “Person” class: ill defined, context dependent, changes from one requirement to the next, etc. I prefer maps for such amorphous creatures.
I now mostly write very functional code for “methods”, too, preferring immutability, recursion, …
So, yes Alex, you’re not the only one rethinking his/her principles ;)
The problem with encapsulation is that almost nobody seems to understand it. Only developers who know that it’s not just about having private fields and public getter/setter pairs get to run into the problems you describe. Everybody else makes a less sophisticated, ball-of-mud kind of mess.
Inheritance, I agree, is fraught with peril. Java’s facilities for controlling inheritance are a bit clunky– if you want a sealed hierarchy, you have to lean on package scope and access control modifiers in ways with which, again, most developers do not seem to be familiar or comfortable. Composition is usually what you actually want, but I know that when I was in school it was taught as a footnote, while inheritance was front and center.
You seem to be finding the same relief from Java’s limitations and bad incentives in Clojure that I’m finding in Scala.
If you *must* program in Java and are frustrated by single inheritance and implementations with overabundance of (brittle) interfaces then I have one word for you: Groovy.
I got the same impression after working with Clojure, Python, etc. for a while. It seems that the Actor model (e.g. like in Scala) better implements the OO ideas than Java.
Encapsulation: I use EVERY day, most of the time in classes with attributes set when the object is constructed and most of them are got calling getX. In summary ABSOLUTELY NECESSARY.
Inheritance: I use EVERY day when two classes are basically the same with something different , then a base class saves me the day. Doing the same with delegation? Well you can, FORCING the “who am I” question with “is part of me” question, why forcing? Ignoring inheritance is like returning to Stone Age of C. If two classes are basically the same they both ARE INEVITABLY COUPLED using delegation or inheritance, you cannot decoupling what is essentially coupled, not ever coupling is bad, in fact reusing is a form of coupling, copy paste is the definitive tool for absolutely decoupling. Try to replace three level of inheritance with (forced) delegation… crazy. Try to rebuild Swing with (forced) delegation… crazy. In summary ABSOLUTELY NECESSARY.
Polymorphism: no criticism, nothing to say. I love it too.
I’ve read your article about Template Method, I think Template Method is unjustly rejected, your example is unfair, ConnectionPool is not essentially related with Connection creation. As you well say you can decouple connection pool management with connection creation, but what if your ConnectionFactory is a base class doing some generic tasks ONLY related with connection creation? A ConnectionFactoryFactory class is the solution? Crazy.
Trying to avoid implementation inheritance is crazy, inheritance is absolutely nice when your class tree has a single responsibility, most of bad uses of inheritance is when inheritance is used to do too much things, the solution is not avoiding inheritance, the solution is to break your inheritance tree in two or more inheritance trees usually coupled with delegation.
“Encapsulation sounds great and all but in Java as typically practiced it’s mostly a joke.”
And what is typically practised is not encapsulation…
In fact, what is typically practised is barely OO!
Global state, methods with side-effects and “feature-envy” is what is typically practised. Should we blame Java for this? Let’s do it.
However, I fail to see how the same coders that use an OO language so inappropriately will be prevented from doing so in any other language.
My advice for anyone who can would be to follow a good design-patterns course like the one by H. Kabutz. Otherwise, read some Bob Martin books.
I agree with previous comments that encapsulation and data-hiding aren’t the same thing, although a well-encapsulated class probably does hide (or at least make immutable) some attributes.
Encapsulation is also about cohesion — a logical binding of attributes (or properties) and behaviors that are best expressed in a single type of entity. I think this is the more important concept that is lost on many OO developers.
We can mostly blame the sorry state of OO practice in Java on JEE. The absolutely broken early versions of JEE (previously J2EE) were so awful and produced so many anti-patterns that are now accepted as standard Java practice, it’s not funny.
I regularly get blank stares when I try to write good OO software with people who’ve only written JEE code with DAOs and stateless session beans and gargantuan spring configuration files. It’s not their fault. They’ve been misled in the worst way.
Burn him!
————
OO is a good thing; but it’s not the only good thing. It is simply because the big languages of the last couple decades have been OO, that OO principles have become generically “good”. As you’ve noticed, there are other, not-so-OO ways of designing systems that are quite nice also.
About encapsulation specifically: the important encapsulation is modularity; modularity is the most important of all software design principles. In OO languages, encapsulation becomes a synonym for low-level modularity.
Questioning OO? Bollucks! OO is a style. Functional is a style. Dixieland is a style. I agree with your observations and I didn’t see anything really flameworthy, other than the title of your blog post. I thought that was a flame because it sounded like questioning chocolate chip vs. pecan praline.
@Mario: I’m looking for a Dixieland language next!
Hej, Alex,
Thanks for the fine article.
And bravo for questioning principles; we should do more of it, if only to sift that which is dogma from that which is fundamental.
I’d like to comment on your use of the term, “Encapsulation,” and point out that, with all due respect, I don’t think you have questioned this principle at all. (Some might also object to the equivalent status that you seem to give to inheritance and polymorphism, as inheritance is merely the mechanism that enables polymorphism, and as such is perhaps not fundamental; have you ever used inheritance without polymorphism?)
In questioning principles, it is wise to state our definitions so that we all begin on the same footing, even if we all don’t all agree on the terms used. In this respect, your definition of encapsulation would seem to be, “Data-hiding;” am I correct in this? (Forgive me if I am wrong in interpreting you.)
I think this is a rather narrow definition in that it fails to deliver the benefits offered by other definitions of encapsulation.
It would be nice if there were an international, standard definition of encapsulation from which we could begin, but for this to be the case would require an international organization for standardization, and this international organization for standardization would have had to have gone to the bother of defining, “Encapsulation,” in a meaningful way.
Well, fortunately, there is an international organization for standardization: it’s called the International Organization for Standardization, and these good people have officially defined encapsulation as being, “The property that the information contained in an object is accessible only through interactions at the interfaces supported by the object.”*
A key ambiguity in this definition is the word, “Information.” This can be taken to mean, “Data,” in which case this definition would be very close to that which you apparently promote.
But this is not necessarily so.
We can also read, “Information,” as, “Data and behaviour,” such that we could discuss how Java encapsulates methods (and not just data) in classes and even how it encapsulates classes in packages.
Indeed, such a reading could then lead us to equate the ISO’s definition of information with that of Parnas.
In 1972, Canadian David Parnas described how software should be designed using the technique of, “Information hiding,”**:
“We propose instead that one begins with a list of difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others.
The point being that if functionality that might change is hidden, then changing this functionality will have a less burdensome impact than would be the case had that functionality been accessible to all other modules.”
Reading the encapsulation definition above, we see that if an object’s information is accessible only via the object’s interfaces, then the object itself must manifest two fundamentally different phenomena: that which is accessible to clients (the interfaces) and that which is not accessible to clients (the contained information). It is trivial – indeed obvious – that the ISO and Parnas definitions can be married by the proposal that the information (being design decisions, both data and behaviour) which is not accessible to clients is information-hidden in the Parnasian sense.
We then come to the root of the matter, and indeed we can answer the most important question that you might ask of this encapsulation principle namely: what is the benefit of encapsulation? If we can’t answer this unambiguously then encapsulation is mere dogma.
But we can answer it.
Encapsulation’s benefit is in minimizing the number of potential software dependencies with the highest probability of modification event propagation. By doing this, the probability that a change to a software artifact will ripple out to other artifacts (thereby increasing the cost of the change) is minimized. Thus encapsulation is about minimizing potential costs.
That’s why we use encapsulation; that’s why it’s a, “Good thing.”
The primary means of implementing this encapsulation is, firstly, to group related methods within classes and to group related classes within packages; and, secondly, to hide both data and methods within classes by declaring them private and to hide classes within packages by declaring them package-private (default accessor).
(Incidentally, if you think encapsulation is just, “Data-encapsulation,” and is most definitely not, “Data- and behaviour-encapsulation,” then by what is the name of the principle by which methods are contained within classes and that their exposure to clients is minimized? Surely you don’t leave your methods public?)
Your accusation that encapsulation, “… in Java as typically practiced [is] mostly a joke,” amounts to the accusation that most people don’t group methods/classes semantically well within their classes/packages, or they don’t use the private method/class accessors enough. With the latter, indeed, I’d have some sympathy: a recent survey*** of Java projects on Sourceforge showed that most projects leave three classes public for every private class they define in a package.
This, however, is a criticism of the practice of the principle, rather than a criticism of the principle itself, and as such, your article left the principle of encapsulation unquestioned.
Which was a shame.
Regards,
Ed.
* “Information technology – Open Distributed Processing,” ISO/IEC 10746, 1998.
** “On the Criteria To Be Used in Decomposing Systems into Modules,” D. L. Parnas, 1972.
*** http://www.edmundkirwan.com/encap/survey1/index.html
While yes, a lot of people mistake ‘encapsulation’ with ‘make your field private-but-not-really-just-add-setters-and-getters’, this is, as the people above me have stated, not to blame on Java alone. It’s a general OOP thing, where someone heard something about not making fields public, but retaining access to a field.
It’s also about time – I’ve only recently actually tried to not have Eclipse just generate getters / setters for all fields, and add methods like ‘hasThisProperty()’ instead of ‘getProperty() != null’. The getter / setter methodology is simply easier to implement, especially for beginning programmers that find it difficult to provide methods for simple operations like an ‘isset’ check and the like (and somehow I fear that I’ll get burned for even suggesting an isset method)
And of course, it’s about teaching materials too. Books that put the get/set idiom in print, websites that show it, and I’m sure even the official Java documentation offers it as well.
Inheritance, taking DI and unit testing and taking the idiom ‘Everything Should Be An Interface’ can, yes, result in large quantities of files in your program and, if you’re not careful or skilled, in lasagna code (where there’s far too much abstraction layers to make sense of anything). However, if applied properly, and applied for the right reasons, I don’t think this should be shot down as quickly. Sure, languages like Clojure might do this faster and more concise (no experience with it at all, by the way, a failing on my part), but is this as easy to use in a large application with multiple developers? Is it a tight contract like interfaces can be? Does it specify what can and cannot go in there based on type and other properties (non-null, which I hope will be added to Java 7, and which I hope we’ll be able to use soon)?
I see Java as a very ‘official’ language, where you can be very explicit about things. Clojure, or what I’ve seen of it, looks ore like small bits of code that Do Something, and I’m starting to doubt it’d be suitable for larger projects (>100.000 loc, if you count in such metrics in Java and translate it to an equivalent in Clojure)
* note: Most of this comment is based on assumption and not experience. Bear with the author.
@Ed Kirwan:
“With the latter, indeed, I’d have some sympathy: a recent survey*** of Java projects on Sourceforge showed that most projects leave three classes public for every private class they define in a package.”
Maybe package-private classes aren’t used a lot because they’re too restrictive. I try to use them as often as possible, but I often find myself wishing it were possible to make a class visible to its package and all subpackages.
@Moandji Ezana
I believe this is a problem as any real-use component/library/etc. will comprise of multiple packages since many times packages are used to organise layers/sub-components/etc.
What we need is a higher level concept to packages. This is most likely “module”; coming with JSR294.
My understanding is that with this JSR a new access modifier will be added in the language – module.
http://openjdk.java.net/projects/jigsaw/doc/language.html
@Tasos Zervos
Yeah, I hope modules turn out to be as useful as everyone is hoping they’ll be.
I read this post and I found this quote from Joe Armstrong ( creator of Erlang ).. it struck a chord with me, so I thought I would share it…..
“I think the lack of reusability comes in object-oriented languages, not in functional languages. Because the problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.”
Any one paradigm will have its limitations. Languages that can support multiple paradigms, even somewhat loosely, seem to be a better solution. Alternatively, environments that support multiple languages of different paradigms being easily combined are another solution.