
My brain can't handle OOP anymore - Swizec
http://swizec.com/blog/my-brain-cant-handle-oop-anymore/swizec/4320
======
marcusf
I have to say, having stared in to the abyss of large Haskell code bases,
they're not necessarily easier to read than a large Java code base.

Reading bad functional code can be just as painful as bad OO code -- trying to
untangle a mess of fold's that an overzealous developer who just learned of
catamorphisms wrote can be painful. Even more so if that young developer is
you, five months ago.

Sure, the language doesn't impose as much discipline in Python/Java/… as in
Haskell(+), so it might require more of you as a developer to write clear,
readable code (note: not saying that it requires more of you as a developer in
general, just that it's easier to fall in to lazy anti-patterns). But if you
work in a decent code base most of the pitfalls in the post are basically
straw men. A well designed OO system will generally not be riddled with
singletons and arbitrarily mutable state.

(+) I'm using Haskell here cause that's the only purely functional language I
have any experience with. Substitute as you please.

~~~
batista
> _I have to say, having stared in to the abyss of large Haskell code bases,
> they're not necessarily easier to read than a large Java code base._

Actually a Haskell oneliner can be more challenging that a large Java code
base.

~~~
EvilTerran
And a single Java class can be more challenging than a large Haskell code
base. So what?

~~~
batista
So the first tends to happen far more often than the second.

If anything, Java code is boring and boilerplate like, not difficult to
comprehend.

Haskell code on the other hand, not so.

~~~
EvilTerran
I think we're arguing over subjectivities here -- comprehensibility is
entirely dependent on the people involved as much as the language in question.
If you're better at Java than Haskell, you'll find it easier to follow, and
vice-versa; I know people in each category. And you can write clearly or
obfuscate in either language; I've seen all the combinations.

Personally, I tend to find Haskell easier to follow. I suspect that's mostly
because I've used a lot more Haskell than Java of late, but it'll also be a
matter of personal taste. As you say, Java can be very boilerplate-heavy --
some may find the redundancy makes it easier to follow, as it can remind you
what's what "as you go"; others may feel like they're scrolling up and down
hunting for meaningful code, and find all that boilerplate a distracting waste
of space.

I will admit that, on average, I'll have to spend a bit longer looking at a
line of Haskell than a line of Java before I know exactly what it does -- but
then again, you rarely need anywhere near as many lines of Haskell as Java to
solve the same problem, so it feels like a net gain to me.

~~~
batista
> _I think we're arguing over subjectivities here -- comprehensibility is
> entirely dependent on the people involved as much as the language in
> question. If you're better at Java than Haskell, you'll find it easier to
> follow, and vice-versa; I know people in each category._

I maybe arguing over subjectivities, but subjectivities turn into
objectivities with the tool of statistics.

And I think that in general (statistically), people find Haskell more
difficult than Java.

------
DanielBMarkham
Yeah I think you missed it. "Answering this simple question requires knowing
everything. The whole execution history of foo. The whole codebase. You name
it, you have to keep it in your head."

Here's the thing about OOADP (Note I didn't just use OOP): it gives you a
simple methodology to solve problems and know where to put stuff. You don't
know _everything_ , because the assumption is that the codebase is going too
big to know everything. But what you _do_ know is where things go; an
organization of nouns. Good large projects have a design theme that's easy to
understand and gives you the mental tools to reason about _which pieces_ need
your attention at any one time. OOP is all about working on little pieces at a
time and not worrying about knowing everything.

It has a lot of problems, but so does every paradigm. I've become a huge
functional programming fan over the last couple of years, but I can tell you
very frankly that nothing beats OOAD. Nothing. It is a gift from the gods. It
allows you to take any problem and make it trivial. Large amounts of wiring
will be required.

The thing here is that as you start generalizing OOP, you being making this
bastard thing that is part OOP and part FP. Or your codebase runs off the
rails and becomes a hodgepodge of junk. Or you enter into the "Kingdom of
Nouns". The ways to screw up are legion.

Dependency issues are also a freaking nightmare in OOP. That's why OOP and
some sort of TDD go hand-in-hand.

