Tuesday, 28 September 2010

Good Hiring: Make Me Work, Not You

Pipelining the interview process

"'Tis far better to reject a good candidate than to mistakenly hire a bad one" should be tattooed on the inside of the eyelids of everyone involved in the hiring for a software development position.


For this reason, the interview process simply must be gruelling. Because of this, you're going to get a lot of candidates passing through (and failing), so the process should be pipelined to minimise the disruption to people involved. Here's what I mean:


Stage 1 is where résumés are received from external sources and vetted by a technical person with a vested interest in choosing a real superstar - i.e. a future team-mate. They should spend no more than a couple of minutes perusing a CV before it goes to the go/no-go decision - you're looking to filter out obviously-weak candidates based on skills, results, and general résumé class. Be ruthless; remember we're looking for people who are Smart, and Get Things Done - CV spelling mistakes immediately rule them out on the first clause.


Stage 2 MUST be a technical test. A killer. Candidates should come out drenched in sweat, with little drops of blood on their forehead. Test that they think like a programmer, not just copy-and-paste code snippets from the web. Test that they really know the language(s) they profess to be good at. Test they understand and can apply a design pattern - and not just Singleton. Look for methodical working, an awareness of side-effects, and evidence that even though they will probably be using pen-and-paper, they are writing clean, maintainable code - because they do it so much it's just unconcious.


Stage 3 - immediately after Stage 2, two employees (again with a vested interest in picking a superstar) go over the answers. Only if things look really, really good do you ask the candidate to explain a few things about their answers. Otherwise, they get shown the door. There is no point wasting time getting someone to explain why they are searching for something by iterating over a List when a Map is the obvious solution.


By Stage 4 things are looking pretty good. Your candidate can talk the techy talk and walk the techy walk. It's time for HR to give 'em a grilling and make sure they can talk to "normal" people, and that they are on the right page with regards to salary expectations and so on. Be aware that HR people are shockers for mistaking "borderline insane" for "very enthusiastic" - so it's a good idea to have a technical person sit in on this interview (even if they never say a word) as a sanity circuit-breaker. Very few people will get to this stage so it shouldn't be too much of a time-sink.


Stage 5 is where you can bring the candidate in one last time and actually introduce them to the team and the project. Draw the system diagram on a whiteboard, and watch for light-bulbs going off behind the candidate's eyes. "POW! I've never used that before, but I've always wanted to!" "ZING! That's a really nice way to solve that problem!" "BANG! I think there might be a better way to handle that!". By the end of the meeting they should be talking like they are a fully-fledged team member.


And if so, then they should be one.


Thursday, 23 September 2010

Unit-Testing Time-Oriented Code

Part 2: Are We There Yet?

The counterpoint to actively forcing the current thread to wait is checking whether a certain amount of time has elapsed. Unit-testing code like this is a similar challenge; we certainly don't want to have to sleep() in our unit tests in order to verify our code - we have better things to do with our (and our processor's!) time.


