Nice article. It does, however, trigger a thought:<p>> <i>By making values mutable, this magical-changing-at-a-distance is always a possibility.</i><p>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.<p>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 <i>method_missing</i>, 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 <i>method_missing</i>?)<p>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.<p>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.<p>[0] <a href="https://plus.google.com/110981030061712822816/posts/KaSKeg4vQtz" rel="nofollow">https://plus.google.com/110981030061712822816/posts/KaSKeg4v...</a>
Why these things in stay in books and blogs and never make their way into Java web apps:<p>1. Use immutable values:<p>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.<p>2. Do no work in the constructor<p>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.<p>3. Program to small interfaces:<p>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<p>4. Represent computation, not the world<p>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.<p>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.
Tangential:<p>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.<p>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.<p>[1] <a href="http://googletesting.blogspot.com/" rel="nofollow">http://googletesting.blogspot.com/</a>
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.
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?)
Re <i>>2. Do no work in the constructor</i><p>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.<p>Here's what I think the compromise looks like:<p><pre><code> public static OptimizedPage fromFile(String path) throws IOException {
return OptimizedPage.from(path, FileReader.readFile(path));
}
</code></pre>
Which seems like having your cake and eating it too.<p>Or to put it another way: that File IO needs to happen either way -- forcing the caller do write:<p><pre><code> OptimizedPage foo = OptimizedPage.from(path, FileReader.readFile(path));
</code></pre>
whenever they mean<p><pre><code> OptimizedPage foo = OptimizedPage.fromFile(path);
</code></pre>
Is a subtle violation of DRY.
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.<p>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.
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.<p>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.<p>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.
Good article.<p>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).<p>I would highly recommend Venkat Subramaniam's book for Java programmers: "..Concurrency on JVM.."- <a href="http://pragprog.com/book/vspcon/programming-concurrency-on-the-jvm" rel="nofollow">http://pragprog.com/book/vspcon/programming-concurrency-on-t...</a>
OK but these things are not enough. I'm a long time Java dev and <i>all</i> these were known in c.l.j.p. and IRC since a <i>very</i> long time. I was doing precisely that, even using the "functional Java" libs when they came out and doing even more radical things...<p>And I can tell you that even when doing that switching to Clojure is pure joy.<p>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.<p>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 <i>dramatic</i> reduction in the size of the source code.<p>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 <i>"Concurrency In Practice"</i> copy since it came out).<p>The other <i>major</i> 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. <i>(and before you start whining like cry-babies, Datomic can be backed by SQL DBs)</i><p>Programmers who haven't done it so yet should <i>really</i> go watch videos by Rich Hickey, here are three particularly good ones:<p>"Simple made easy"<p>"The value of values"<p>and "The Database as a value"<p><a href="http://www.infoq.com/presentations/Datomic-Database-Value" rel="nofollow">http://www.infoq.com/presentations/Datomic-Database-Value</a><p>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 <i>sucks</i> big times and that stacktraces are still a serious issue.<p>But at least Clojure is showing that there's a saner way than this Java madness.<p>You have to realize that Clojure is Rich Hickey's fourth attempt or so at a Lisp dialect and that he had <i>lots</i> of very painful experience working on Java Real-World [TM] maddening codebases.