Monday 28 February 2011

Tidier Varargs, part 2

Last time we looked at how we could tidy up code that deals with a single, possibly-null varargs parameter. But of course there are lots of cases where the business rule is an "at-least-one" scenario.


An example of a real API that operates like this is the mighty Mockito's thenReturn method, which looks like this:

OngoingStubbing<T> thenReturn(T value, T... values)

Which is typically used to define mock behaviour like this:

Mockito.when(
    mockCountdownAnnouncer.getCurrent()).thenReturn(
        "Three", "Two", "One", "Liftoff");

The nice thing about this is the "fluent" way you can add or remove parameters from the list, and it just keeps working - as long as you've specified at-least-one return value.


This kind of API is really pleasant to use, but it'd be doubly great to have clean code within methods like this. The VarargIterator needs some extension!

    
    /**
     * @return an {@link Iterable} of a suitable type.
     * Null-safe; passing a null {@code optionalArgs} will simply return
     * a single-element {@code Iterable}.
     * @throws IllegalArgumentException if {@code compulsoryArg} is null
     */
    public static final <T> Iterable<T> forCompulsoryAndOptionalArgs(
        final T compulsoryArg, final T... optionalArgs) {

        Validate.notNull(compulsoryArg,
            "the first argument to this method is compulsory");
        if (optionalArgs == null) {
            return Collections.singletonList(compulsoryArg);
        } else {
            List<T> iterable = new ArrayList<T>(optionalArgs.length + 1);
            iterable.add(compulsoryArg);
            iterable.addAll(Arrays.asList(optionalArgs));
            return iterable;
        }
    }

As you can see, we encapsulate null-checking and null-safety in this method, allowing users to simply write (with a static import in this example):

    public OngoingStubbing<T> thenReturn(T value, T... values) {

        for (T retValue :forCompulsoryAndOptionalArgs(value, values)) {
            // Do Mockito magic with each retValue
        }
    }

Mmmm. Squeaky-clean!

Friday 25 February 2011

Tidier Varargs, part 1

One of the less-appreciated of the many massive improvements made to Java in version 1.5 was varargs, aka those little dots that are syntactic sugar sprinkled onto a strongly-typed array:

    public static void printAllOfThese(String... things) {
        for (String thing : things) {
            System.out.println(thing);
        }
    }

It goes hand-in-glove with the enhanced for loop. Very tidy. Except what happens when I inadvertently do this:?

   printAllOfThese(null);

You probably correctly guessed: NullPointerException at line 1 of printAllOfThese - yep - sadly, the enhanced for loop is not null-safe. What we really want is for a null argument to be silently ignored. So our previously oh-so-tidy, oh-so-readable varargs method ends up needing a null-check wart:

    public static void printAllOfThese(String... things) {
        if (things != null) {   
            for (String thing : things) {
                System.out.println(thing);
            }
        }
    }

Ew. That's ugly, and in turn requires more test cases. There has to be a better way, but amazingly, I couldn't find any solution in the usual common libraries. So, somewhat reluctantly (because if premature optimisation is the root of all evil, then wheel-reinvention is surely sudo), I present the VarargIterator helper class:

public class VarargIterator {

    /**
     * @return an {@link Iterable} of a suitable type. 
     * Null-safe; passing a null varargs will simply return
     * an "empty" {@code Iterable}.
     */
    public static final <T> Iterable<T> forArgs(T... optionalArgs) {
        if (optionalArgs == null) {
            return Collections.emptyList();
        } else {
            return Arrays.asList(optionalArgs);
        }
    }
}

This allows us to rewrite our printAllOfThese method very neatly:

    public static void printAllOfThese(String... things) {
        for (String thing : VarargIterator.forArgs(things)) {
            System.out.println(thing);
        }
    }

Next time: Elegantly dealing with compulsory and optional elements.

Tuesday 22 February 2011

In The Beginning ...

... There were packets. And They Were Good. Our data was ritualistically encoded into fields and offered unto the network, and with much latency and the occasional sacrifice, was reassembled in hopefully-the-right-order on the other side. We gave thanks to the Internet Elders for this.


And then Wise Hackers realized you could just memcpy() thine C data structure into thine transmit buffer. And it too was good. For marshalling and unmarshalling data to-and-from arbitrary formats is surely the devil's own drudgery.


But lo the Enterprise Architects did speak. And speak XML they did. And they spake that XML was all that any shall speak. And so (for fear of being struck down by these mighty warriors), we encoded our data once more, this time in a verbose form so that those heathens who should sniff the wire should sniff many an angle-bracket and naught of any interest.


But the hackers did once more rise again and thus the prophet Json was begat. And he was good, for he was once more a literal representation of The Word. And there was much rejoicing amongst those who had lived in the shadow of the Architects.


And so it is that what was once old is new again, and what was once bad is now good. And this cycle shall go on for eternity.


Like an Enterprise Architect.

Friday 18 February 2011

Welcome to Stand Up

Ah dammit I was going to do the Fight Club thing but I've just remembered that the Secret Geek beat me to it.


