
Why I love everything you hate about Java - of
http://magicscalingsprinkles.wordpress.com/2010/02/08/why-i-love-everything-you-hate-about-java/
======
oconnor0
I find it odd that while the article is titled about Java, all of the code
examples are in Scala.

The statement "function composition is a degenerate case of the Decorator
pattern" in the blog is bizarre to me. OO languages like Java have to resort
to the Decorator pattern to handle their lack of composibility; that seems far
more degenerate than a language that supports this kind of composition without
hacks.

Also this article is 2.5 years old.

~~~
mercurial
Agreed. Most design patterns are workarounds around missing features in a
language. You can go around and pretend the reverse is true all you want, but
it doesn't make it so. Also, looks the author never heard about decorators in
Python, which let you do the same thing if you want, just with much less
boilerplate.

The article reads like it was written by somebody with experience in Java and
Scala, but not much more.

------
r00k
_So we set about to re-write Querulous using my favorite modularity
techniques: Dependency Injection, Factories, and Decorators. In other words,
everything you hate about Java._

Hey there Mr. Strawman.

I write mostly Ruby, and I use dependency injection, factories, and decorators
liberally. There's nothing in Ruby that makes these any harder than they are
in Java (in fact, I'd argue they're easier.)

Two years ago, when this piece was written, the author had more of a point:
some people rejected anything that reminded them of Java out of hand,
including design patterns.

These days, I'd argue that interest in classic OO design ideas is experiencing
a massive resurgence in the Ruby world.

~~~
tptacek
Why would you ever use a "factory" in Ruby?

I'm less certain that DI is "wrong" in Ruby, although it's definitely
unidiomatic.

~~~
r00k
I use a factory for the same things you use them for: to build objects.

For example, I use factories to create test objects that are complicated to
set up (using a gem named factory_girl, actually).

Also, in Ruby, every class is a factory for its own instances. If I define a
class called User, I can assign the class object User to a variable:

factory = User

Then I can call

factory.new

and receive a new User instance.

As for DI, it's not wrong, nor is it unidiomatic. Plenty of folks in the
community use it, and often.

A commenter elsewhere in this thread says that DI is unnecessary in Ruby
because you can just reopen or redefine a class whenever you want. That's
technically true, but isn't a good practice, as it can lead to some rather
rapid foot shootery.

If you want to swap in different-behaving dependencies, DI is a
straightforward choice. Reopening an existing class and mangling it can cause
very confusing behavior, and is generally avoided by experienced Rubyists.

~~~
tptacek
I thought you perhaps meant something more than class objects.

Regarding DI: Jamis Buck infamously used DI for net/ssh and posted that he
regretted doing so, because DI felt out of place in Ruby. I'm not spoiling for
an argument about its virtues.

Regarding "experienced Rubyists" and reopening classes, I think you should
have a look at activesupport/core_ext.

------
josteink
Just before I saw this post on HN, I realized that the first editor I was
presented to when I was being taught Java at university was emacs.

Emacs felt slow, clunky, last-century and everything which could be light,
nimble and cool Emacs made feel boring and hard. I did not get to like Emacs
back then.

In fact I've gone years and years and years actually never fully liking emacs,
beyond it being simpler to use than vim (which I still consider insane) while
readily available on most shells. It was a safe haven, although a unpleasant
one.

Recently though, I've dabbled in clojure. Eclipse is really not good for
clojure development. Especially not so for learning how things works under the
hood. So emacs is seemingly the lingo-franco in clojure circles, and I was
forced to return to my old Java-related enemy. Or at least so I thought.

Out of the box, almost nothing is optimal for clojure development. So you have
to add packages (emacs supports packages? nice!), you may have to tweak
init.el to do so (emacs is configurable and programmable through its own lisp-
dialect? nice!), oh and you may want to add some repos and map package-install
over this collection of useful pacakages (no way!).

Once you're there and getting productive, you might encounter things you don't
like. Google it and find ready-made lisp-code to import into your init.el, and
your problem is solved.

I guess that's not really directly related to this article, but before heading
to HN now, I had the realization that emacs, despite it being the horrible
tool which Java made me hate, is actually pretty awesome.

You need the right perspective to fully appreciate something. This is crucial
and something Java taught me this, although in the wrong way. And just as I
realize this, then I see an article about Java and perspective.

I like cute litle coincidences like that :)

~~~
chris_wot
Have you considered adding your configurations to a GitHub repo?