I'm mostly with the author, but I don't think he understands the full extent
of what he's talking about. OOP (and TDD) is a great tool for large, complex,
shared codebases. Even though I'm a huge fan of FP, I remain very skeptical
that it can scale well to 100+ developer efforts. I think to truly criticize
something like this, you should know both how it's awesome and how it sucks,
not just how it sucks.

~~~
dustingetz
i read your post twice because its the top comment from my view, and while I
see you wrote a lot, I don't think you actually said anything. are you
interested in clarifying?

~~~
DanielBMarkham
Sorry about that.

Here's the underlying philosophy of OOP not covered by the original article
[philosophy described]. Here are some strengths not covered by the original
article [salient points covered].

Author managed to share his frustration with the structural details of the
paradigm without conveying that he understood the bigger picture of its actual
effective use.

That's a recap. Work any better for you now? Or did you not understand my
description of how the philosophy works or what the strengths were?

~~~
spacemanaki
dustingetz's criticism was a bit harsh, but I kind of agree with him. You
aren't concretely illuminating how those qualities of OOP (or OOADP) are
advantages or are unique to OO. I would really value more clarification from
you on this, given your prolific HN presence and experience. I genuinely want
to learn more about this (see my other comment in this thread), but I've
struggled to find really good, motivating examples in the past.

> nothing beats OOAD. Nothing. It is a gift from the gods. It allows you to
> take any problem and make it trivial.

I'm supremely skeptical of claims like these. I could say that same thing
about... anything. But that's just not enough.

> Or your codebase runs off the rails and becomes a hodgepodge of junk. Or you
> enter into the "Kingdom of Nouns". The ways to screw up are legion.

So how do you avoid this? How can I develop an intuition about good OO design?

You talk about TDD a bit, but you can do TDD with functional programming too,
and in many ways it's easier (less need for mock objects and dependency
injection, which are as good an example of _incidental complexity_ as I can
think of).

> I think to truly criticize something like this, you should know both how
> it's awesome and how it sucks, not just how it sucks.

Yes! Please, help me learn how awesome OOP can be, and get to a place where I
can criticize OOP more brutally. ;) Seriously though, what open source code or
books would you recommend? I looked here:

[http://hn-books.com/#BC=0&EC=0&FC=0&Q0=11&QC...](http://hn-
books.com/#BC=0&EC=0&FC=0&Q0=11&QC=1)

... but it wasn't clear to me which of these books would be best. Many of them
are a bit too specific.

The functional programming proponents who have convinced me most are Clojure
people. Rich Hickey's simplicity talk, his talks and mini-essays on state and
time, Stuart Halloway's similar talk on simplicity, the idea of values over
identities, dealing with basic data structures (maps, vectors, sets) over
burying data in classes and domain specific APIs, separating out OO features
to get "OO a la carte" ... it's very compelling stuff, and most of it is about
striving for _simplicity_ and tearing out unnecessary complexity. That's where
I'm coming from in my skepticism of OOP, because most of it seems to make
things more complex than they need to be, with not a lot of gain.

On the other hand, I'm pretty green, so I know that much of this could just be
naive fantasy, since I've never had to deal with massive codebases being
hacked on by 100+ programmers, neither in FP or OOP languages/styles.

~~~
DanielBMarkham
So whenever I post on OOADP, seems like everybody gets in a bit of a snit with
me :) (not you, just a small minority of the community. Perhaps these are
dangerous political waters!) But I'll explain a bit more. Please remember,
though, that this is long-format material. I have serious reservations about
being able to explain myself or convince anyone of anything in an HN thread.
But I can certainly share my perspective.

Like I said, I'm becoming a huge fan of FP -- to the point I'm really not
interested in doing a lot of OOP in the future, and I did OOP for many, many
years. But that's because I work with small teams mostly.

OOP is all about the organization of the ontology of the problem domain. It's
about gaining a common understanding of a general organizational philosophy
that then can be scaled and coded. In OOAD you start with simple conversations
and slowly created complicated structure where everything has a place. It's
this process of being able to take any problem and create a complicated place
for everything that is both OOP's strength and weakness.