Never mind. But there are a few additions I could make to that excellent list:


  • You really do have to stand up. It speeds up the process
  • By all means talk fast, but please talk loudly too - don't mumble!
  • If you worked with a team-mate yesterday, mention them; but;
  • Don't cover what somebody else already has. You don't HAVE to increment your awesome-quotient each and every day. Just "pass", optionally referring to the prior speaker
  • Use a "talking stick" or other such binary semaphore to ensure exactly one person is speaking at a time
  • Invoke the talking stick on anyone who violates the semaphore - either metaphorically (he who talks out of turn has to fix the next build breakage) or literally (you'll need a pretty chilled OH&S policy here!)
  • Change things up by throwing the talking stick randomly around the circle so people pay attention
  • ANYTHING controversial is taken "offline"
  • No Agendas, Minutes or Action Items

Tuesday 15 February 2011

Zero-to-coding-hero in 5, 4, 3 ...

Improving the new-starter experience - Part 2

Continuing on from last time, let's assume you've managed to rustle up a desk, chair and network-connected PC for your new starter in software development. What's next?


In my experience, typically a good two days are wasted watching progress bars dawdle across screens - downloads, installations, setups, checkouts, plugins, pah! This has always seemed like a right-royal waste of time to me. Firstly, by installing "the latest version" of Java/Eclipse/whatever the new starter is almost certain to differ in some possibly-important way from the other developers' platform configurations. Secondly, downloading anything off the internet will always be slower than copying it from the local network.


Here's what I propose, which should have a newbie eyeballing the codebase within minutes of logging in:

  • Step 1. Install a virtuali[sz]ation environment. I'm a big fan of VirtualBox OSE on the Ubuntu desktop, but really, anything will do
  • Step 2. Copy a "developer's disk image" (aka "one I prepared earlier") from a network drive onto the local disk - anywhere you like really. This is a bit-for-bit copy of a fully-working desktop development environment:
    • OS
    • Java - the standard version for your site
    • Eclipse with all appropriate plugins
    • Tomcat
    • Database with JDBC drivers
    • A known-good (if old) source tree
    • etc
  • Step 3. Launch the image. On a modern PC, the performance hit of running under virtuali[sz]ation is so minimal as to be insignificant


Now wasn't that easy? Of course it will take a bit of work to set up that first "gold image" but it gets amortized over each new developer's immense time savings. The image can be kept regularly, if infrequently, up-to-date as a post-release action. A quick source-control update, and the new starter is ready to actually start! Huzzah!

Friday 11 February 2011

Zero-to-coding-hero in 5, 4, 3 ...

Improving the new-starter experience - Part 1

Another new contract, another interesting getting-set-up experience. Let's break down what a developer needs in order to be a productive team member at a new site - firstly, basic/physical items:


  • An Access Pass/Code that allows ingress/egress to the place of work.
  • A Desk and a Chair, preferably close to their new team, if not right in the middle of it
  • A PC with a Functional Network Connection - note an OS is not necessarily required, but a valid IP address certainly is
  • A network login with an email address - something that can at least get through the (inevitable) corporate proxy and receive internal emails

So what can go wrong? Well, the paperwork for the new starter might not have come through or perhaps it's not clear what access the developer needs. A temporary access pass should be sufficient for the first week or so.


Desks and chairs can frequently be in very short supply - if a team is "skilling-up" there won't be a recently-vacated workstation so a degree of flexibility is required in accommodating the newbie. It's extremely important that they can be sited physically close to their team, in particular the most experienced/technically-strongest member(s) so that questions can be fielded quickly and efficiently.


The PC is probably the most interesting point. At my new site they allow developers to set up their PCs any way they like - although practically the OS choice seems to have boiled down to Windows or Ubuntu. This is impressively open - they are trusting that a developer will either not mangle their machine OR that they will be able to fix it if they do!
Of course it's also quite likely that a new starter will be taking over an ex-employee's PC. In that case it would be insane to blow away a known-good configuration.
The other likely (although least-developer-liked) option is a new locked-down, corporate-imaged desktop PC. The same one given to sales drones, secretaries and Milton from Accounts. This can be a real pain if the installing developer tools requires extra privileges! Which brings me to:


The network login - it can take a while to materialise from the bowels of IT. A nice advantage I had with my fresh Ubuntu installation was the complete independence from the corporate Active Directory, Windows domain malarkey. My login arrived a good 24 hours after my PC - but I already had a full Java development environment configured in the meantime, complete with root access. When the login arrived I just put the cherry on top - getting Evolution to access my email account.


So what would be the policy in my Optimal Office ™?

  • There should be a pool of Guest Access Passes at the front desk. These will be replaced as soon as possible with properly-customised access cards for new starters
  • Each team "pod" should always have a spare desk, chair and (possibly-unconfigured) PC available. That way a new starter can hit the ground running. The next desk/chair/PC combo should be ordered/allocated as soon as the new hire is confirmed
  • I certainly wouldn't have a Windows-based network so I'd be advocating Ubuntu desktops all around. They're free, install quickly, support any hardware, you can set them up without knowing any network credentials and there's tons of help available on the net

Tuesday 8 February 2011

This One Goes Up To '11

... back for another big year

Happy belated New Year!


As promised/threatened, I'm back in the blogging seat for another year. My new contract has started and I'm getting nicely into the thick of things, but there have been a few niggles that I've been thinking about - my OptimalOffice™ tag will be getting more of a workout soon!


At some point fairly soon (perhaps coinciding with the release of the next Ubuntu Server version in April) I plan on embarking on what I will modestly title The Ultimate Continuous-Integration Server Setup Guide - which will be pitched at the developer who wants a Really Nice Build Environment - no prior system admin experience required! No doubt it'll be a monster, with gotchas galore, but hopefully it'll save a few follicles out there somewhere.


Hope you'll join me for another exciting year in modern software development.