I had occasion today to reflect on what I’ve learned in the last few years developing software and it occured to me, not much has really changed since I first struggled with Lisp and Scheme in university. I still don’t completely “get” functional programming! Wrapping my head around all those brackets in any derivative of Lisp felt like torture, but maybe that was just academia trying to punish me for my eventual release into a world of programming languages concieved AFTER 1979. Not that Iam in any position to be critical of such seminal ideas – which after all are at the root of the Groovy Closure I know and love. I do “get” Closures, fortunately.
š
In the last few years I’ve been exposed to a huge variety of different tools and frameworks, and have followed the transition of Java from 1.4 to 1.6(and beyond!) Past time to take a look at just what has changed, and perhaps why it doesn’t matter so much.
Build tools and dependency management – Ant, Maven, Ivy, Grape
I started off in my programming career with lots of build.xml files and eventually made the (at times rough) transition from there to pom.xml. The best part of this: never having to hand-code a classpath again. Worth it right there. Maven adds enough dependency management magic to the build process to make it a nice alternative, and when you factor in the great IDE support available(I’m looking at you IntelliJ) it’s almost a no brainer. When you need to switch from one project to another, as has been pretty common in my career at least, being able to open a project at first sight and have your IDE correctly load up and run out of the box is a big plus.
Of late I’ve been getting more experience with Grape and Ivy. These dependency management tools bring some really elegant simplicity to the table, especially Grape; good-bye to complicated command line “java -cp …” calls when all you want to do is run a little snippet locally and import a jar. Now of course, this journey takes us all the way back to ant, since it is such a close(and apparently integral) part of Ivy. Which is all right in my book – ant has really stepped up to the challenge in recent history, in no small part due to the community. The Groovy AntBuilder and Gant enable many of the iterative style features so hard to express in xml mostly trivial, greatly simplifying usage of the powerful ant capabilities and making them easier to bring to bear. Now of course, the ability to run both Groovy and ant from with Maven kind of make it a moot point – if you really want to make your life easy, it pays to get to know all of these technologies and fit them into your build in the most effective way possible.
Dependency Injection – Spring, Maven, Seam, Guice
First time I saw dependency injection in action was with Spring. The IOC principle has since then become central to how I look at software. I mean, if you want to unit test effectively, it’s pretty much compulsory. And it encourages you away from ‘bad’ design patterns – static method only classes, shared instantiated utility classes, lack of interface abstraction, etc.
Maven and the Plexus container makes writing Maven plugins a breeze. Baking functionality into a maven build is really pretty trivial and I have had a lot of success with GMaven plugins for applying static analysis to a build: verifying that all properties in a resource bundle are actually referenced in a web application for instance. It’s an added bonus that you can easily test your plugin for Maven… with Maven.
The Seam framework also provides a very nice IOC container and it has been a real pleasure to leverage that power in a real-world application. It certainly facillitates testing – my preferred stack is TestNG with Unitils to add easy annotation support. It’s the simple things like @TestedObject to clearly specify intent and @InjectInto to mock out dependencies that make testing outside of the container as painless as possible. Not only does it ease testing, it encourages good modularization of functionality.
Guice is comparatively the new kid on the block, and the dependency injection framework I have the least experience with, but again the idea is sound, and having another implementation that can take advantage of history is a good thing. Webbeans aims to take the paradigm to the next level, and it will be interesting to see how that implementation evolves. Anyway you want to cut it, the picture is pretty clear – don’t hardcode your dependencies – inject them!
I am a… Functional Programmer?
Somehow, since I started writing code – I started to get it! Closures now make sense to me, currying does not sound like a cooking technique and I realized that however you code certain fundamentals apply.
- write the code
- test the hell out of the code
- make sure the code gets USED, because this is the only way you’re going to find the bugs you didn’t think of in your tests(*see one line above). And no, you didn’t think of everything one line above.
The real point here is don’t discriminate – use the right tools for the job and get the most out of them you can, whether it’s functional VS procedural, Ant VS Maven, etc ad infinitum. Each tool brings a slightly different skillset to the table and if you want to make your programming life easier, it does pay to know which to use when (and how much). Beyond that, taking the time to pry and prod at the tools you use challenges your assumptions and gives you a greater appreciation of just exactly what is ‘going on’ when you hit the Big Green Go button on your build.
Not to mention that all of the tools/frameworks I’ve described here have LOTS of daily users AND represent some of the most executed(and IMO best written) code out there in the Java+ community. As a developer, you can’t help but benefit from digging into such code.
Whatever you do, don’t stay stuck in the past. It just doesn’t make a whole lot of sense when what you’re really after is to make your job as easy and painless as possible to do.