Let's look at a typical (if contrived) bit of time-elapsed-measuring code:


  public void sendRequest(Packet packet, int slowThresholdMillis) 
                throws ExcessiveLatencyException {
    final Date sendTime = new Date();
    networkInterface.sendAsynchronously(packet, new AckCallback() {
      public void ackReceived() {
        Date ackTime = new Date();
        long timeTaken = ackTime.getTime() - sendTime.getTime();
        if (timeTaken > slowThresholdMillis) {
          throw new ExcessiveLatencyException(timeTaken);
        }
      }
    }
  }

Now clearly we need to be able to cover that "took too long to respond" path in our unit tests. Of course we could pass in a negative value of slowThresholdMillis but that's not really a realistic situation, and indeed a requirement will probably come along to validate against non-negative and non-zero values for that parameter.


Again the solution is to refactor out the parts which are currently hard to unit test. As a side-effect we'll probably get a much cleaner sendRequest() method - I've certainly never liked seeing all that millisecond-twiddling sitting alongside higher-level abstractions like networkInterface.sendAsynchronously()!

What we need is commonly known as a Stopwatch component, and given there are several proven implementations to choose from, there's absolutely no need to re-invent the wheel here.


Let's go with the Spring implementation because we've almost certainly already got it in our classpath:


public class RequestSender {
  private static final StopWatch DEFAULT_STOPWATCH = new StopWatch();
  private final StopWatch sw;
  
   public RequestSender() {
    this.sw = DEFAULT_STOPWATCH;
  }

  /** Package-visible for unit testing */
  RequestSender(StopWatch stopWatch) {
    this.sw = stopWatch;
  }

  public void sendRequest(Packet packet, int slowThresholdMillis) 
                throws ExcessiveLatencyException {
    sw.start();
    networkInterface.sendAsynchronously(packet, new AckCallback() {
      public void ackReceived() {
        sw.stop();
        if (sw.getLastTaskTimeMillis() > slowThresholdMillis) {
          throw new ExcessiveLatencyException(sw.getLastTaskTimeMillis());
        }
      }
    }
  }

Notice how a minor refactor for testability has already improved the code - we've saved a line and delegated off some drudgery to a reliable third-party library. I've gone for a constructor-injected approach here for two reasons, namely that having a StopWatch is essential to the correct operation of the class - and I would say the same for the (elided) networkInterface collaborator, and secondly, it gives a straightforward way to ensure that sw is final so I can use it in the ackReceived() callback. All that remains now is to mock the StopWatch implementation in our unit tests so we can exercise all the paths through the code:


public class RequestSenderTest {
  private RequestSender testInstance;
  @Mock
  private StopWatch mockStopWatch;

  @BeforeMethod(groups="unit")
  public void setup() {
    MockitoAnnotations.initMocks(this);
    testInstance = new RequestSender(mockStopWatch);
  }

  @Test(groups="unit", expectedExceptions=ExcessiveLatencyException.class)
  public void checkLargeLatencyThrowsException() {
    Mockito.when(mockStopWatch.getLastTaskTimeMillis()).thenReturn(200);
    testInstance.sendRequest(mockPacket, 100);
  }
}

Tuesday, 21 September 2010

Unit-Testing Time-Oriented Code

Part 1: Sleepy Time

Every now and again, we come across a need to write code that is time-sensitive. It could be as simple as waiting a certain period before timing-out a request, putting a pre-delay in an autocomplete control, sending a rapid-fire chatter of calls, or measuring performance of some other aspect of the system. In all these cases, unit testing can be a real pain.


We all want our unit tests to run as quickly as possible; if it takes longer than a couple of tens of seconds to run, we'll potentially lose focus, switch to browsing the web and get distracted, or worse yet, not run the tests at all. But if the unit tests for our time-sensitive classes take real-time amounts of time to run, we could be looking at enormously time-consuming test runs (imagine running a suite of 10 or more tests where "timeout after 30 seconds" is the expected outcome!)


The solution is of course to somehow mock out the code that requires or takes time to execute. In effect, we want a mock that lets us "fast-forward" time. Let's first look at the classic naïve way to "wait a bit" - sleep:


  public void sendPings(int numberOfPings, int delayMillis) {
    for (int i=0; i<numberOfPings; i++) {
      sendPing();
      waitForMillis(delayMillis);
    }
  }

  private void waitForMillis(int millisToWait) {
    try {
      Thread.sleep(millisToWait);
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
    }
  }

How can we fully test the sendPings() method without incurring the time cost of waiting between pings? Well, we could of course only test with very small values of delayMillis, but that's still going to take a bit of time. Let's look at our overall aim for unit-testing sendPings:

  • We'd like to mock out the actual pinging mechanism so we can count how many times it was invoked - hence checking our for-loop logic
  • We'd like to verify that the sleeping mechanism is correctly told to sleep for delayMillis
  • We can pretty-much trust that the Java sleep() method works as advertised
  • We don't want to actually wait numberOfPings times delayMillis milliseconds in order to see if a certain combination works

What we need to do is classic Refactoring, classic Clean Code, classic SRP, classic Design Patterns, classic OO, you name it. We extract the waiting mechanism into a class that is solely concerned with waiting:
  public interface WaitProvider {
    void waitForMillis(int millisToWait);
  }

  public class ThreadSleepingWaitProvider implements WaitProvider {
    public void waitForMillis(int millisToWait) {
    try {
      Thread.sleep(millisToWait);
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
    }
  }

So now the interesting bits of our pinging class under test look something like this:
public class PingSender {
  private static final WaitProvider DEFAULT_WAIT_PROVIDER =
    new ThreadSleepingWaitProvider();
  private WaitProvider waitProvider = DEFAULT_WAIT_PROVIDER;

   public void sendPings(int numberOfPings, int delayMillis) {
    for (int i=0; i<numberOfPings; i++) {
      sendPing();
      waitProvider.waitForMillis(delayMillis);
    }
  }
  
  void setWaitProvider(WaitProvider newWP) {
    this.waitProvider = newWP;
  }
}

Thus, our default behaviour is still to use the Thread.sleep() mechanism, but we can substitute a mock WaitProvider to speed up our unit tests. We just use the package-visible setter:
public class PingSenderTest {
  private PingSender testInstance;
  @Mock
  private WaitProvider mockWaitProvider;

  @BeforeMethod(groups="unit")
  public void setup() {
    testInstance = new PingSender();
    MockitoAnnotations.initMocks(this);
    testInstance.setWaitProvider(mockWaitProvider);
  }

  @Test(groups="unit")
  public void checkDelayIsPropagatedToWaitProvider() {
    testInstance.sendPings(3, 333);
    Mockito.verify(mockWaitProvider, Mockito.times(3)).waitForMillis(333);
  }
}

And so on and so on ... Note that I am not suggesting for a minute that the unit tests using the mock WaitProvider are the only testing that should be done on PingSender. There should be a full set of integration tests which use the "default" provider with reasonable (if short) delays specified, and possibly even a further set (perhaps annotated appropriately) that use relatively large delayMillis values.


In the next installment, we'll look at unit testing the situation where rather than waiting for a set time, we need to test whether a certain amount of time has elapsed.

Friday, 17 September 2010

Methods Should Be Wider Than They Are Long

A New "Clean Code" Mantra

I'm a huge fan of Robert C. Martin's Clean Code handbook. While most of the recommendations are of the head-nodding "of course, been doing that for ages" ilk, a few of the solutions offered have been genuinely outstanding for improving the readability of the code I produce.


Here's just one example. Uncle Bob is all about the Short Method - and I'm totally with him on that one. Short methods neatly sidestep so many of the readability issues we often find when scanning code - be it someone else's or our own. It's pretty hard to get into a major stylistic battle with a "only ever one return statement" purist when the entire method is 5 lines long. But I digress. The issue I'd always had with Short Methods was where to put all of them. Say you have a class with 3 public methods, and 5 private methods that actually do the work. Do you structure your source file like this (classic C++ access-level ordering):

public methodA()
public methodB()
public methodC()
private methodD()
private methodE()
private methodF()
private methodG()
private methodH()

Or do you put called methods immediately after their caller?

public methodA()
private methodD()
private methodE()
public methodB()
private methodF()
public methodC()
private methodG()
private methodH()

But how should you arrange things when (private) methodF() is called by all three public methods, and methodD(), a private one?


My classes were a bit all-over-the-shop in this respect. I'd never really hit on a strategy that kept that uppy-downy scrolling through source files to a minimum. I'd get especially annoyed during debugging sessions in Eclipse - with all of the extra views running, it felt like I was looking at the code through a mail slot, and my mouse's scrollwheel was going to wear out.


Uncle Bob's solution is simple but effective; just arrange the methods like a newspaper article - more detail emerges as you work down. Top-level methods that orchestrate others live at the top, with more nitty-gritty provided as you scroll down the file. When you've got well-named methods that are written with the "principle of least surprise" at front-of-mind, you find most of what you need is within half a screen of scrolling of your current point of interest.


It was while I was refactoring a unit test with Uncle Bob's wisdom fresh in my mind that I realised I could combine three of his top tips into one new maxim. Take the recommendation that your methods should be short, combine with Single Responsibility Principle that a method should do one thing only, and add the fact that in today's age of modern languages and widescreen monitors, a method should have a long and meaningful name, and you get ...


Methods Should Be Wider Than They Are Long


Implicit in that commandment is that the method signature itself should be the longest line. Think about what you get if you honour this:

  • If any line of your method is longer than its signature, you've definitely got too much indentation going on (and therefore need to refactor out whatever is causing that)
  • As a counterpoint, if your method starts getting long, it's obviously doing more than the name suggests - and again it's off to Refactorville, population: You.
I like this mantra, and so far in my own code it's definitely panning out well. Try it for yourself!

Tuesday, 14 September 2010

Blog Style Overhaul

A CSS Metamorphosis

Over the next few days I'm going to be re-skinning this blog using a design from Open Web Design, a fantastic resource for real purdy CSS templates and lovely graphics.

I've always considered the story of web-page creation to have three tasks (to use Agile vocabulary):

  • Make it work
  • Make it standards-compliant (so it works everywhere)
  • Make it pretty
While I generally have no problem putting together functional, standards-compliant HTML and CSS, the "make it pretty" stage requires a skillset (and/or side of brain) that I am the first to admit I completely lack.

The design I'm starting from is called Colourswirls by Metamorph - the original design is here. I love the contrast and the crisp design, but it was a little too flowery for my taste, so I dropped the elaborate corner motifs. I also did a little bit of colourspace-tweaking to get the palette from light-blue into my preferred purple. For these tasks I always find myself turning to Paint.NET, the best .NET application I've ever seen in the wild - indeed one of the best Windows apps ever, and it's free. I've never quite got along with The Gimp, no matter how I try.

Hope you enjoy the new look.

Friday, 10 September 2010

Sometimes You Don't Even Need Eyes

Part One: Bad Interview Smells

Many years ago I owned a Subaru Impreza. A fantastic car, and one with a distinct aural signature courtesy of its flat-four engine. Ever since owning that car, whenever I hear that throbby rumble I know I'm about to spot another Subie. Of course these days, a lot of the boy-racers/ricers/tuners (substitute your local dialectical word here, you know the guys I'm talking about) choose to accentuate that noise with a comically-large exhaust system, which means I'll be able to picture the car I'm about to see even more accurately.


I've come to the realisation that software development teams can often be characterised/pre-judged in the same way. You can get a feel for what you'll be dealing with Without even seeing the code. Here are some questions to ask, and outright warning signs that Things Are Not Good, just maybe they'll save you in an interview one day:

  • They don't use source control
  • They do use "source control", but it's Visual SourceSafe
  • Who is the person interviewing you? Your future boss? Are/were they a software developer? A good one? Shoot back a question that will reveal if they're up to scratch technically. If they're not, you don't want to be there
  • "We've got/we had this guy, he's super-smart and he's [re-]written 90% of our stuff in [something bizarre]"
  • Find out how they document stuff like new-starters' guides and things like that; Wiki = good. Word Doc = bad
  • See if you can sneak in a question about the build process. Is there a CI build server? A build light? These things not only show how seriously the team takes the software development process, but also how willing management is to support them
  • You might be lucky enough to be led through the development area on your way to the interview room. Is it a cube-farm? Low-walled? High-walled? Glass offices? Is there a purposeful hush punctuated by the occasional techie-chat?
  • Are there numerous whiteboards with interesting-looking diagrams on them? Interesting diagrams (but not in the "WTF?" way) imply interesting discussions, implying quality colleagues

Tuesday, 7 September 2010

Cats and Dogs

When Tomcats and Puppies Collide

This blog is hosted* on what may be the (literally) coolest little app server ever. A completely silent, ultra-low power IBM NetVista N2200. My "production infrastructure" is the N2200 plus a NetGear home router; total power consumption is something in the region of 10W :-)


The little black box runs a copy of Puppy Linux 4 that's been heavily butchered (sorry for the mental image that may conjure up) to run in the 256Mb of RAM with the smallest possible footprint (currently about 180Mb free before starting any Java processes). No XWindows, Samba or CUPS, just a lean, mean, SSH-accessible server. A Tomcat 6 installation does the actual work. With only a single 233MHz core to play on, it's no speed demon to start up, but once running it's just fine.


One of the nicest things is that the whole kit-and-kaboodle sits on a small Compact Flash card that I can copy off and treat just like a "virtual machine image". I've got 5 more NetVistas just waiting for work (courtesy of eBay). After replicating my image to more cards, I could cluster these puppies!


The blog software itself is Pebble - after messing around for hours trying to get a Roller instance to work properly on an H2 database, what a pleasure it was to plop pebble.war into place and see it Just Work. Pebble looks like it supports everything I could ever want to do with this site, and allows extension into some very interesting directions. I'm hoping to explore some of these in future and hopefully contribute them back to the development.


What a great endorsement for free and open source software - a complete, secure and performant application server, running useful software, on a ten-year old low-power desktop worth roughly USD$15...

* Not any more actually :-)

Sunday, 5 September 2010

SotSoG 2010 Hall of Fame

Standing on the Shoulders of Giants

When I first moved back from The Dark Side to the world of Java, I was astonished at the vibrant software ecosystem that had grown up around Sun's baby. When I left the Java world at the end of the 20th century, the JDK 1.2 JARs were pretty-much all I knew.


Cut to 2005 and The Apache Project has gone ballistic, churning out libraries for just-about everything and an industry-standard servlet container. There are more app servers, JDBC drivers, XML parsers and webapp frameworks than be conceived by a sane mind, and SourceForge is hosting literally thousands more useful Java projects.


Some of the projects we all take for granted in the Java world represent many thousands of development and testing hours. Truly we stand on the shoulders of giants when our own projects succeed thanks to their hard work and generosity.

Some projects more than others really make Java development a pleasure, and hence I'm calling them out for the inaugural Millhouse Group SotSoG Awards (actual prize is nothing except a warm fuzzy feeling for those involved...)

  • The Spring Framework - Still the defacto IoC framework of choice, but that's really just the tip of the iceberg...
  • Apache Maven - Yes, it enforces a standard project layout. And that's the way I like it.
  • Eclipse IDE - A hulking great beast of an IDE. Plugins for stuff that hasn't even been thought of yet. And still totally free.
  • Apache Tomcat - Still my choice, and getting better every release.
  • Mockito - a lovely, fluent mocking API that itself stands on the shoulders of EasyMock!

All of these projects deserve their own blog posts, and will get them in time. But in the meantime, if you're not familiar with any of the above, Google them up and give 'em a go! Enjoy the view.

Saturday, 4 September 2010

A Tiny Bit About Me

A Human Stack Trace
Just for the sake of some context, here's my story.

Although born in the UK, I now reside and work in Melbourne, Australia - a thriving megatropolis with almost 4 million residents. Melbourne is Australia's second-largest city, after its arch-rival Sydney, and boasts a healthy IT sector, primarily in "the usual suspects" - banking, insurance, utilities, you know, that old chestnut.

I kicked off my career writing C and C++ for a very large, very well known IT multinational out in the suburbs. While this taught me lots about working in large codebases and using source control (we were on Rational ClearCase), after 3 years I moved down the road to a startup working on vehicle tracking.

Because I'd been working in communications testing, I was asked to develop the communications stack for an embedded device, allowing it to send GPS co-ordinates over GPRS and through the internet to a C# server-side listener (.NET version 1.0!) - which I also wrote.
As far as I know, my code (both client- and server-side) is still running faithfully some 6 years later. Who knows how many UDP/IP datagrams I have "fathered" in that time!
I'm keeping these companies anonymous at this stage, although given time I may write longer entries about some of these workplaces. We'll just have to see how libellous they turn out!

After a couple of years of hectic multi-hat-wearing startup antics, I switched to full-corporate suit mode for a few years, and came back to Java for the first time since my university days. Java had grown up a great deal since my last experiences writing applets in vi under JDK 1.2; working on Java 5 through the NetBeans IDE and deploying WAR files to Tomcat 4.1 was mind-blowingly awesome. Some might even say "insanely great". I was hooked.

Between 2006 and 2009 I was lucky enough to work in the UK, an experience that I greatly enjoyed. During my 3 years there I worked at three very different companies, but the common thread was that all were small startup-style companies, doing interesting, decidedly non-traditional work. And since returning to Melbourne as an independent contractor, I have sought out more of the same.

My career so far has very much been driven by my constant desire to keep learning new things. Typically this has meant moving jobs every few years, if not more frequently. While this might scare a lot of people, I feel that in software development we are lucky in that there will always be a need for avid learners, and that as candidates they stand out. By reading this blog, you're showing yourself to be an avid learner too. Nice job!

Friday, 3 September 2010

Howdy

Welcome all to The Millhouse Blog, an outlet for thoughts about software development in the 21st century, with a particular focus on the Java ecosystem.

These are "interesting times" (as the Chinese curse supposedly goes) indeed in the world of Java, but the community still has such a lot going for it - hopefully there's room for Yet Another Java Blog...