
Did OOP do this to us? - 10ren
http://sob.apotheon.org/?p=935
======
sdp
_"OOP didn't do this to us; we did it to ourselves. OOP just held our hats."_

I support the article's claim that programmers are responsible for spaghetti
code, but I disagree that OOP in general is responsible for facilitating this
behavior. Compare Java's OO to smalltalk's OO.

On the one hand, you have "a halfway point between C++ and Lisp" which
inherits a bytecode on virtual machine implementation from lisp and most
everything else from C++. [[http://people.csail.mit.edu/gregs/ll1-discuss-
archive-html/m...](http://people.csail.mit.edu/gregs/ll1-discuss-archive-
html/msg04045.html)]

On the other hand you have an open source ecosystem built on top of a VM,
where all code is available for modification and extension by the user.
[<http://www.squeak.org/About/>]

Java programs are notorious for being resource hogs and unstable, and
smalltalk programs are notorious for the opposite.

This dichotomy suggests OOP is not the evil villain it's made out to be.
Rather, I would suggest that the average quality of code produced in a
particular language is proportional to how easy it is to read other people's
code in that language.

Java makes it very easy to hide your code. Often while working on a large Java
project at school, each of my team mates and I divide the project into classes
and we are each responsible for a particular set of classes. We don't ever
need to look at one another's code to complete the assignment, and thus bugs
can creep in.

On the other hand, I work on a mid-size PHP code base which is my
responsibility alone. Thankfully, one of my co-workers is an excellent PHP
coder. Whenever I make revisions to the code, I ask him to review my code. The
mere knowledge that someone else is going to read the code I write is enough
impetus for me to write better code in the hope that someday he won't find
something I'll need to revise.

My experience is not an isolated case, as can be seen in this article by Jeff
Atwood who quotes Code Complete:
[<http://www.codinghorror.com/blog/archives/000495.html>].

This is supported by the generally higher quality of code in very shared
languages like C, Smalltalk and Python, than in seldom shared languages like
Java, C++ and Cobol.

Clearly, C has a high potential for code hiding, but a community of code
sharing (Unix) was built around the language to address this issue.

~~~
michaelneale
>Java programs are notorious for being resource hogs and unstable, and
smalltalk programs are notorious for the opposite.

I haven't experienced a smalltalk app that couldn't be described similarly -
but maybe things are improved in recent times, I should look again.

~~~
sdp
My experience with the OS/GUI built on top of the Squeak VM has been very
positive.

------
mechanical_fish
I'm no expert on enterprise software, but this tallies with my casual
observations.

Note that Java didn't _make_ enterprise software into a bloated, confusing
architectural spaghetti. It just found its niche there. Remember that Java was
originally intended for writing embedded software for set-top boxes; then it
got repurposed for writing "write once, run anywhere" desktop applets. It is
only because the language was a nigh-complete failure in those niches that it
became primarily known as a language for server-side enterprise software,
which has influenced its development ever since.

So it might be that the enterprise development "pattern", memorably
characterized by PG as "maintainable spaghetti", did this to (Java's) OOP, not
the other way around. But I would suggest that it's a little of both: Java and
the "enterprise pattern" are _coevolved_ , like the chicken and its egg. At
this point it's hard to sort out which came first.

UPDATE: I should point out that the author says more or less the same thing:

 _OOP didn't do this to us; we did it to ourselves. OOP just held our hats._

His title is a rhetorical question, so the fact that I think it's subtly
misleading is actually a sign that it's doing its job. ;)

~~~
russell
You make a good point. Open (loosely used) enterprise software leads to
committees and committees lead to kitchen sink specifications. CORBA, from a
previous generation, had exactly that kind of bloat, W3C specifications
likewise. The Java libraries show that in spectacular fashion. Maybe Sun
thinks we need umpteen hash table implementations, but I think we would be
better off with one well done.

Frameworks done by committee are even worse. God save us from W3C and the
Apache Foundation.

Counterpoint: software from dictators: Python and Django.

~~~
eru
How does Haskell's collective approach to design / standardization stand here?

------
timr
For those who will vote this up without bothering to read past the title: the
conclusion is that no, OOP is not responsible for bad programming. Bad
programmers are responsible for bad programming.

News at 11.

~~~
joe_the_user
OOP has had several phases. The first phase conflated encapsulation into
objects with generic reuse. It also advocated complex object diagrams, deep
inheritance trees and a variety of over-elaborate approaches.

The second phase was more closely related to patterns and agile methologies.
Here, the illusion of OOP creating generic reuse was abandoned, the idea of
"containment over inheritance" was broached, and the paradigm became closer to
"the right tool for the job".

I am actually amazed that methodologies were able to improve but I can't argue
with what I've seen.

------
nihilocrat
I just think it's the case where OOP does not implicitly guarantee the
modularity and good architecture of applications, it simply provides a model
where for many problem domains and with proper code discipline, it will.
Nature always builds a better idiot.

Most importantly, I think it might be some sort of "it's so expensive, it's
GOT to work" effect. The complexity of OOP patterns can be pretty ridiculous,
so perhaps people dilligently code away using them because they feel like
there's nothing better, or they feel like the complexity has to be good for
something.

~~~
twoz
_"it's so expensive, it's GOT to work"_

Exactly.

 _“Simplicity is hard to build, easy to use, and hard to charge for.
Complexity is easy to build, hard to use, and easy to charge for.”_

~~~
apotheon
Where'd you get that second quote? It seems familiar.

~~~
twoz
As seen on Twitter by Chris Sacca:

<http://news.ycombinator.com/item?id=248322>

------
moe
Reminds me of that old Yegge quote:

Java is like a variant of the game of Tetris in which none of the pieces can
fill gaps created by the other pieces, so all you can do is pile them up
endlessly.

\-- Steve Yegge (2007, Codes Worst Enemy)

~~~
russell
No. The long answer is that Java did it to us. Like jacquesm below, I have
inherited a large Java enterprise project, 400,000 lines of Java, XML,
JavaScript, HTML, and Flex. And no comments, JavaDoc, or design documentation.
All of this seems to have been written by one person with smaller
contributions by a couple of others. There seems to be lots of copy and paste
and IDE generated code. The system was designed to be modular with plugin
components.

The first culprit is Java itself. The language is missing critical builtin
data structures, ArrayList and Hashmap with corresponding literals. If they
had been part of the language and not just libraries, Java might have taken a
completely different direction. Throw in lack of overloadable operators, first
class functions, and descent introspection and you get a language that in not
very expressive.

Lack of key fundamental data structures, leads to the OOP bandwagon.
Interfaces and inheritance are good tools but they should be used in
moderation. In my project there is the pattern of BaseInterface, BaseClass,
MoreCompleteInterface, MoreCompleteClass, ModuleLevelInterface, and
ModuleLevelClass all to implement a DAO with nothingg but getters and setters.
In one case this adds up to more than 2000 lines of code that does nothing
that could not have bee done with a hash. Just to make sure that the code is
completely non-understandable most serious classes have something like this

BaseInterface dataSource;

along with a setter that is filled in by Spring at runtime. I cant even
explore the class structure. Contrast this with Python, where it would be a
handful of lines of code, maybe 100 or 200 times fewer.

To get around the problems inherent in the language, Sun came up with beans
and the Java community went charging off into complexity. And throw in XML
configuration just to create an impedance barrier. Since this was all new
territory, the result was an explosion of frameworks.

So now I have a stack that includes JBoss, Spring, Hibernate, MySQL, 200k of
JS libraries (some of which I never heard of before), Flex, Granite, and more
open source Java libraries than I can shake a stick at. I suspect there are
many cases of a library being added for a single feature. Java OK, JS not so
OK because of download bloat. Maybe Java is not OK either because I have to
deal with what broke when I upgrades to a new version.

I particularly dislike the addition of Hibernate because it separates the
programmer from the understanding of the database. In my case the database
itself was generated from the the .hbm.xml files. The database was created
from a Java-centric point of view as a network of classes. As a consequence
Hibernate created hundreds of tables. One query to fill in a simple list in
the browser created an SQL query with 10 joins. I'm surprised the db didn't
roll over dead.

At least I'm being paid well.

~~~
sdp
How does a lack of "critical built-in data structures" (as opposted to
libraries) lead to poor design?

C has a ridiculously small set of built-in data structures, but the unix core
tools written in C are very elegantly designed.

~~~
frig
Eh, don't read more into an argument than is really called for.

The crux of the above argument is usually something like:

In most nontrivial programs you'll wind up with a lot of "sophisticated" code
that performs some task but has a ton of parameters and behaviors it'd be at
least theoretically useful to be able to tune or override at some specific
point-of-use of said code.

Sometimes the right decision is to just hard-code in all the non-essential
parameters to sensible defaults, and do only what you need; in places where
this approach is warranted ("keep it simple, and only do what you need to"),
Java is as annoying to use as ever but doesn't do much to shoot you in the
foot beyond being more verbose than it needs to be.

It's also sometimes the case that the right decision is to make the code as
fully-articulated-as-possible: as many parameters as possible are tunable, and
as many behaviors as possible can be overridden. We'll call this the
"complicated" scenario.

In the "complicated" scenario, you have at least the following choices for
architecture:

\- approach 1: a tower of interfaces and base classes; each interface+base
class combination augments or extends some of the behavior or adds or removes
points-of-articulation from the layer beneath it. Once you've built the tower,
whenever you get to a point where you need to call on this functionality you
pick the appropriate item from the tower, subclass+augment its behavior
further (if necessary), and go to town.

\- approach 2: similar to 1, but make heavy use of reflection (at least at
certain points) to try and achieve some level of genericity (in the core
methods and algorithms) and to make the implementation less dependent (at time
of coding) on the specifics of any particular interface implementation.

\- approach 3: have methods that're like void
openConnection(IConnectionSpecification connectionSpecification,
Map<String,Object> options), and then be smart about how you extract options
from the options Map.

approach 1 and approach 2 have their problems but fit well into the tools Java
gives you. Approach 1 is more suited for writing code that other people will
use (ie, call into), whereas approach 2 is more suited for writing code that
other people's code will be used in (ie, called) (yes, that's a bit vague, but
it's good enough for today).

Approach 3 is common in the scripting languages, because it allows for a lot
of ad-hoc extension / parameter setting without excessively cluttering the
interface.

Approach 3 isn't impossible in Java, but the lack of literal syntax for eg
maps and lists makes it unwieldy. If it were possible to write something like:

\- ConnectionBroker.openConnection(cSpec,
{"port":80,"username":"username","password":"password"});

you'd see a lot more use of Approach 3 in Java. As-is, you'd have to
explicitly construct a Map of the right type, then one-item-and-line-at-a-time
populate it with keys and values, and so on, at which point (especially if
used often and in a big project) you're better off coding up an
IConnnectionOptions interface, etc., and going from there.

So it's less: lack of data structures == bad design.

It's more: lack of literal syntax for the basic data structures means that
it's a royal pain to do certain ad-hoc friendly tasks in an ad-hoc way.
Assuming laziness (always a good assumption), given an idiomatic way to handle
cases with lots of potential parameters most programmers would handle things
the ad-hoc way, and save the "over-engineered" tower-of-interfaces for the
situations which are actually necessary (eg: real-honest-enterprisey-
software).

~~~
russell
Excellent exposition of what I was trying to say.

The overarching concept is the ""expressiveness" of a language. Concept is
"How easily can I express my goal in the language. A crude measure of the
relative expressiveness of two languages is the ratio of the number of tokens
in the respective implementations of a program. I remember reading a study a
decade ago that ranked C at 1, Java at 2, Python at 5 (roughly). Having hashes
and their literals as part of the language makes it more expressive than one
where hash is in a library. Look at JavaScript where the literals for arrays
are used as a serialization protocol.

Expressiveness goes beyond just literals. In python functions are first class
objects, so there is no need for the thunk/functor/inner class kludge that you
have in Java. Or look at list comprehensions which are way more powerful than
for each.

The expressiveness shapes how programs are coded. Programmers will use a
concise, powerful idiom because it saves time and thinking and the program is
shorter. There is a corresponding obligation on the language developer to make
sure the expressive idiom is almost always the best way to go.

~~~
sdp
The "crude measure" that you cite which "ranks C at 1, Java at 2, Python at 5
(roughly)" shows that on average, every line of code in Python is worth 5
lines of C. Let assume that this is true.

Naturally, this seems to imply that more powerful languages require less code
to perform the same task. Python provides a good example of this, but it is
not always true.

C is not a very expressive language. It is often cited as a portable assembly.
Yet, decades of unix/GNU utilities show that powerful programs can be written
in small amounts of C, which are combined to build elegant and decoupled
systems.

Java is more expressive line by line, but its implementation of OOP requires
so much boilerplate that it requires no less code than C to represent the same
simple design as the C equivalent. Additionally, because each line of Java
represents 2 lines of C, the resulting programs are far less efficient.

It is important to consider why this true. Java attempts to abstract many of
the details of the underlying C implementation, allowing it to be much more
expressive. This abstraction allows the higher level programmer to think about
business logic rather than pointer arithmetic.

However, these abstractions constrain the programmer's ability to write code
that the language designer hadn't considered.

Of course, you might consider these to be edge cases and that is a fair point.
However, crippling the outliers pushes your userbase towards mediocrity.

As pg stated: _"when you damp oscillations, you lose the high points as well
as the low."_

~~~
cubicle67
So we need a high pass filter for languages?

------
david927
No, ambition and sloth did this to us: Ambition in the scope of the systems we
build, sloth in our willingness to give in to whatever gets the job done.

As Alan Kay said, "The revolution hasn't happened yet." He knows that OOP
isn't the final answer (although I think we're all thankful for its
existence). He is one of a small group, made up of mainly self-funded geniuses
and eccentrics, who are working in this space. Everyone else gave up. We had
PARC in the 70's and really nothing else since; we're still coasting on what
they accomplished there.

Now that we know how important this is, why can't we fund a PARC again? Why
can't we build a place where we throw it all out and start over? I know of a
few places doing this now, including Viewpoint Research, but we need more.

------
dkarl
Funny how people are so eager to attribute bad design to the design philosophy
it attempted to follow. This guy at least acknowledges that as a trap, but he
doesn't convince me that he isn't falling into it. Furthermore, if you read
his other post that he links to, he pretty much admits that the things he
blames on OOP are due to incompetent use of OOP:

"The thing that wasn't equal was the tendency of humans to fill a new
development technique's capacity for scalability as long as that technique is
used. As OOP provided greater ability to write ever-larger programs, humans
wrote ever-larger programs — even when they didn't need to do so (and probably
shouldn't have done so)."

~~~
apotheon
You did a very good job of paraphrasing much of what I said. I wonder why you
phrased it as though you disagreed with me.

------
jerf
I've read tons on the pros and cons of OO, done quite a lot of both OO and
non-OO programming, and witnessed many other people try. My conclusion after
all of this is that the debate on OO is almost entirely obscured by noise,
because only 10-20% of developers are capable of using it even remotely
correctly in practice. Many of the people yelling about how horrible it is are
not in that 10-20%, either, and nor are many of the people singing (or, at
least, "repeating") its praises.

It may be sold as a technique that the masses can use, but this is
demonstrably not true, if you examine the code the masses are producing.

~~~
gruseom
Yeah, but as Tim Lister once said (about something else): if everybody gets it
wrong, there's something wrong with _it_.

~~~
jerf
I tend to agree. But it should be pointed out your observation extends to
programming and architecture in general, and OO is just a special case of
that. Most people are pretty bad at designing anything much past about ten
thousand lines and almost everybody above that scope ends up producing
"relatively maintainable spaghetti code", regardless of the language paradigm.

I am also sympathetic to the idea that we shouldn't have architects as a
separate, distinct position, but some way of recognizing your good designers
and architects seems necessary, because you don't really want just anybody
doing it.

~~~
dhimes
_I tend to agree_ You shouldn't, because the original premise is wrong. You
can ask most people very intuitive questions about physics (such as, if you
are walking along and drop a book, where will the book land?) and they will
get it wrong. They are wrong, not the physics.

I agree strongly with your original premise: most don't understand how to use
it properly. I recommend Allen Holub for learning.

~~~
jerf
That's a good argument for science, but a putative _engineering_ discipline
must be something that actual, real humans can perform, or we are forced to
admit that the standards should be raised and too many people are currently
trying to do the engineering.

That's why I point out that it applies to all design philosophies I encounter.
I hate to be elitist as a general principle, but I regretfully must come to
the conclusion there's a lot of programmers programming who really shouldn't
be, based on the evidence.

~~~
dhimes
It may also simply be a communication problem. Here's another example, that
I'm more familiar with. In engineering physics textbooks, most treatments of
AC circuits are very confusing for the student. At that stage of their
careers, we use sin and cos as opposed to a more complex-exponential
treatment.

Now, the textbooks all tend to make the same basic treatment. When I was a
prof, since I am a "challenged" reader, rather than try to wade through the
mess in the book I set apart my own derivation. When I was finished, I
naturally had to tie it back into what the textbook was saying so that the
students had something to hang onto. But when I went to make the link, what I
found actually startled me.

In their derivations, all of the authors made the same phase-shift of the
source signals _and never mentioned it_. I couldn't believe it, and tried to
figure out where my mistake was. But I didn't make a mistake.

In a section of the book that didn't really figure in to the future of the
students' education--could be easily skipped, in fact, because anybody that
needed it would do it over "correctly" anyway-- everybody just sort of did
what everybody else did.

Perhaps that's what is going on in OOP. I'm not trained as a programmer--I
just pick up what I can. So I'm sure that most of my code is laughable, and I
do sometimes paint myself into a corner. But I find that I am sometimes
surprised by how easy it is to make big changes if I've encapsulated things.
Just my personal experience.

------
jacquesm
I've just 'inherited' a fairly large java project, and while I doubt that java
is the cause of this kind of problem it definitely makes it very easy to make
these mistakes.

Over enforcing the oop concept is a fantastic way of losing track of what is
going on with your code, and it pretty much guarantees inefficiency, because
'abstraction' is just another way of saying "I don't want to know". What you
don't know you can't analyze and what you can't analyze might very well be the
cause of your problem.

Good programmer (tm) can write excellent code in Java, because like any other
tool it will respond to its handler. If you are just using classes to pile
layer upon layer of unwanted abstractions on top of each other because you
fail to grasp your problem properly then you have nobody to blame but
yourself.

Again, in some languages this kind of behaviour is actively encouraged and in
some it is discouraged, I suspect that java is one of the former.

~~~
ricky_clarkson
Java makes excellent code unreadable.

~~~
russell
... and makes it possible to hide some pretty bad code/design among the
abstractions.

~~~
jeffcoat
Well, yes: arguably, that very fact is one of the major wins you get from good
abstractions.

------
azgolfer
OOP is an excellent tool when it is used to support separation of concerns.
I'm actually working on a system where they lumped all the functions together,
didn't try to separate them by obvious domain entities. This is inconvenient,
but it is not nearly as bad as a poorly designed OOP framework. The problem
that I see with the frameworks is not enough people ask the question "what
does it really buy me ?". For instance relational databases give a huge
benefit in ACID transactions, a query language that gives correct results, you
can dynamically update tables without breaking things, dynamically join tables
to give new kinds of results, etc.. So paying the price to use SQL to acess
your data is not bad, because you get so much back. But what exaclty are you
getting back from using a framework like Hibernate in between you and the
database ? And where is the proof that ORM is even a good idea ? There seems
to be an idea - if it is OO it is good, and if a lot of people are using it it
must be good. I think these two assumptions are the real problem.

------
voidpointer
In my opinion, a main reason for the situation described by the author is lack
of architectural governance in large projects. The most senior programmer
often is assigned the role of "the architect", even if he is more of a type
that likes to obsess over details rather than the big picture. Such types are
prone to dismiss the importance of conceptual integrity throughout a complex
project which ultimately leads to the pile of unsustainable mess that many
enterprise-class applications have become. Brooks laid out the importance of
conceptual integrity pretty well in in the mythical man month. It is often not
taken serious enough today.

------
msluyter
I'm curious what the alternative is, if any?

~~~
apotheon
Use OOP correctly.

Don't turn OOP into the point of your programming style on any project.

Don't use it at all when it's not appropriate.

When you don't use OOP, make sure you're using the right thing for the problem
domain at hand.

When you use something programming paradigm other than OOP, make sure you use
_that_ correctly, too.

~~~
apotheon
I probably should have said "Avoid Java" in there somewhere, too.

------
gjm11
No.

And that was this week's edition of Simple Answers To Simple Questions.

