
Things Java Programmers can learn from Clojure - goatslacker
http://www.lispcast.com/java-learn-from-clojure?utm_source=dlvr.it&utm_medium=twitter
======
skrebbel
Nice article. It does, however, trigger a thought:

> _By making values mutable, this magical-changing-at-a-distance is always a
> possibility._

I agree, very much so. However, I could also simply promise that none of my
code, nowhere, will modify that DateTime. On top of that, I'll ask all my
colleagues to not mistreat it either.

Now, that's what many of us are doing now, and the entire point if the OP's
first section is that that's just asking for trouble. But how is that
fundamentally different from promising to never call toRubles() on a DateTime
object? That's what you do with dynamic typing. Yo, here's an object. Please
only call methods that it has, and I won't tell you which those are so you'll
have to guess the types it may have and then browse to the API docs first
(unless it has a _method_missing_ , which you'll have too look at the API docs
for as well - but what if it's duck typing and only one of the ducks quacks
_method_missing_?)

Sure, I'm exaggerating. I like dynamic typing. I just have the idea that
immutability is for nouns what static typing is for verbs. Just like Java has
it half-assed, I feel a bit that Clojure has it half-assed the other way
around.

In terms of Steve Yegge's conservative vs liberal discussion[0], it feels like
Clojure went all liberal on one end, just to get super-conservative on the
other.

[0]
[https://plus.google.com/110981030061712822816/posts/KaSKeg4v...](https://plus.google.com/110981030061712822816/posts/KaSKeg4vQtz)

~~~
skrebbel
Yeah, replying to myself. I'm not sure if that's considered weird but ok.

According to this logic, most mainstream languages don't make sense. Notably,
Java, C#, C, C++, Clojure are all screwed up. Not sure about other lisps.
Ruby, PHP, JavaScript, Python, F#, Scala and Haskell have it right though.

(yeah sure, you can do mutability in Scala and immutability in Java, but the
languages and their community _lean toward_ the other, which is what matters
here, I suppose)

Given that I've been much of a C# fanboy recently, my nose bleeds.

~~~
holmak
> it feels like Clojure went all liberal on one end, just to get super-
> conservative on the other.

In the brief time that I used Clojure, I also thought that the contrast
between immutability and dynamic typing was very strange. Ultimately, I think
it makes _more_ sense than having the entire language be highly dynamic (or
highly static).

I think Clojure's choice is not inconsistency, but that there is a kind of
budget for craziness in a language. In Clojure, you can go crazy with dynamic
types on the foundation of immutability, transactions, etc. In Haskell, you
can go crazy with really awesome static typing tricks that would be utterly
unfathomable if the language wasn't very rigid in every other way --
immutable, referentially transparent, side-effect-tracking. These two pack all
their craziness into one corner of the language.

On the other hand, other languages -- Python, Javascript, Ruby -- seem to
spread the craziness (I am not sure I picked the best word for this!) around,
instead of having one super dynamic feature and everything else very
inflexible. These languages tend to lack the really big flashy features:
macros, typeclasses, etc.

It seems that you have a lot of flexibility as a language designer on how you
spend your craziness budget, as long as you don't go too high (and become
incomprehensible) or too low (Java?).

~~~
dmcg
Maybe constraints rather than craziness? Constraints tailor a language, make
it fitter for one purpose or another. But you have a limited constraint budget
- overspend and everything is difficult.

As an old boss of mine (hi Paul Earwicker) used to say - "flexibility is just
design decisions you haven't taken yet."

------
lazydon
Why these things in stay in books and blogs and never make their way into Java
web apps:

1\. Use immutable values:

Models used in client server communication need to follow Java Bean spec which
is like the exact antagonistic concept to immutability. Service methods that
implement business logic are stateless. As objects are not shared across
threads, nobody feels the need for immutability. The most popular frameworks
Spring and Hibernate dictate this architecture.

2\. Do no work in the constructor

Are constructors still used? All services are wired using dependency
injection. Models are either DTOs or Hibernate POJOs - both dumb and anyways
don't do any work.

