Martin Odersky has some comments about Object Oriented Programming

(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at: lawrence@krubner.com, or follow me on Twitter.

A lot of people have read my essay from October 7th, 2014, “Object Oriented Programming is an expensive disaster which must end“. Many people like the essay, and many people hate the essay. The people who hate the essay often raise the possibility that I am a troll. They also feel that the whole essay should be dismissed based on its mistakes.

I have been meaning to write a second version that fixes all the mistakes of the first. If I had known how popular the post would be, then I would have been more rigorous. The essay is very long, 30,000 words, so it will take me some time to write a second version.

Scala programmers, in particular, have hated this essay because I used a bad example of Scala in the essay. I do not know Scala very well, so I probably should have left that example out. However, that one example is such a tiny part of the essay, that if anyone is willing to dismiss the essay because of that one example, I think it is reasonable to say that they were looking for any possible reason to dismiss the essay.

Russ Paielli posted a link to the article on a mailist for Scala programmers. He wrote:

So the author seems to be unaware that OOP can be done with immutable objects. Does that discredit the entire article? I think so, but apparently not everyone agrees. In fact, there seems to be a lot of outright hostility to OOP out there. The article claims that everything that can be done with OOP can be done in a simpler and better way with pure FP. I’ve seen this claim before.

Is it OOP if you only use immutable objects? As I said in the essay, you can use Java and write in the Functional Style — but if you are writing in the Functional Style, you might want to use a language other than Java, since Java works against you when you try to be Functional.

Scala programmers are proud of the fact that Scala is multi-paradigm. However, if anyone criticizes the OOP features of Scala, the Scala programmers tend to react as if Scala is fundamentally OOP, such that any attack on OOP is also an attack on Scala. What Russ Paielli has written is a good example of this.

Bardur Arantsson followed up in that same thread by writing:

I think in this case the phrase “don’t feed the troll” may apply.

I agree with Arantsson that we should never waste time arguing with someone who is arguing in bad faith. However, I don’t think anyone can read my essay and sincerely believe that I was arguing in bad faith. And if you are talking to someone who is an advancing an argument, and offering supporting evidence, and who makes their argument in good faith, and then you accuse them of being a troll, then that marks you as someone who is frightened of new ideas.

Those of us who have argued against object oriented programming run into the problem that the people defending it feel free to redefine it whenever someone makes a good argument against its worst flaws. Jonathan Rees does an excellent job of summarizing the frustration that we feel:

Because OOP is a moving target, OOP zealots will choose some subset of this menu by whim and then use it to try to convince you that you are a loser.

That is the short version. He wrote that back in 2001, and the situation has only gotten worse. The longer version:

I have heard OO defined to be many different subsets of this list.

Encapsulation – the ability to syntactically hide the implementation of a type. E.g. in C or Pascal you always know whether something is a struct or an array, but in CLU and Java you can hide the difference.

Protection – the inability of the client of a type to detect its implementation. This guarantees that a behavior-preserving change to an implementation will not break its clients, and also makes sure that things like passwords don’t leak out.

Ad hoc polymorphism – functions and data structures with parameters that can take on values of many different types.

Parametric polymorphism – functions and data structures that parameterize over arbitrary values (e.g. list of anything). ML and Lisp both have this. Java doesn’t quite because of its non-Object types.

Everything is an object – all values are objects. True in Smalltalk (?) but not in Java (because of int and friends).

All you can do is send a message (AYCDISAM) = Actors model – there is no direct manipulation of objects, only communication with (or invocation of) them. The presence of fields in Java violates this.

Specification inheritance = subtyping – there are distinct types known to the language with the property that a value of one type is as good as a value of another for the purposes of type correctness. (E.g. Java interface inheritance.)

Implementation inheritance/reuse – having written one pile of code, a similar pile (e.g. a superset) can be generated in a controlled manner, i.e. the code doesn’t have to be copied and edited. A limited and peculiar kind of abstraction. (E.g. Java class inheritance.)

Sum-of-product-of-function pattern – objects are (in effect) restricted to be functions that take as first argument a distinguished method key argument that is drawn from a finite set of simple names.

The defenders of OOP freely re-define the term so that it never means whatever you criticize. Russ Paielli’s remark is an example of that — in his view, OOP is really all about the Functional Style, where everything is immutable. I have to wonder why people have such a deeply emotional loyalty to OOP. After all, since Russ Paielli clearly admits that defaulting to immutability is a wise choice, why won’t he switch his allegiance to those languages that were invented to support that style? Perhaps Jonathan Rees gets at the emotions behind this issue when he writes:

In a pack you want to restrict everyone else’s freedom as much as possible to reduce their ability to interfere with and take advantage of you, and the only way to do that is by either becoming chief (dangerous and unlikely) or by submitting to the same rules that they do. If you submit to rules, you then want the rules to be liberal so that you have a chance of doing most of what you want to do, but not so liberal that others nail you.

In such a pack-programming world, the language is a constitution or set of by-laws, and the interpreter/compiler/QA-team acts in part as a rule checker/enforcer/police force. Co-programmers want to know: If I work with your code, will this help me or hurt me? Correctness is undecidable (and generally unenforceable), so managers go with whatever rule set (static type system, language restrictions, “lint” program, etc.) shows up at the door when the project starts.

Back in 2001, Paul Graham wrote:

There is a kind of mania for object-oriented programming at the moment, but some of the smartest programmers I know are some of the least excited about it.

My own feeling is that object-oriented programming is a useful technique in some cases, but it isn’t something that has to pervade every program you write. You should be able to define new types, but you shouldn’t have to express every program as the definition of new types.

Since 2005, there has been a reaction away from Object Oriented Programming, and Scala is a reflection of that reaction. Whereas, in the late 90s, languages were competing to be known as the most “pure” of all the Object Oriented Programming languages, nowadays the newer languages compete either by calling themselves multi-paradigm (Scala) or by emphasizing their “pure” commitment to non Object Oriented styles (F#, Clojure, etc). No one, in 2015, is trying to promote their favorite language by insisting that it is purest Object Oriented language out there. As I wrote in my essay:

The hype in favor of OOP built up during the 1980s and early 90s, but I would say the zenith of the idea was from 1995 to 2005. After 2005, very slowly, a reaction against OOP developed. This reaction initially showed 3 tendencies:

1.) a movement away from static typing and toward dynamic typing

2.) a movement away from compiled languages and toward script languages