~~~
josteink
I'd say it's not warranted and it's not needed. After meddling about for a
bit, I did a reset and I did it using "emacs starter kit" by technomancy (of
leiningen fame):

<https://github.com/technomancy/emacs-starter-kit>

On top of this I've added some tweaked versions of yank-indent and indent.el
from the emacs-wiki:

<http://emacswiki.org/emacs/AutoIndentation>

On top of that, I've just added whatever tweaks and hacks necessary to get
screen & emacs behaving properly in a FreeBSD shell, since currently my best
and most powerful internet-facing host is a FreeBSD machine.

So as you can see, most of it is repo'd already :)

------
argv_empty
The article explains why closures are a poor man's objects. Be sure to read
the comments to see why objects are a poor man's closures.

~~~
zanny
Both are a poor mans structs with name mangling!

~~~
anonymous
But really, those are all just fancy names for 'void*' for people who can't
remember two things at once.

~~~
cpeterso
A pointer itself is not a composite data type. It can't remember two things at
once.

~~~
jerf
void* is the zombo.com of pointers. It can do anything. The fact that it can
do absolutely, utterly anything is precisely why it is useless.

~~~
lurker14
Useless? The software running the computer you are typing on is full of void*.

~~~
jerf
All the pointers are void *; and yet, none of them are.

------
confluence
Language wars bore me. I've got pretty decent proficiency in C, C++, Java,
Python and Javascript and I honestly like them all.

I use C to really get what happens on the metal. I use C++ to leverage C and
C++ libraries for perf critical applications quickly. I use Java like C++
where it makes more sense - Android, or availability of libraries etc. I use
Python to prototype and quickly express complex ideas and determine their perf
characteristics. I use Javascript for frontend web dev which communicates with
json back-end APIs that are language/platform independent services that scale
out horizontalty.

I have 2 main rules.

If the question is to learn one important thing or another - I learn both.
Then when I come across a new problem I solve it with a combination of the
tools at my disposal.

Hence this is why I am currently learning Emacs, lisp, clojure, Scala and
Haskell to round out my languages with maybe a little Ruby thrown in. This
will take me a few years.

In the end programming is just about getting things to screen quickly and
correctly. Seen from that viewpoint most languages are very similar at heart.

~~~
jackpirate
>Language wars bore me

The Haskell vs. everything else language war really is important though. All
the languages you mention are basically the same thing with slightly different
syntax or a slightly different runtime environment. Haskell, on the other
hand, revolutionizes the way you approach code. Or at least it did for me.

~~~
confluence
Yeah I'm not so sure. If Haskell is so great why isn't it dominating? Where
are the Haskell phones, apps, services etc?

Don't get me wrong - I enjoy it. But I've learned a few things throughout my
life. First, the one true crowd is always wrong. Two, if it's so good - use
it, and prove it.

A lot of functional stuff is a ton of gushing talk - but no product walk.

When Haskell runs on billions of devices or serves trillions of pages or
produces trillions in revenue call me. Otherwise, I'll just keep shipping with
my lame proven product producing languages.

Functional languages have so far been all talk and no walk.

~~~
mercurial
You do have a few cool, real-world products out there in Haskell (eg, git-
annex, darcs). But to be fair, there is a fairly steep learning curve.

Once upon a time, at my old company, a guy came to an interview. He was very
experienced in PHP, having used it to build websites as a freelancer for
something like 10 years. Did he know object-oriented programming? He'd heard
about it, it was probably good for larger teams. Because he'd just been
working with the same techniques all these years. And the sad truth is, your
average programmer is likely to be like this guy. In which case, you want to
give him a solid language, which is aimed at preventing him from shooting off
his own foot, and does not feature many complicated concepts, like Java.

