Thursday 28 October 2010

The Bore That Is Core

(and how less gives you more)

Every single Java codebase I have ever come across has had a project called core or common or somesuch. And almost-universally, dwelling within this library, under the banner of "useful functionality used by other projects" lurk classes like:

  • StringUtils for String manipulation
  • FileHelper for dealing with files
  • ValidationUtils for argument-checking
  • DateHelper for tweaking Dates

I know, I know. But I've seen this macro-level antipattern in even the most experienced of development houses.

If you have a "core" library featuring any of the above stuff, exorcise that code now. Right now. Your core library is a liability. You are maintaining redundant code that almost-certainly has bugs you haven't found yet.

In the spirit of simplification, may I humbly recommend:

  • Apache Commons Lang gives you StringUtils, DateUtils and loads more besides.

  • Google's Guava (formerly Google Collections) gives you fabulous, fully-genericised collection-manipulation, plus some handy-dandy utilities like Preconditions to take care of your argument-checking requirements

These libraries will slim down your "core" to stuff that is genuinely domain/site/whatever-specific.

Grab them, learn them, use them, love them :-)

Monday 25 October 2010

Beware The Marauders ...

... They've Been Customised

An otherwise-routine story-sizing was enlivened (for me at least) by our BA's rapidfire pronunciation of the phrase:

Customer Orders

Which was phonetically indistinguishable from:

Custom Marauders

I don't think they are covered in the Enterprise Archetypes book just yet...

Thursday 21 October 2010

Simplify, Then Add Lightness

The Virtues of Being Small

Colin Chapman's famous quote is applicable to software development as it is to performance cars. In Clean Code, Uncle Bob dishes out the following sage advice:

  • The first rule of functions is that they should be small
  • The second rule of functions is that they should be smaller than that

The story is the same in the chapter about classes; small is good. Small means the class has few (ideally one) responsibilities. This gives each class far more potential to be re-used. Small classes give a chance for a system to be organised more logically. It's crystal clear:

Only good things come from having small classes

So methods benefit from being small, and classes benefit from being small - why stop there?

At my current workplace, we've been having problems with excessively-long CI build times. A little bit of investigation showed that there was one core library that was constantly being rebuilt due to upstream changes, and would cause an avalanche of dependent builds to be queued up when it finished building. Combined with the fact that the time-to-build of the project itself had blown out from 5-ish to 10-ish minutes, it was a disaster.

You can guess where I'm going with this. The library was too big. It tried to do too much, and thus was depended upon by myriad downstream projects. Ponder the consequences of refactoring it into vertical slices that are still operating at the same "layer", but address fewer needs:

  • The smaller slices depend on fewer upstream projects and hence get pointlessly-rebuilt less often
  • The smaller slices take less time to build
  • The smaller slices bring along less JAR file "baggage", reducing the eventual deliverable size
  • Downstream projects can pick and choose from the slices they actually need. The number of pointlessly-run dependent builds drops
  • There's a closer correlation between Java package name and the project it belongs to

This is all good too. So I'm hereby adding a new pseudo-Clean Code mantra to my mental map:

  • The first rule of projects is that they should be small

Tuesday 19 October 2010

Fortress Eclipse

Know Thine Secret Passageways

As mentioned previously, I think Eclipse is a great IDE. It somehow reminds me of a massive medieval fortress - must be all the grey in the UI.

  • It's tremendously strong, with huge thick walls that take a long time to get into (learn).

  • The rather lengthy startup time is required to muster the troops (plugins) for inspection by the king (you, the Eclipse user).

  • Once you're inside, there's a thriving marketplace and you rarely need to leave. Every now and then (version control) riders arrive with news from remote parts.

  • There exist innumerable secret passageways (keyboard shortcuts) that can get you to anywhere in no time

  • Very occasionally, the king lowers the drawbridge and allows his magnificent new (code) carriage to be seen by the lowly peasants at the bottom of the hill ... OK, OK I'm going a bit far with the whole castle analogy, but there's a point coming, I promise!

Eclipse is a very large, very complex product - I actually consider it a greater achievement than something like OpenOffice (which in itself is an extraordinary effort) because it's designed for arguably the toughest critics of all - fellow programmers. When you first arrive in the castle, it'll take you a while to find your way around, but you should not just stop there. You might not get lost any more, but it doesn't mean you can't get to know as many "secret passages" as possible!

I was in a code review today and watched a fairly senior Java developer bounce his way inefficiently around the Eclipse UI. I told him these keyboard shortcuts and he was immediately "closer to the code" rather than grappling with his IDE:

  • Ctrl-Shift-T-Open Type: Most of the time it's quicker than Ctrl-Shift-R (Open Resource) for opening a Java class because none of the .xml, .properties et al malarkey gets included. Also, you can configure Type Filters from the top-right triangular drop-down to always ignore certain packages (e.g. filtering the hated java.sql.* means you never have to pick which Date you meant)

  • (With a class name selected) Ctrl-T-Type Hierarchy: Essential for clambering up and down an inheritance tree

  • (With a class name selected) Ctrl-Shift-G-Find References: Vital for seeing how extensively a class or interface is used

  • (With a field/method/class/parameter name selected) Alt-Shift-R-Rename: With practice you can attain vi-like levels of keyboard-driven speed with this refactoring shortcut.