3.) a movement away from heavy-weight frameworks and toward lighter frameworks

And then eventually a 4th tendency appeared:

4.) a movement away from OOP and toward the “functional” paradigm

In response to Russ Paielli, Martin Odersky joins the thread and writes:

Objects done well provide a lightweight module system (in the sense of ML). The requirement for a good module system is something that’s often overlooked when all you do is a simple application, but its lack becomes painfully apparent for large systems and systems that are maintained over time.

You can go the SML route and provide a module system and a functional core language. But then there’s the pressure that you want to generalize your modules to be more flexible, which means you want them to become recursive and first-class. If you do that, you end up with a de-facto object system in addition to your core language of algebraic data types and functions.

Scala’s approach of unifying modules and objects is more parsimonious: The same constructs define the core language and the module language. So Scala is simpler, in the sense that fewer concepts are needed to describe the total feature set.

Everyone, including me, would agree on this:

The requirement for a good module system is something … apparent for large systems and systems that are maintained over time.

The inclusion of “is something that’s often overlooked when all you do is a simple application” is the first whiff of a bit intellectual dishonesty. Did he have to phrase it this way? We could agree that a module system is not needed if you we are just writing a trivial application, but if we are writing an app of any size, the need for some kind of module system is among the most discussed issues in the history of computer science. With the words “something that’s often overlooked” he sets himself up as some kind of hero of computer science. If I wrote “Something that’s often overlooked is that weapons are useful during war” would that make me one of the greatest military historians ever?

You might think I’m being ungenerous by pouncing on this small phrase, but I want to call out the small infractions that normalize the larger infractions.

The phrase “Objects done well” at least concedes that objects are often not done well. We could then ask if they are ever done well, and if there is a definition of “done well” we could all agree to. Otherwise, this is a frustrating example of what I was complaining about when I wrote:

The No True Scotsman fallacy leads to arguments like this:

Person A: “No Scotsman ever steals.”

Person B: “I know of a Scotsman who stole.”

Person A: “No True Scotsman would ever steal.”