I started with the Tao of Objects <http://amzn.to/KHE5TK> and the Coad Yourdon
books <http://amzn.to/IS9fqj> and <http://amzn.to/IS9oKh>. I still like these
because they focus more on how to mentally approach OOAD instead of the
details of coding. People get lost in the details here instead of learning the
key skill: _how to think about problems_. (which is useful no matter which
type of language you use)

The best way to describe OOAD is "applied philosophy". That is, you are taking
a world known only to the customer and translating it into machine code. On
one hand we have the slipperiness of language and the fuzziness of human
thought. On the other hand we have hard science and boolean logic. OOAD gives
you a game plan for making that journey in an easy-to-use manner. FP is not
like that. FP is more like building a compiler for whatever the problem is.
Same result, but the thinking process is completely different. OO is concerned
with top-down. FP makes little blocks and then fits them together into bigger
units. In OOP you might spend a lot of time on structure without ever writing
any code that does anything at all. But when you _do_ write something, it's
already broken down into tiny digestible pieces. In FP I always feel like I'm
carrying the linker around in my head. :)

In some problems, it's more important to gain immediate functionality than it
is to worry about scaling your code or development team. Startups are mostly
like this, and FP and startups go very well together. In some problems,
however, it's more important to have clear areas of responsibility and an
overall plan for life, the universe, and everything. Large government or
corporate projects are like this. The organization of the code units into
something mirroring the domain model allows planning at a much larger scale.

As I get older I realize that I was a bit of an architecture astronaut in my
younger years -- always creating a structure much more complex than was
actually needed. But I also note that these projects usually went off without
a hitch. We were able to hire "normal" programmers and we were able to hand
the code off to "normal" maintenance programmers when we were done. OOP, to me
at least, is much more about the people part of programming than it is the
technical part. FP guys are always making these technical arguments about
their language, and they miss the point entirely: the problem that OOADP
solves isn't a technical one, it's an organizational one. Where does stuff go?

So if I had a large project to do, I'd start with OOAD and then when I got
into later design think seriously about which parts would deploy better FP or
OOP. The browser code is going to need some kind of namespace, which is
usually done with objects in Javascript. Talking from the browser to the
server looks entirely functional to me. The back-end gets a bit tricky.
There's nothing like a normalized database model for data analysis, but
creating a business and database tier looks counterproductive in some cases.
It'd depend a lot on the circumstances.

~~~
spacemanaki
> So whenever I post on OOADP, seems like everybody gets in a bit of a snit
> with me :) (not you, just a small minority of the community. Perhaps these
> are dangerous political waters!) But I'll explain a bit more. Please
> remember, though, that this is long-format material.

I appreciate it, and I recognize that there's sometimes a bit of knee-jerk
snittiness that can come across in these OOP vs FP debates, including in my
post. If you've written about this in a longer format somewhere else, or plan
to, I would be interested.

> FP makes little blocks and then fits them together into bigger units. In OOP
> you might spend a lot of time on structure without ever writing any code
> that does anything at all.

This is getting closer to the crux of things. The bottom-up FP style just fits
my own workflow and habits better. Spending a lot of time building structure
without writing code that does anything seems like dangerous premature design.
Thinking about the problem and about problem solving ahead of time is
important, but I'm not sure that building structure is.

> In FP I always feel like I'm carrying the linker around in my head. :)

I'm not really sure what you mean.

> OOP, to me at least, is much more about the people part of programming than
> it is the technical part. FP guys are always making these technical
> arguments about their language, and they miss the point entirely: the
> problem that OOADP solves isn't a technical one, it's an organizational one.
> Where does stuff go?

I think it's possible to answer this question in a functional program, as
another commenter said, Clojure namespaces provide an answer to questions like
"where". I think bigger picture design like MVC can be useful here, see
ClojureScript One for one (relatively simplistic, but very interesting
nonetheless) example.

So I guess if OOP/OOADP is about solving a nontechnical problem, my question
would be if we can solve those same social problems while writing FP code? If
we want to avoid object oriented hierarchies and graphs that are
interconnected and _complected_ , can we still address the social and
nontechnical problems you think OO solves? Surely that's possible? It seems
that relying on OO to solve these problems drags in an awful lot of baggage
(like introducing a lot of mutable state that is problematic for very
technical reasons).