------
Cacti
I write in all kinds of languages professionally and have been doing this sort
of thing for a long time (since I was 9 and I'm now 31), so, I'm mostly over
the language war thing. Yes, I prefer some languages over others. Or certain
languages in certain situations. But I try not to let my opinions get out of
hand. Everything is pretty much the same anyway.

Java? I can see the appeal. It's really come a long way. The only thing I
can't get over about Java is the goddamned verbosity of it. It's
_excruciating_ to write anything in Java.

Yes, I know. Use a modern IDE. The namespaces are designed that way for a
reason. Just deal with it. It's not a product of Java itself but of the
libraries. Blah blah.

It's still a painful environment to deal with and, with developer time several
factors more important that just about anything else, I value my time highly
and I'm not going to waste it on AbstractSingletonProxyFactoryBean bullshit.

Now, yeah. If you're a huge corporation that is bumping up against the law of
large numbers, where most of your developers are mediocre and yet still have
to work together, then I guess Java is OK.

~~~
vsync
I've found things like Lombok and LambdaJ to be super helpful as far as
verbosity.

One thing that does frustrate me is that the compiler enforces a target
bytecode level at least as high as your source version. Meaning that even the
simpler syntax for initializing generics isn't allowed even though it's pure
syntactic sugar and has no impact on the generated bytecode.

------
viraptor
This is a gem to remember in the future (from the comments): "Design Patterns
are for when you run out of language".

~~~
kbd
Thanks for this. Great quote.

FWIW the original, by Rich Hickey, seems to have been "Patterns mean 'I have
run out of language'".

Cited here - [https://google-
styleguide.googlecode.com/svn/trunk/lispguide...](https://google-
styleguide.googlecode.com/svn/trunk/lispguide.xml) \- but I can't find an
original source.

------
sbochins
Not sure how Java is better than all the "hipster" languages as you say. It
doesn't seem like you're just using some design patterns that are present in
basically every language.

Clojure has futures too, but the syntax isn't as clunky as Scala or especially
Java. All these synchronization primitives are in basically every other
language. Maybe I'm missing something but I don't really see what is special
about Java here. Has the OP ever tried any "hipster" languages, he might be
pleasantly surprised if he did.

------
dustingetz

        dependency injection : currying
        factories : type constructor
        decorators : higher order functions
    

there's nothing wrong with DI and the like. what's wrong is the way it's done
in idiomatic java. when you do DI in idiomatic scala, there isn't much of a
problem.

~~~
lurker14
Huh?

How do any of your analogies work?

~~~
nandemo
One example of the first one:

[http://mikehadlow.blogspot.jp/2010/03/functional-
dependency-...](http://mikehadlow.blogspot.jp/2010/03/functional-dependency-
injection.html)

------
grogs
I no longer care. Java is overly verbose, but therefore explicit. I'm happier
to do concise Scala with more stuff implicit stuff going on, or more explicit
stuff in Java with lots of Spring config.

Opinionated frameworks which hide stuff from me are bad. They're good for
initial productively, but you pay the price later - you have to understand it
to weak it, and may find the architecture doesn't fit your problem.

On the other hand, writing a Spring config file from scratch is a horrific
process, especially without the Spring eclipse plug-in.

But now that I understand web.xml's and application-context.xml/*-servlet.xml,
and have written plenty of Spring config, my productivity is pretty damn good.
So why should I care.

------
devin
FWIW I don’t think the Clojure or Scala communities have any kind of “hate”
for Java. Clojure views Java as an ally for many of the reasons you discuss. I
think you’d be hard-pressed to find people in the Clojure or Scala camps that
refuse to acknowledge there’s a right time to descend into Java. Likewise, I
think any Ruby programmer worth his/her salt would tell you: if you’re trying
to process 20,000 messages per second, don’t rely on Ruby. Moreover, JRuby,
Clojure, and Scala are all quite fond of Java interop, so I’m not sure I agree
with your opening statement that people who use said languages are “hipsters”
who blatantly ignore the benefits of changing the level of abstraction when
the situation warrants it.

------
MatthewPhillips
AbstractFactoryFactory seems like an inevitability of object orientation. I
have to wonder why we don't see it as often in other OOP languages. I'm not
versed in Ruby or Python so I can't comment on those. In JavaScript there
isn't the concise class or extends/implements keywords and people tend to hide
how a library is implemented behind a closure that prevents you from extending
it.

So I wonder if Java just gets the blame because it is the most pure object
oriented language. It doesn't put up walls preventing you from doing what OOP
really wants you to do. C# is the same way, by the way, you see
IThisOnlyExistsToBeGeneric<T> all of the time; AbstractControllerBase is a
real class in C# MVC if I remember correctly.

What walls does Ruby and Python have that prevents this? Because I see no
reason why people _aren't_ doing it.

~~~
lars
There reason you don't see interfaces or abstract classes in Ruby or Python is
because they are dynamically typed. Interfaces and abstract classes are
byproducts that are required for Java and C#'s type systems to work. What use
would you have for them in Ruby?

~~~
zimbatm
I still reason in terms on interfaces when passing arguments to a function
though (eg: argument X needs to behave like a string). It will later be
verified in runtime and when running the tests but it's how I reason when
structuring the code.

------
marizmelo
Java is an excellent language, it has a elegant syntax, but... it's not made
for web development. JSP/Servlets development is a joke.

~~~
parasubvert
Those are 1997 technologies, though. Have you looked at

\- Play Framework <http://www.playframework.org>

\- Jersey [http://codahale.com/what-makes-jersey-interesting-
parameter-...](http://codahale.com/what-makes-jersey-interesting-parameter-
classes/)

\- GWT <https://developers.google.com/web-toolkit/> or

\- Grails <http://grails.org/products/ggts>

for example?

Not saying any of these are perfect, but it's been 5+ years since anyone had
to use JSP/Servlets/Struts.

edit: formatting

~~~
mbell
Mentioning Servlets seems pretty out of place here. The Servlet spec isn't a
web framework its an HTTP middleware. Its more similar to Rack than Rails.
Both GWT and Jersey are commonly deployed on top of Servlets.

~~~
vsync
Because in the past you had to use servlets directly, or JSPs that you had to
do a lot of work manually to separate business logic from the presentation
layer.

Source: I worked at a Web startup circa 2000 where we did exactly that. I
think people sometimes forget how far we've come.

------
dscrd
" Our life is frittered away by detail. Simplify, simplify, simplify! I say,
let your affairs be as two or three, and not a hundred or a thousand; instead
of a million count half a dozen, and keep your accounts on your thumb-nail. "
\-- Thoreau

This is pretty much why I find Java (and others at similar levels of
complexity) distasteful and try to steer clear of anything related to it. It
is also why Go appears to me as attractive: it has simplicity everywhere.

------
setheron
My experience at amazon has been that people.drink the config kool aid. They
make everything configurable but never end of changing in the lifetime of the
app anything from the sensible defaults.

At that point you've just added unnecessary bloat.

There is something nice to be said about code that works right off the bat
with sensible defaults.

------
irisshoor
I think people get too caught up on the verbosity side of code. Most devs
spend considerable amounts of time debugging, and that's probably the suckiest
part of the job. The amount of time spent writing the code (especially for
someone who types quickly, as most devs do) is immaterial compared to the pain
of trying to debug a nasty bug or perf problem (especially in a complex
systems). That's where verbosity helps a lot as you don't have to dig into the
library code to understand what's going behind the scenes, because most of the
relevant configs and choices made in regards to how to use the framework are
laid out in front of you.

------
nviennot
In Ruby, we often use the middleware pattern (the rack stack, sidekiq or
faraday to name a few).

In the article, replace "Factory" with "Middleware" and "apply" with "call"
and it's just like what we do in the ruby community.

------
ekyo777
This article doesn't say much about Java, it is mostly about OOP patterns

~~~
codewright
>it is mostly about OOP patterns

It's mostly about why I love Clojure's partial / Haskell's currying.

~~~
josteink
As someone who has spent a little time into F# and other languages where
currying are the default behaviour for any function, this is the one thing I
find myself missing the most in clojure.

Yes, I see why wee need partials and can't have currying by default. It would
seriously mess up destructuring. Yes, I get that. I still miss it though.

~~~
codewright
I'd rather have destructuring.

------
Peaker
This guy must really love his null pointer exceptions.

------
yxhuvud
I think the author of this article has too much exposure to Rails 2.x and not
enough core knowledge of Ruby. If he had actually known the language well,
then he wouldn't have made any references to the deprecated rails hack
alias_method_chain. Instead, he would have used modules to examplify.

The problem is though, when doing it with modules instead then the points he
is trying to make totally disappears.

------
kevingessner
tl;dr: "different languages are appropriate for different uses"

~~~
danabramov
or different habits, for that matter.

------
realrocker
I refuse to get drawn in this.again.for the last time.

------
shasta
No hire

------
pootch
I reject the idea, that because I want to scale, I should have to write thread
pools, executors, concurrent queues, and task completion APIs. This is 2012,
any idiom, functional or not that doesnt support this as a built in capability
is less than worthless. How many times do I have to write, rewrite and debug
the obvious just to make a living? And as for the factory pattern, yes you can
use it to hide a whole bomb load of configuration and code evil, that you
probably should never even have to worry about, if you werent working in such
a crap tool

~~~
vsync
Which is why I love working in a Java EE application server like Geronimo
where very smart people have gotten paid lots of money to do that boring
grunt-work for me, and I can just spend my time building features and deploy a
nice scalable system when I'm done.

