Outrageous statements on Java: Guava, Modularity, Build

I'm rolling off a 16 month stint as the sole proprietor of a Java library used internally where I work.  Yep, it was an almost unheard-of situation within corporate America: I had no project manager, no marketing rep, no support staff, no unique testers.  I was responsible for API design, test plan, interfacing with multiple teams, delivery, support, infrastructure.  The works.

In short, I loved it.

I loved getting to code 6 to 12 hours a day, every work day, working through design decisions, collaborating with other teams.  I'd go to bed noodling on design problems, I'd often get insight into them over coffee, then I'd have them implemented by that next night.  Most of the people I worked with were colleagues of mine from way back.  My only mandate was "make them happy," and take care of my own stuff.  I had a project manager for the first month or so; once he was satisfied I had my stuff together, the reigns were off.

(Insert maniacal laughter here)

Prior to this assignment, I'd had an uneven career path--I was a (non-coding) team lead for a product amid an unclebob-esque phase of bit-rot, mostly dealing with customer issues.  Then I took an assignment doing C++ / Win32 comm work in our driver group for a year.  It was a very mature subsystem, so again--most of the work was break/fix and stability.  After that, I hopped on a classic deathmarch project for 18 months, and did utility infielder work while trying to lead/architect a system on the fly.  I coded where I could, the largest piece of which was a small application written in ActionScript 2 (!)

Anywho...

So, I'd been out of Java since 1.4.  Right when I stepped out of my project to go to driver-land, they were looking at going to Java 5, with its myriad syntax oddities:


Also, having just come off ActionScript, which has the same root as JavaScript, I'd gotten used to asynchronous programming.  It took much pain, but I broke myself of needing a new Thread to do everything, instead learning to live in callback land.

That is all to say, my perspective on tackling a J2SE 1.5 library were somewhat fresh and unbiased, other than a deep-seated hatred for the Singleton pattern

Without further ado, some random ruminations on Java in 2010->2011:

  • Yes, it's verbose and ugly.  Use Guava, and it's less so.  It's also standard, powerful, and runs everywhere.
  • Logging is still a heterogeneous mess.  Use slf4j and it's less so.  Okay, that's a cop-out: It's still a mess but your library will be insulated from whichever religion...er...method your consumers genuflect before.
  • Modularity, in a word, sucks.  I understand this is a hard problem that no one has solved satisfactorily.  Still yet, I imagine there's something more advanced than java.util.ServiceLoader yet less-onerous than  Spring, Guice, or (heaven help you) OSGI bundles.  I ended up combining ServiceLoader with a bit of hand-rolled setter injection (a la Guice) to manage it without requiring another library.
  • (Nonsequitur) Git is indescribably cool, while remaining unintelligible to the untrained.  That is, I've taught managers and graphic designers to use Subversion ("download Tortoise...now click here..."); I couldn't imagine doing the same for git.  Granted I'm no Matthew McCullough.
* * *
Build.  Ah, Java build.  If ORM is the Vietnam of Computer Science, surely build management is the Land of the Lotus Eaters for Java/JVM devs.  In the time I'd been away from java, the zeitgeist moved from (deep breath now....): Ant, Maven1, Ivy, Gant, Maven2, Gradle, Maven3.  I probably missed a few in there.


Build gets its own section, because this is one where I can't make a pithy epigrammatic recommendation, at least not in good conscience.  Here's some ways I slice at it.

  • Right out: Maven1 or Gant.  Obsolete given the others on the list.
  • Ant: most mature & crufty.  Most Java devs can work with it, unless they've been suckling the teat of IDE for years.  Easy to do non-standard stuff.  Verbose, since Ant makes you spell-out explicitly everything you want it to do.  Ironically, then, it's not programmable unless you're masochistic.
  • Maven2/Maven3: It pains me to say this, but these are probably the most mature and tractable of the bunch.  They move you into the Transitive Dependency (warning, math ahead!) world and simplify your build.  They also shackle you into the "maven way."  Structure your files, tests, resources, and build steps just so, and maven will make it trivial to build, test, release, document your module.  Need to do something novel, and maven will make you long for the "freedom" of ant or even makefiles.
  • Ivy: I haven't messed with ivy too much, but it seems like a good compromise between ant and maven.  You get dependency management and transitivity, without giving up the control inherent in an ant file.  It has ALOT of moving parts to understand and since it's so customizable, it's easy to get wrong.  I had one top notch dev and one poseur (me) looking at an ivy file problem for three days before we figured out it was a missing '->' operator.  Yep, finicky, and the docs aren't the best, mainly because most people use either maven2 or....  
  • Gradle:  Gradle burst on the scene recently, and as of today, it hasn't hit 1.0.  It's an amalgam of every good idea in the above, and dumps XML in favor of a Groovy DSL.  It's terse--not Scala terse, but small, and does most things for you, in the style of Maven.  The big difference: It's actually Groovy code, so you can put as much imperative logic in there as you like.  That's a double-edged sword.  It gives you ample opportunity to shoot yourself in the foot, and its free-form nature brings us (ironically) back to Ant:  It's easy to do non-standard stuff.  Dince it's not at 1.0 yet, it's almost CANNONICAL to do non-standard stuff.  (hope you enjoy reading mailing lists...)
That being said, one opportunity in being a one-man-show was I had no one to convince if I wanted to try something out, so I switched from Maven2 to Gradle.  My unvarnished opinion at the moment is, it's not ready for prime time.  As of today, we've had 6 milestone releases moving towards gradle 1.0, and each has been less stable than the last.  Milestone 5, in particular was so problematic that they pulled it from the downloads section.  

If I had it to do over again, I don't see the ROI in converting a working Maven2/Maven3 build to Gradle right now for these reasons:
  • The plugins aren't there, or they're duct-tape & bailing wire bolt-ons of Ant tasks.  This is where Maven really shines: If I want to add a plugin to my build (say, Cobertura) I find the Cobertura plugin, I add it do my pom.xml in the plugins section, and it's there, pulled-down from MavenCentral the next time I build.  Gradle, it's not that easy, and it's almost PERL-like in its TMTOWTDI-ness.
  • There's churn.  They're racing for 1.0, and they're adding features not just at the 11th hour, but at 11:55. 
  • I happened to like the site generation & documentation features of maven, and gradle doesn't have anything to match.  Granted, I may be in the minority, as Maven3 ditched the default site stuff from core moving it to a plugin. Look, Pluto is a planet, Han fired first, and MAVEN CAN BUILD A SITE, okay?! /rant
Suppose, however, that you have a greenfield project, or one that's on Ant or Maven1?  Go Gradle, in my opinion.  You'll need to dedicate one person to learning "The right way to do it" so you don't end up with a spaghetti build.gradle, but that's pretty much the same way in everything but maven.  In maven-land, every pom.xml is equally mired in verbose angle-bracket hell.

* * *

So, there you have it, my (mostly unsupported) ramblings on doing a java library in 2010 and 2011.  Tools are great and I hope some of the suggestions I have above either help you or help you pity the sorry state of things before people had ____________ in year __________, when you're reading this.  (Suggestion: "neural programming, 2016")

Popular posts from this blog

Monday Mope

RegisterForPrintAsyncNotifications

The reality of the next car purchase