Thanks for the pointers to those books, I'll check them out.

~~~
DanielBMarkham
"... can solve those same social problems while writing FP code? If we want to
avoid object oriented hierarchies and graphs that are interconnected and
complected, can we still address the social and nontechnical problems you
think OO solves?..."

I believe that's where functional OO languages like OCAML and F# come in. Do
your OOAD, then construct the code functionally. Once you realize you're not
going to refactor, start grouping into classes. Your OOAD helps drive your
data structures out. Actual code and functionality drive your class structure.

But what I'm finding is that both FP and OOP code evolves into a DSL; FP more
directly and OOP in a more roundabout manner. If that observation holds up,
then what we're really talking about with organizing code is creating layers
of DSLs, not tiers of functionality. If that's the case (and it's a big "if")
then something like a code budget and insistence on DSLs as a desired end-
state might be the best way to balance both scalability (in terms of team size
and effort) and complexity.

------
spacemanaki
Ok, so there are a few comments claiming that this kind of revelation only
seems valid because the author hasn't seen OO done right, or has only seen bad
OO code. As someone who has gone through a similar shift and feels
disenchanted with a lot of the OO code I deal with on a daily basis, but is
still very much aware of my own inexperience and naivete, I'm wary of these
claims but I'm curious.

So what's some really great, clean, elegant object oriented code that I could
read to better understand what makes up good OO design? What are the books one
should read to develop a deeper understanding of OO's qualities? It doesn't
matter what language or platform they focus on, since I think the fundamentals
ought to be independent, and I'm willing to work hard. Rails internals, Django
internals? Some Java framework? Or is there some awesome piece of Smalltalk
code out there that demonstrates the roots of OO? Is the Gang of Four book
still relevant? Where do you go for getting the bigger design picture?

For context, I've done a lot of Java (Android) but I don't think I've been
exposed to good large scale design in Java (I've read Effective Java and Java
Concurrency in Practice, but both of those deal with the nuts and bolts of
programming in the small) Most of my functional programming experience is with
Clojure, which is very opinionated and takes a radical approach to OO, and I
think the bar has been set kind of high by Rich Hickey.

Please don't tell me to go get a job at Google or your company where the code
is beautiful all the time; that's just not fair.

~~~
raganwald
_there are a few comments claiming that this kind of revelation only seems
valid because the author hasn't seen OO done right, or has only seen bad OO
code_

That argument is also known as, “No True Scotsman.” People regularly jeer at
it when process proponents defend their practices by saying “Yes, that project
failed, but you weren’t doing Waterfall/XP/Scrum/Spiral right.” But there’s no
reason why we shouldn’t poke it with a sharp stick when defending a technical
argument. If so many people are "Doing OOP Wrong," shouldn’t we have serious
reservations about it?

I’m sure that if we pick any practice, we can cherry-pick and find some great
code written with it. But what good is it if such examples are rare?

~~~
pgsandstrom
Just as you might dismiss the arguments as "No True Scotsman" you could
dismiss the original post as anecdotal evidence. The presence of a fallacy
does not directly affect the truth of the point being made.

~~~
raganwald
No, but if all the arguments for and against boil down to anecdotal evidence
and fallacies, why are we bothering with a discussion at all?

------
zoul
This seems to be yet another example of the "X sucks because you can write bad
code in X" argument, which is not really that interesting.

------
option_greek
I would say OOP for OOP's sake became a lot more common with the increase in
popularity of Java. The euphoria of automatic memory management vanished with
the increasing complexity of design patterns.

In most of the cases they are applied for any scenario that even slightly
resembles a design pattern, with most of the energy expended in fitting the
scenario into a pattern than to find the correct solution.

------
kamaal
For most people OOP is basically synonymous with earlier C++ and now Java.

Now wonder people are frustrated, modifying a large project or doing any thing
trivial requires the help of a IDE loaded with Intellisense goodies to help
you navigate through levels and levels of abstraction, often you will have no
clue what each layer does. This is good for reading but bad both for writing
and maintaining code. I have often had to end scratching my head figuring out
what a certain middle layer of code does. I am sure most people are generally
lost figuring out the layers below
AbstractClassFactoryFactoryFactoryFactory.java and can't really understand why
there is method
Something.SomethingElse.AbsoulutelySomethingElse.WhereAreWe.finallyWeMadeit()
like that.

