Thursday, November 27, 2008

Why Bad OO Sucks

Anyone who as read my blog knows that I am an OO advocate, but I was watching Joe Armstrong the other day of Erlang fame and he posed the question: "In which Object should you place a given function? To me the choice seems arbitrary". Now if you've got a solid grounding in OO design principles then the answer to this one is easy. Keep the function near the data. So the object with most of the data is where the function should be. I have posed this very same question at interviews and most of the time supposed experienced OO Java developers are clueless.

The fact that a language designer is asking this question in itself is interesting, and says a lot about how OO has been misrepresented over the years. Joes critism is thoughtful. He outlines why he believes OO sucks in a blog post. He then asks the question, why did OO become so popular? I repeat each of his reasons here:

Why is (Bad) OO so popular?
  • Reason 1 - It was thought to be easy to learn.
  • Reason 2 - It was thought to make code reuse easier.
  • Reason 3 - It was hyped.
  • Reason 4 - It created a new software industry

I agree with all of Joes points.

Reason 1- Bad OO is easy to learn because it requires no learning at all. C with Classes is still C. And a class can be used the same as a struct if you choose. The whole ORM industry is built on using classes as structs :) So a bunch of programmers have transitioned from C to C++ to Java etc without learning almost anything at all.

Reason 2- Code reuse as always been speculation. The languages where object reuse has been achieved are not the popular ones. Take a look at NextStep. They managed to produce a pretty reuseable Financial Framework in the 1990s, but it was all written in Objective-C. The "industry" had decided at the time that C++ should be the OO language of choice and went off and tried to build "Pink", "CommonPoint", "OpenDoc" etc which all failed. Why? Could it be that C++ is a static language and the idea of "live" resuable Objects only works with a dynamic language? Even with dynamic languages reuse is illusive. Why? Well back to the idea of categorisation. No two things in this world are truly identical. So my Banks idea of a Bank Account is different to your Banks. So even with the binding problem solved by using a late bound dynamic language, it doesn't mean I can send my Account Object to your Bank and expect everything to work. Proper OO aficionados know this and for this reason alone do not seek to reuse objects out of context.

Reason 3 - Hyped. No arguments here :)

Reason 4 - OO didn't create an industry. The IT industry created an industry. In fact the father of OO Alan Kay has spent the last twenty years bemoaning what the IT industry has done with his baby. Reasons 3 and 4 go together. The industry hyped OO with promises of reuse etc and then felt obliged to go off and build middleware to deliver on the hype. The astute amongst us noticed pretty early on that hey this stuff is getting pretty complex and heavyweight. The rest merrily jumped on the bandwagon with COM, CORBA, J2EE etc. So as Joe rightly points out the industry created a problem of its own making then went about selling us stuff to solve it.

At this point I should go on to defend good OO. But Joe wasn't speaking about good OO. Good OO doesn't suffer from all these problems and good OO isn't popular. Infact good OO is still in obscurity and suffering from funding problems, something that cannot be said for Bad OO.

No, I have plenty of other posts on this blog that speak to the qualities of good OO. And I am not going to say that good OO is intrinsically better or worst then good FP. I would just say that they are different approaches to modeling, each with its own sweet spot. And as always the thing that really matters is the fleshy blob behind the keyboard :)

12 comments:

Yardena said...

I couldn't agree more!

Paul W. Homer said...

I think the fundamental problem with OO is that as a base building block objects just doesn't match the way the world around us works. The point about mixing data and code being awkward is correct, I think. It's like trying to pack tightly using only the tetris 'S' blocks. You've got an overly limited subset of primitives.

The reason it goes so horribly wrong in practice is that most programmers have an instruction-oriented view of their code, rather than a data-oriented view. OO tried to change this by making data more important, and adding that directly to the language semantics, but still programmers choose to ignore it. Most people think of a program as some instructions that manipulate data, rather than some data that is transformed by instructions. That difference in perspective is huge.

Paul.

Paul said...

Hi Paul,

You makt two arguments:

1. OO provides an "overly limited subset of primitives".

I don't get this. The whole point of OO is to extend your language with new user defined primitives called objects. Infact FP is a subset of OO since a lamda expression can be an Object too. Part od the problem is that when you say OO everyone thinks you Java, and I agree Java is quite limiting, but those limits do not apply to say Smalltalk, or Self or even Newspeak for that matter.

2. "Most programmers have an instruction oriented view of their code"

I whole heartedly agree with this point. Which is why someone learning OO should start out with a pure OO language. Languages like C++ and Java with procedural constructs allow programmers to carry one programming in a procedural style. These hybrid languages have not served us well as learning tools.

If you speak to people who cut their OO teeth on Smalltalk you will find that they have a very strong grasp of objects. For example:

3 < 4 ifTrue: [ Transcript show: '3 is less than 4'].