3\. Program to small interfaces:

Interfaces are dictated by functionality they provide and not size. They can
have hundreds of methods. This is how it looks: DocumentService - put every
document related method in here, FinancialInstrumentService - put every
instrument related method in here

4\. Represent computation, not the world

Almost everybody begins OOP with this misconception - objects in real world
directly map to OOP objects. Its maybe a good place to start but how many grow
up from the initial simplistic rule - map nouns in requirements to classes.
So, you end up with objects that don't really mean anything and don't do much.
Naive use of UML diagrams also leads to this. Discovering abstractions is
tricky. One needs to really live with requirements inside out before they
present themselves. Who has so much time? Believe me in a quarterly release-
developers get around only 3 weeks – rest is divided into BA, QA, UAT, freeze,
deployment time.

PS: Please don’t get me wrong OP makes good points. It's sweet but the reality
is different. May be Google does this (and they do in Guava which is just an
example one after another of good stuff in Effective Java). But there's a big
corporate java world out there that does things differently. They have well
defined easy run of the mill patterns where these things don't fit (yet). This
was just a peek into it.

~~~
mseebach
1: Just because some ubiquitous libraries have dictated a practice doesn't
make it a good idea or a good model. In fact, Hibernate's tracking of mutable
objects in the current session is one of the most painful things about it.
There's nothing inherent about client server communication that forces beans
on you?

2: That's good, but work in the constructor is by no means gone.

3: That sounds like god objects. "FinancialInstrumentService" is way too much
functionality (or poorly named). Getting a current quote, getting historical
quotes, doing quant-stuff and placing a trade are all completely separate
concerns. Opening a document, saving it, printing it - all separate concerns
that are better kept in separate interface. Now, there's little harm in having
an implementation implement several interfaces if the implementations has much
in common. Extra bonus: Easier to write tests for.

4: Mostly agree, but:

> Believe me in a quarterly release- developers get around only 3 weeks – rest
> is divided into BA, QA, UAT, freeze, deployment time.

I won't believe you, because I've worked on a team that pushed out releases
every two weeks, and got 8-9 days development in for each.

~~~
timbaldridge
I would go a step farther and say that OpenDoc should be in a separate
interface from SaveDoc.

~~~
mseebach
That's what I meant - should have said interface_s_, I see now :)

Actually, opening a document is probably not even a good abstraction.
DocProvider is better: You can have FileSystemDocProvider and BlankDocProvider
- the latter can't meaningfully be said to "open" a document, but it's
interacted with in the same way.

------
lazydon
Tangential:

OP reminded me of Google Testing Blog [1]. Misko Hevery used to share lots of
great insights there. Awesome yet practical stuff on coding in Java world,
which anybody will greatly benefit from but not many are aware of. I hope more
people read his stuff. I wish he stayed a bit longer before moving on to the
AngularJS project - Java needed him more than the script.

Another Google Testing Blog star was James Whittaker, who's now moved on to
Microsoft. Google Testing Blog doesn’t seems the same exciting place any more.
And to add to that the crazy new design of blogspot - some stuff keeps
happening on the page that's beyond one's control.

[1] <http://googletesting.blogspot.com/>

------
tawgx
If Java programmers would only apply the concept of immutability the world be
such a better place... Every time I log from within a setter to see who's
calling this and when, a little fairy falls from the sky.

~~~
tomjen3
I have hacked Haskell just to be able to see what goes on inside a particular
method chain.

~~~
calopetreep
Do you mean you have trouble with seeing what's going on inside a long
function composition? I wrote a cool function to examine it with almost no
code changes:

    
    
      module TraceCompose where
    
      import Debug.Trace
    
      -- | Trace a value, resulting in the value itself
      idTrace :: Show a => a -> a
      idTrace x = trace (show x) x
    
      traceCompose :: (Show a, Show b, Show c) =>
        (b -> c) -> (a -> b) -> a -> c
      traceCompose f g = h f . h g . h id
        where h f x = idTrace (f $ seq x x)
    
      -- Replace "normal" function composition using traceCompose.
      test = (+1) . (*10) $ 4
        where (.) = traceCompose
    

