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 :-)