Person A believes all Scotsman are brave and honorable, and you can not convince them otherwise, for any counter-example you bring up is of some degraded Untrue Scotsman, which has no bearing on whatever they think of True Scotsman. And this is my experience whenever I argue against Object Oriented Programming (OOP): no matter what evidence I bring up for consideration, it is dismissed as irrelevant. If I complain that Java is verbose, I’m told that True OOP Programmers let the IDE take care of some of the boilerplate, or perhaps I am told that Scala is better. If I complain that Scala involves too much ceremony, I’m told that Ruby lacks ceremony. If I complain about the dangers of monkey-patching in Ruby, I’m told that True OOP Programmers know how to use the meta-programming to their advantage, and if I can’t do it then I am simply incompetent. I should use a language that is more pure, or a language that is more practical, I should use a language that has compile-time static data-type checking, or I should use a language that gives me the freedom of dynamic typing.

Discussions of languages differences would be greatly improved if we could all give up phrases such as “done well” and focus on the overall tendencies that a language promotes. Vague definitions of “done well” invite intellectual dishonesty. You can make anything fit a vague definition, if you are motivated to do so.

Finally, there is this:

But then there’s the pressure that you want to generalize your modules to be more flexible, which means you want them to become recursive and first-class

But where is that pressure coming from, and are objects the answer? Erlang, in particular, seems to offer the alternative: further separation of the modules to the point that they are basically separate apps, each running in their own process, and each sending and receiving those messages that are allowed by their interface.

It seems like Odersky is stretching the definition of objects so wide that we can say all languages secretly want to be Object Oriented (“you end up with a de-facto object system”) and bad languages introduce unneeded complexity by trying to avoid objects (“Scala is simpler”).

There is this whiff of intellectual dishonesty that emanates from certain advocates of Object Oriented Programming, and especially from the Scala community. If we re-define “module” and “object” such that any language with a module system is an Object Oriented language then the phrase “Object Oriented” becomes meaningless, because we would now be including several languages that are famous for rejecting Object Oriented Programming. But if he’s saying that any language that has modules faces pressures to make the modules more flexible because “you want them to become recursive and first-class”, then the “you” in the sentence is actually Martin Odersky, and he is merely re-stating his personal preferences. That is, if you give Martin Odersky a module, he prefers to turn it into an object. And I already knew that. Joe Armstrong (inventor of Erlang) had different preferences, and went in the completely opposite direction. And Joe Armstrong has written a fantastic work describing his reasons for doing so.

Also, this is odd:

“Scala is simpler, in the sense that fewer concepts are needed to describe the total feature set.”

Scala has always been proudly multi-paradigm, so surely “fewer concepts” has never been the goal? I am not saying that “fewer concepts” is good or bad, but if it is your goal, then Scala is a terrible choice for you. There are single paradigm languages that use less concepts than Scala, precisely because they are not multi-paradigm.

A final point about Russ Paielli words. He wrote: “OOP can be done with immutable objects.” If we were discussing soccer, I could imagine saying “My team can do defense”, and I might even get emotional when explaining my team, but I didn’t think we were discussing teams here. We are discussing concepts, and we should try to keep track of ideas that are mutually exclusive. I would think computer programmers would be good at this.

I wish we could discuss these issues honestly. I wish people could be honest with themselves, why they feel the need to defend certain ideas, or certain languages — if they were honest with themselves, then they could be honest with the rest of us. So often developers defend their favorite paradigm, or their favorite language, with what feels like a thin veneer of rational rhetoric that’s meant to disguise the real emotions that motivate them. These tech conversations then become religious wars. These conversations would be a lot more productive if all of us could soberly talk about the real conditions of our work, and how we think specific technologies will shape our personal experiences.

Again, Jonathan Rees summarized what seems to be developers real motivations:

In a pack you want to restrict everyone else’s freedom as much as possible to reduce their ability to interfere with and take advantage of you, and the only way to do that is by either becoming chief (dangerous and unlikely) or by submitting to the same rules that they do. If you submit to rules, you then want the rules to be liberal so that you have a chance of doing most of what you want to do, but not so liberal that others nail you.

We’d all be better off if we could describe our preferences, with our starting point being “I want such and so freedoms for myself, I want such and so limits on my co-workers.” If that is the emotional truth that drives supposedly non-emotional arguments, then let’s start there, as it offers clarity for arguments whose subterranean tectonic forces are often obscure.

Post external references

  1. 1
    http://scala-programming-language.1934581.n4.nabble.com/OOP-is-an-expensive-disaster-which-must-end-td4636898.html
  2. 2
    http://www.paulgraham.com/reesoo.html
  3. 3
    http://www.paulgraham.com/noop.html
  4. 4
    http://www.erlang.org/download/armstrong_thesis_2003.pdf
Source