When you run "test", it will print:

4 40 41

(i.e., the outputs of each function at each point in the composition in order
of execution.)

------
zvrba
I thought that classes+methods were meant to transform an object from one
consistent state to another consistent state. So why is immutability suddenly
a big deal? (I.e., if it's a big deal, may it be because encapsulation is
lacking? IOW, is immutability a rediscovered "private" keyword, just much more
cumbersome to use?)

~~~
unclebobmartin
BTW, immutability has nothing to do with encapsulation. Encapsulation is the
hiding, or access restriction, of data structures from "foreign" functions.
Those foreign functions may only manipulate the encapsulated data through a
prescribed set of functions.

We achieve this in clojure through clojure's lovely typing mechanism which
allows you to declare types that have publicly known functions without any
data declarations; and private implementations of those functions that know
the data they are manipulating.

One last note. C was much more encapsulated than C++, Java, or C# because in C
you would declare your functions in a .h file, and your variables in a .c
file. No other .c file could see your variables, so they _had_ to use your
functions. The public/private keywords were added to C++, and then to Java and
C# because the act of putting variable and function declarations in the same
source file broke encapsulation, and we needed a way to re-assert it. That
reassertion was only partially effective.

The bottom line is that all the C based OO languages are _less_ encapsulated
than C.

------
dlss
Re _> 2\. Do no work in the constructor_

The author doesn't propose a solution here, so I'm worried he's thrown out the
baby with the bath water. Yes, it's true that you should have no File IO in a
constructor when it violates the SRP. At the same time (and as the author
notes), it's very convenient to have Foo.fromFile(String path) or similar.

Here's what I think the compromise looks like:

    
    
       public static OptimizedPage fromFile(String path) throws IOException {
          return OptimizedPage.from(path, FileReader.readFile(path));
       }
    

Which seems like having your cake and eating it too.

Or to put it another way: that File IO needs to happen either way -- forcing
the caller do write:

    
    
       OptimizedPage foo = OptimizedPage.from(path, FileReader.readFile(path));
    

whenever they mean

    
    
       OptimizedPage foo = OptimizedPage.fromFile(path);
    

Is a subtle violation of DRY.

~~~
lmm
So yes - static factory methods - or, if it gets complex enough, a distinct
factory object - are the right place to do work that would otherwise need to
be done in the constructor. Use package-private constructors to enforce that
people don't bypass them.

~~~
dlss
Those are factory methods because I think

    
    
       OptimizedPage.fromFile(pathName);
    

reads cleaner than

    
    
       new OptimizedPage(pathName);
    

Do you think there's a real difference (besides readability) for preferring a
factory method to a constructor in this context?

~~~
lmm
As a library vendor it gives you more flexibility, particularly if you make
the method return an interface rather than the concrete type. Also it can make
working with frameworks that call a constructor by reflection easier (you
probably know if this is happening though). It's certainly worth separating
the "inner" (i.e. the one that takes a FileReader) from the "outer"
constructor so that you can call the inner one for testing (perhaps with a
mock FileReader), but admittedly you can accomplish that equally well with a
public constructor that calls a protected constructor.

For internal code I doubt it makes a lot of difference - you can always change
it if you need it - but I prefer to use static factory methods everywhere for
consistency.

------
gordaco
I think that the article's defense of immutability is a bit poor. Making a
date mutable means that it won't always reference the same point in time:
yeah, a birthday will remain constant, but an appointment may not; the same
goes for a lot of types. That's why C and C++ gives us the "const" keyword:
the same object can now be used as mutable or immutable, depending on
circumstances.

The other points, especially the second, are spot on, although they have a lot
more to do with the Java culture than with the language itself.

~~~
weavejester
The date of an appointment might change, but the date itself does not. Dates
are values that refer to a fixed period of time; the meaning of "March 7th
2013" won't change if I move an appointment.

The correct way to handle an appointment is to have a reference to an
immutable date. When you want to change the date the appointment is on, you
change the reference to a different date, not the date itself.