Here you have no choice other then to think about data (Objects). The value of the expression 3 < 4 is a boolean object which understand the message ifTrue: which will evaluate the block [ ...] which has the side effect of writing ' 3 is greater than 4' to the console.

So we have 5 objects:

literal 3
literal 4
the Block
the Transcript
literal string '3 is greater than 4'

And three messages:

<
ifTrue:
show:

As you can see the instructions (messages) play second fiddle to the data (objects). In Smalltalk you have no choice.

ncloud said...

This is something that frustrates me in every job I get. Even people who claim to have solid OO knowledge design systems and write code that just completely misses the point. I have been reading a bit about Domain Driven Design, and it seems, as a movement, to be shuffling back towards true OO -- now if only people would listen to me when I bring up the subject :-)

Matt said...

You say, "Joe wasn't speaking about good OO" -- but I don't think it was just "bad OO" he had in mind. He finds fault in "the basic ideas involved", like encapsulation and information hiding, saying "Data structure and functions should not be bound together", and that hiding state inside objects is "the worse possible choice" for dealing with state. I don't agree with him, but his objections appear to be quite fundamental.

Paul said...

Hi Matt,

Yes I chose to gloss over Joes misconceptions. I'll come right out and say it. I am by no means qualified to make an informed critique of functional programming. Having done a little Lisp and gone through a tutorial on Haskell doesn't qualify me.

Likewise, Joe openly admits that he doesn't know in which object to place a method. "It all seems arbitrary to me". As far as I understand it Joes background is in FP and I don't believe he has much OO experience. So he is clearly not qualified to speak authoritatively about OOP.

I think Joe has smelt a rat and is speculating about the root cause.

Paul.

murphee said...

You might want to consider Erlang's Actor model. Joe mentions that it's considered more along the lines what Alan Kay thought about when he created Smalltalk. Which is true if you read Alan Kay's HOPL paper on the history of Smalltalk: Carl Hewitt's Actor model was a major influence on Smalltalk. Back then, Smalltalk-72, 'message sends' really were messages, not the more procedure invocations of today. (You even had to "parse" the message arguments, as compared to what's done today with binary/keyword arguments).

If you consider Erlang's programming model, which works with many Processes communicating via messages... well, that just looks like an idealized version of old-style Smalltalk, ie. every 'object' is an active living thing and communicates with others via messages.

Paul said...

Him Murphee,

Yep. The Actor model is consistent with Alan Kays "biological cell" analogy for Objects.

Thanks for pointing this out. I didn't cover everything in my post and I'm sure a lot of my readers aren't aware of this little known fact.

Paul.

fsilber said...

Having specialized in functional programming in grad school, I don't understand the big deal about mixing functions with data. Functional programming has its roots in two ideas, the lambda calculus and LISP. In the lambda calculus everthing is a function (lambda expression) -- even data. In LISP, everything is data -- even a function.

Functional programmers do have an issue with the concept of program state, but OOP was intended to replace imperative languages -- which were no less stateful.

Leaving OO design aside, OOP is nothing more than abstract data types with implementation inheritance. If you have a problem with abstract data types, then let's back up twenty years and talk about Ada and Modula-2. If the problem is with implementation inheritance, then let's focus our discussion on that, and not bring in a bunch of irrelevant issues.

Paul said...

Hi fsilber,

Everyone is so certain that they know what objects are and what they aren't. Yet everyone here has a different idea.

Doesn't that tell you something. perhaps your idea of objects is half baked based on an idea propagated by people who didn't fully appreciate OO?


Alan Kay is on record stating that "I invented the term Object-Oriented, and I can tell you I did not have C++ in mind". So what did Alan mean by this?

Firstly you can have OO without class inheritance. Take a look at Self it doesn't have classes at all.

Data abstraction doesn't cut it either. I've got no clue how I would send a message to a data abstraction. Also explain how I achieve representation independence using just data abstraction?

This is what I mean by Bad OO. Everyone thinks they know, but no one stops to question whether they actually do.

Paul.

dafydd said...

"In which Object should you place a given function? To me the choice seems arbitrary"

Wrong question.

Somebody's thinking in pascal and mapping it back to the oo programming language.

This is better:

"Which object is best positioned to do this? (given what it already knows and what it can already do)"

I don't want to make an OO language easy for people to transliterate procedural code into. If it's easy to learn the OOPL because you've done C but no OO then something is likely to be wrong with your code.

People find Smalltalk hard to read at first. The syntax provokes a serious effort from people to think about how it works. Having a C-like syntax may win converts but they will write the same crap - and I will end up maintaining it(!) I'd rather burn bridges when it comes to syntax. It should look different from a procedural language - because it IS different.

Languages like Java and C++ are easier to learn because people don't need to bother - and it seems that most never do.

Saurabi said...

Yeah that's great since I use a new explorer made it by a friend it's easier to buy viagra online, very faster.
Thanks