OOP in principle in itself is good but unfortunately the languages that it
gets expressed really makes it case very weak. Every time I see a Java
application with 90% of the code being try/catch statements, get/set methods
and XML DSL's - I cringe. Every time I have to spend 30 mins trying to figure
how to configure and use a logger I get totally lost.

When I think of OO the worst parts flash in front of my eyes.

------
exDM69
I had a very similar revelation to the OP in the article. Coincidentally, I
also happened to be writing semantic analysis for a compiler using the visitor
pattern.

From this I can conclude two things:

\- It's definitely the wrong choice to do abstract syntax tree traversal using
the visitor pattern. But what would be a better choice? When using Java?

\- Writing a compiler can be a life changing experience.

These days I call myself a recovering object oriented programmer.

------
akg
A couple of excellent reads for arguments against OOP:

<http://c2.com/cgi/wiki?ArgumentsAgainstOop>

<http://c2.com/cgi/wiki?ObjectOrientationIsaHoax>

Personally, I'm on the fence, but I think as is the case with most tools,
there is a right and wrong place to use them. The trick is figuring out when
that is.

~~~
justncase80
What I really want is to write functional code in a way that looks like OOP.
OOP is so simple and straight forward in comparison, it just results in code
that is not scalable or easily maintained.

------
copx
I do think that FP IS a snake oil fad and unsuitable for 90% of all code,
which is all about mutable state and IO: manipulating data bases and game
worlds, writing and reading files, sending and receiving network packages,
user interaction etc. all of which is awkward in FP.

Back then OOP was paraded around as the silver bullet of software engineering
some people rightfully pointed out that many problems do not map cleanly to OO
abstractions. People tried to force all code into that straightjacket anyway,
most infamously Java, and thus we ended up with things like "Singleton"s and
"AbstractFactoryFactory"s.

Yet OOP was a success, because most problems can be expressed in a decent to
good way using that paradigm, and it forced some structure on bad programmers.
In contrast, most problems can not be expressed in a straightforward way in FP
and the advantage of forcing structure on bad programmers is mostly gone.

I think the current FP fad is actually an unfortunate side effect (pun
intended) of the OOP craze. All these younger programmers who learned
programming with Java, who had to write all that AbstractFactoryFactory
"Enterprise Java" code, they see FP examples and think they have seen the
light.

As the article almost admits, FP is basically a restricted subset of
procedural programming. However, while these people were taught that
"procedural programming" is an archaic evil and everything must be wrapped
into classes by their Java schools, nobody told them that about FP (because
the instructors probably did not even consider/know it). So now they can enjoy
the simplicity and freedom of procedural code without the feeling of being
"politically incorrect".

However, as I said, FP is simply unsuitable for most real world problems. The
problematic thing about Haskell is not understanding monads, it's that they
are necessary! They and other constructs like that are the "Singleton"s and
"AbstractFactoryFactory"s of FP - what happens if you try to force something
naturally "unfunctional" into a functional straightjacket.

The right solution is multi-paradigm programming. Use FP where it makes sense,
don't use it where it doesn't.

~~~
Drbble
Read "Tackling the Awkward Squad" paper by Peyton-Jones et al.

~~~
EvilTerran
Link for the lazy:

[http://research.microsoft.com/en-
us/um/people/simonpj/papers...](http://research.microsoft.com/en-
us/um/people/simonpj/papers/marktoberdorf/mark.pdf)

It's a good bit of writing, that.

------
EliRivers
This sounds like OOP gone horribly wrong. OOP isn't for the code's benefit;
it's for _my_ benefit.

Some problems can be easily thought about in terms of independent objects; it
makes it easy to work out the solution, and to code an elegant, coherent
solution. Some problems just don't suit that kind of thinking. Applying OOP to
something it's not suited for and then blaming OOP for the resultant mess is
just silly.

------
crumblan
I prepared this whole rant about how displeased I am with your article and how
it doesn't really say anything. Instead I want to recommend that you try
Objective C.