Hopefully these tips (whether new to you or just a refresher) will help you next time you're touring the castle.

Friday 15 October 2010

Quartz Jobs in Spring 3.0

Elegant Simplicity

The Spring Framework's Quartz integration is a lovely example of a framework doing all the heavy lifting, allowing the developer to concentrate on the actual task.

Thanks to the MethodInvokingJobDetailFactoryBean, any Spring bean can be invoked periodically, with all of Spring's dependency wiring happening exactly as you'd expect. This makes unit testing an absolute breeze - you just test the expected functionality, ignoring the external timing concerns. Even integration testing can be accomplished quickly by substituting a faster schedule; for example, if our "runtime" bean definition looks like this:

<bean name="thingyServiceBean" class="com.millhouse.service.FooService"/>

<bean name="thingyJob" class=
  <property name="targetObject" ref="thingyServiceBean"/>
  <property name="targetMethod" value="doThingy"/>
  <property name="concurrent" value="false"/>
<bean name="thingyTrigger" class=
  <property name="jobDetail" ref="thingyJob"/>
  <property name="repeatInterval" value="60000"/> <!-- 60 sec in millis -->
  <property name="repeatCount" value="-1"/> <!-- -1 means forever -->  

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  <property name="triggers">
      <ref bean="thingyTrigger"/>
we obviously don't want to have our thingyServiceBean invoked every sixty seconds forever in integration tests, so we supply a different application context for testing:
<import resource="classpath:jobConfig.xml"/>
<-- Overridden definition for the trigger: -->
<bean name="thingyTrigger" class=
  <property name="jobDetail" ref="thingyJob"/>
  <property name="repeatInterval" value="0"/> 
  <property name="repeatCount" value="1"/> <!-- run once for testing -->  
If you're using Maven, placing the "runtime" jobConfig.xml in src/main/resources and the above file in src/test/resources Just Works - and you've proven your Spring wireup is correct. Lovely.

Tuesday 12 October 2010

*Facepalm* Moments, Part One

Self-defeating updates

My gig at the satellite-vehicle-tracking company was an interesting experience. A great deal of stuff was seat-of-the-pants, looks-like-it-works-ship-it kinda software because the CEO had put his house on the line and every week we didn't have a solution put him a week closer to being homeless.

Corners were cut. Unit and integration testing was non-existent. As soon as a (flaky as hell) Version 1.0 was in the wild, we operated in what The Daily WTF calls a Developmestruction environment. Our production server was a Windows Server 2003 box that was infected with so many trojans that Internet Explorer took minutes to start up - but we couldn't afford to clean it and reboot in case it never came back.

Good times, good times ;-)

Anyway, the subject of this classic *facepalm* moment from my career is actually the embedded code that ran in the little boxes that got installed underneath car dashboards. It was pretty standard embedded C code - malloc() was banned, circular buffers ruled and everything ran off a gigantic while(1) loop in main.

The firmware actually worked pretty well. I'd managed to iron out all the tiny leaks that caused it to die when left to run overnight, and it dealt nicely with all of the weird and wonderful failure modes the attached GPRS modem could throw at it. (We had a simple serial link to the modem and treated it just like a standard dialup device, firing AT commands to it, setting up a PPP link and resetting it whenever the dreaded NO CARRIER message arrived - which was a lot, GPRS was pretty sketchy in Australia way back in '03). We'd gone through a couple of major version increments, adding some good features and desperately trying to tidy up the code as we went along, when we got to The Big One. Over-The-Air Firmware Upgrades. I had privately always thought that this feature should have been in the code since version one, but apparently there were always more lucrative things to add. I digress.