------
iSnow
What bothers me just a wee bit in section 1 of his example is that Date is
more or less a simple container class for data - one that could be implemented
as a HashMap.

It is easy to make classes like Date immutable, but that does not help with a
lot of problems. Date is super-easy to test, only state, no logic. Similarly,
static methods are easy to test.

The real pain in Java is when a class has both state and logic - and those are
precisely the classes you cannot easily make immutable.

~~~
brown9-2
Not necessarily - take joda-time's DateTime class as an example, which
contains plenty of methods for changing fields in the date, but all of which
return _new_ DateTime instances to caller. DateTime itself is immutable.

------
jared314
I would add "Create custom annotations sparingly". It makes Java interop and
debugging harder. But, that is just a personal pet peeve.

------
shad0wfax
Good article.

Writing immutable software is hard, when the language doesn't provide
constructs for it. It will require some discipline. There are some good
frameworks/tools for the JVM for Java programmers for this (the whole AKKA
package is a good place to start).

I would highly recommend Venkat Subramaniam's book for Java programmers:
"..Concurrency on JVM.."- [http://pragprog.com/book/vspcon/programming-
concurrency-on-t...](http://pragprog.com/book/vspcon/programming-concurrency-
on-the-jvm)

------
martinced
OK but these things are not enough. I'm a long time Java dev and _all_ these
were known in c.l.j.p. and IRC since a _very_ long time. I was doing precisely
that, even using the "functional Java" libs when they came out and doing even
more radical things...

And I can tell you that even when doing that switching to Clojure is pure joy.

Because even when doing what TFA talks about, this still doesn't solve lots of
very nasty Java issues, like the totally outdated approach to concurrency.

What Java programmers can learn from Clojure is that it's possible to create a
language targetting the JVM which cannot deadlock and which can offer a
_dramatic_ reduction in the size of the source code.

Sadly you simply cannot apply these to "Java the language": Java is utterly
verbose and there's no way to have a "sane" way to deal with concurrency in
Java (yes, I've got my Java _"Concurrency In Practice"_ copy since it came
out).

The other _major_ thing to learn about Clojure + Datomic is that there's a
world out there made of something else than the special kind of hell that
Java/C# + ORM ([N]Hibernate) + XML + SQL is. _(and before you start whining
like cry-babies, Datomic can be backed by SQL DBs)_

Programmers who haven't done it so yet should _really_ go watch videos by Rich
Hickey, here are three particularly good ones:

"Simple made easy"

"The value of values"

and "The Database as a value"

<http://www.infoq.com/presentations/Datomic-Database-Value>

Now sure some will criticize Clojure as being a Lisp-1 and not having real
reader macros, others will rightly point out that Clojure's documentation
_sucks_ big times and that stacktraces are still a serious issue.

But at least Clojure is showing that there's a saner way than this Java
madness.

You have to realize that Clojure is Rich Hickey's fourth attempt or so at a
Lisp dialect and that he had _lots_ of very painful experience working on Java
Real-World [TM] maddening codebases.

~~~
jbooth
What do you mean by the totally outdated approach to concurrency? I'm also a
longtime Java dev who's embraced these values for a long time, and I generally
thought of using ExecutorServices and Callables as a very functional approach
to concurrent programming. If you're referring to manually starting threads
and using synchronized monitors to ensure thread-safety, then I agree, but
java.util.concurrent really doesn't encourage that approach.

~~~
pivo
Not the author, but I'd say he's referring to two Clojure features that make
programming with concurrency so nice, specifically STM (Software Transactional
Memory) and immutability by default. STM is much better (IMO) approach to
concurrency than locking, but it's really only viable (as far as I know) in a
language like Clojure where values are immutable by default.

The great thing about STM is that it's easily composable, while locking isn't.

~~~
seanmcdirmid
It can be done at the page level in an OS if you want. It's not efficient, but
then it hasn't been shown to be that efficient in a controlled functional
language yet either. Locking still wins on clock cycles, unfortunately.