You can do most of the string, dictionary, array things using immutable
objects, which is nice, and the mutable things like windows are usually used
to hold state like positions, colors, etc., and so it's easy to conceptualize
what you are mutating:

NSRect frame = [window frame]; frame.origin.x += 5; [window setFrame:frame];

Singletons are rarely used, mostly for what is basically an event responder
(called the application delegate), and objects that are basically a way to
group functions (NSFileManager to do IO functions, NSNotificationCenter to
send application-wide events).

They've even got a first-class function object.

I have no desire to use Java, and it seems you don't either, but I think you
should consider other OOP languages. It's fine to prefer functional
programming (I sure do) but if you don't get the visitor pattern, I cannot
help but think you don't know enough about it to write OOP off entirely.

------
beala
I think part of what might be going on here is that OOP patterns incur a large
upfront cost in complexity, but the hope is that it will payoff later when it
comes to maintaining and extending the code. For example, the visitor pattern
he talks about might seem needlessly complex. Why scatter the logic for a
recursive tree traversal across several classes when I could do it here, all
in this one function? The response, of course, is that once the program starts
to grow, and you want to write other modules that traverse that same
structure, you won't have to copy and paste that same logic everywhere. Simply
write another class that conforms to your visitor's interface. So, this
reduces code duplication, and decouples the operations your performing on the
tree, from the way that you're traversing the tree.

Another issue is that static type systems often make OOP design patterns seem
more complex than they really are. Compare, for example, Python's visitor
([http://pythonwise.blogspot.com/2006/06/visitor-design-
patter...](http://pythonwise.blogspot.com/2006/06/visitor-design-
pattern.html)) with Java's
(<https://en.wikipedia.org/wiki/Visitor_pattern#Java_example>). Python simply
uses reflection to pull out the right visit method. This is almost a one-
liner. Java, on the other hand, needs a complex double-dispatch setup to
please its type system. Now, I'm not saying that Python's approach is better.
There's a trade off involved, and, in fact, it's the exact same trade off as
before. Python's approach is simpler at first, but, once your program starts
to grow, you might find that catching type errors at compile time is a very
handy feature indeed.

Also note that functional programming isn't without its seemingly complex
design patterns. Monads are the obvious example, but there are many more:
<http://www.haskell.org/haskellwiki/Category:Idioms>

------
anuraj
Have you ever worked on a project with millions of lines of code which is
supposed to work together as a single piece? That is where OO is required. OO
works when you design your system to be composed of blackbox components. Right
level of abstraction is the key. Facades must expose blackbox functionality to
other components. You are never to look into the innards of a component (the
whitebox model do not work). These days the WEB CRUD apps do not require OO as
each service rarely exceeds few hundred lines and they never work as a
monolithic piece. But once you put your head into a Telecom Switch, a flight
control system, an MRI scanner - OO is the way to go.

I think these days exponents of so called 'Functional Programming' just
oversee the importance of abstraction in OO and try to use it in CRUD apps
where it is clearly not warranted and then hurl abuses. Get a Life!

~~~
spacemanaki
Aren't some (many?) telecom switches run with Erlang? I haven't used it, but
from what I understand it's more functional than OO, is it not?

~~~
chriszf
Freeswitch and Asterisk are both written largely in C, although it's unclear
if that's representative of industry practice.

------
GlennS
Surely this criticism extends to any information hiding mechanism in
programming? You could do exactly the same thing using closures.

I happy to talk about the flaws of OO programming, but I'm not convinced that
allowing you to have encapsulated private state is one of them.

------
bdfh42
If you write classes that have methods that can change a non observable state
of the class then you have followed the wrong path. Not at all sure that
functional programming will prove a cure though.

------
darklajid
I love my share of anti oop rants and hoped for some functional praise.

Unfortunately I couldn't read the article on my mobile, because someone
decided it would be a great idea to have floating social sharing gizmos
covering the content. It's totally unreadable right now.

------
Drbble
After author graduates and writes some production code, please post a followup
that shares the experience and says more than "college is harder than high
school"

------
darylteo
I see OO as a way of imposing model constraints in a problem domain... there
may not necessarily be a need for objects to maintain state.

------
Nemmie
That can go both ways I guess. You can do OO right, you know?