The process was pretty simple. We'd point the server-side code at a binary file and it would slice it up into packets using our proprietary protocol that ran on top of UDP, firing them one-by-one to the target device. Upon reception of a packet, the device would run a rudimentary checksum over it and ACK or NAK the segment - a NAK triggering a resend. If the segment had arrived intact, it would be copied out to flash, as there wasn't enough RAM to hold the entire firmware image. Once this extremely tedious process was complete (we'd typically push through about one packet per second, and the download used 200+ packets, with probably one-in-ten needing a resend), the box would run another checksum over the entire firmware image before firing off a special processor-specific machine code incantation that caused it to reflash itself and reboot.

So I'm attempting the first-ever over-the-air download with the aforementioned CEO (who designed the process on the back of a napkin) and things are going pretty well until we get to packet 189 of 220, at which point the device seems to lose all connection with the outside world and reboot its GPRS modem. "Oh well," we say "these things happen, let's kick it off again". Four-plus minutes later, the download dies again at packet 189. We go over the obvious possible causes in the code. There's nothing special about the number that would cause an overflow. There's plenty of flash memory left over. All of the circular buffer pointers look sensible. But because the flash-writing process is somewhat finicky, we're loath to attach a debugger and possibly introduce more weirdness. We're working almost entirely in the dark.

On a whim, I decide to fire up Ethereal (as it was then, now Wireshark) and inspect the packets my development box was sending to the device. And sure enough, we find the culprit lurking in packet 189:

    63 64 41 54 45 30 41 54 48 30 45 51 56 31 45 54    cdATE0ATH0ATV1AT 

    4D 30 4E 4F 20 43 41 52 52 49 45 52 41 54 44 54    M0NO CARRIERATDT

Yes, we'd got to the symbol table in the firmware binary, and the device code that was constantly scanning the receive buffer for "NO CARRIER" found exactly what it was looking for, promptly resetting the GPRS modem.


Friday 8 October 2010

The Weird Ways People Do Things

Part 1 of a Potentially Infinite List

Not much time today, so a quick one. I was shoulder-surfing/pair-programming with a very experienced Java EE developer the other day and watched in (silent) amazement as he performed an int-to-String conversion like this:

  methodThatExpectsAString("" + numThings);

I hadn't seen that idiom used since my university Java 1.0 days!

In most modern, typed languages these kinds of conversions are so frequent that they are semi-automatic to type (I often find myself typing valueOf when all I really meant was value!) - so why is it so hard for people to know and use the library methods that have been in the language since Day One? You only have to search for Java integer to string to see how many people don't know stuff that's covered in the Java Tutorial that immediately follows the "Hello World" demo.

To be fair, my keystroke-saving colleague is actually using the very first int-to-String technique outlined in the aforementioned tutorial. I just prefer the more explicit statement of intention offered as an alternative:


Oh well. As my Great Uncle Bruce used to say; it's all part of life's rich tapestry...

Tuesday 5 October 2010

Sometimes You Don't Even Need Eyes

Part Two: Organisational Odours

In Part One we looked at things you might be able to pick up in an interview that can steer you away (or indeed towards) a potential employer. Let's assume that the first interview uncovered no great horrors, and this time, you've been called in for "a chat with HR" , the next part in the gruelling multi-part process that is hiring in a quality organisation.

  • Are you being hired due to a sudden outflux of developers? If so, why?
  • How is the company structured? Wide and flat? Fiercely hierarchical?
  • What's the deal with developer PCs? Is it open-slather, run-whatever-you-like, or a fully-locked down corporate SOE where you'll need to ask a sysadmin to get Java installed?
  • How is the team/department/whatever structured? Are there lots of people with "Architect" in their name?
  • Does the only "upwards" career path require "promotion" to management? Only badness can come from this

Most software developers, if given a choice, will reject the stereotypical "corporate culture" of organisation charts, ineffectual middle-management and communication-by-PowerPoint presentation. Every potential employer exists somewhere on the spectrum between sandal-wearing open slather and six-minute-increment corporate bureaucracy; we just have to choose where we want to play.

Friday 1 October 2010

Currently Reading: Continuous Delivery

Misleading name; good stuff

I'm currently ploughing ("plowing" in the US) through Continuous Delivery - Reliable Software Releases through Build, Test, and Deployment Automation by Jez Humble and David Farley. Don't be put off by the name, this is emphatically not about some crackpot scheme of auto-deploying your project into production straight out of the back of your CI server.

Rather, it details the current best practices for getting software reliably passed through a "deployment pipeline" that starts with version-controlled source code and ends in a simple Deploy/Undeploy switch on your production server.

Humble and Farley have a ton of "war stories" that most emphatically prove they are not naïve about the spectacular and not-so-spectacular ways real-life deployments can fail, and their "staged software delivery" approach will definitely improve your processes, even if you only adopt one of their myriad recommendations. It is fairly programing-language-agnostic, but does tend towards giving code examples in Java, with the bulk of low-level advice aimed at Java and C# developers - a fair assumption given their marketshare and ease of comprehension.

This book is a member of the Addison-Wesley / Martin Fowler "Signature Series", a collection that I am rapidly growing to love. They neatly address the slice of the market that fits into the techy-book spectrum here (I'm using made-up titles but you'll recognise the patterns):

  • High-level - conceptual, diagrammy
  • Architecting Stuff - Buzzword, XML, Buzzword, SOA
  • Martin Fowler "Signature Series"
  • Write Code Properly - By someone who really knows what they are talkin' bout
  • Big Enterprisey Thing - Explained, one module per chapter
  • Learn Language X/Library Y - comparing it to others you already know
  • Cram This! - to pass your exam or hack together something for your uncle
  • Low-level - copy-and-paste coding

Highly recommended.