Monthly Archives: June 2014

Some decisions are hard to change.

Ever built a desktop tower PC from components? Or ever upgraded a tower PC?

What’s the easiest component to change?

Trick question.

You were thinking “RAM” right? Man you can unclip one of those little silicon buddies and snap a beefier one in place in less than a minute. Once the case is open.

No, not RAM.

How about your USB memory stick. That’s pretty easy to change. If you don’t use one, how about your mouse? Or headphones?

Okay we’re thinking outside the box here. What about software? Ehhh not as easy as headphones. Oh how about the user!  Well unless your password is “123456”…

I’m going with headphones.

Right so now you’re ready for the real question. What’s the hardest component to change?

You’ll be looking for trick answers now, this is good.

The desk? Heh, nice outside the box thinking – yeh that’s hard to change. Pretty much have to unhook and move everything to get that thing shifted.

Motherboard? Getting warmer. But come on, that’s obvious.

No. What I’m thinking about is
The case.

The case is an interesting little beast. It does one job and does it well. It keeps things that should be inside the box inside it; things that are outside outside. But while doing that it also provides external ports for headphones, mice, keyboards and monitors; it provides internal fixings for the motherboard, dvd drive, power supply, sound card and so on.

But the really nice thing about the case, is that if I go and sit at your computer with my headphones, I don’t need to give a damn about what is inside your case. I just plug my headphones in, put on your music and I start changing your desktop background.

And the other really nice thing about the case is that if you want to start swapping out components – your hard drive could stand to be a bit bigger – you can just swap that out. And no-one needs to care what is outside your case.

Your case makes things easy to change.

Except the case.

Its hard to change the case, because its busy making everything else easy to change.

I’m not just talking about swapping your case for another case.  Could you actually swap your case for something that wasn’t a tower case but solved the same general problem?

Well sure you could but you might need to redesign the bits that fitted inside it.  Laptop cases have many of the same features.  Server racks solve a similar problem.  Once you’ve decided on a tower PC case, you can swap any of the bits inside and out but changing it into a laptop is a tall order.

The case is a real world example of a design pattern at work.

Software design patterns are common solutions to common problems.

Hey I need to be able to get an instance of an object… but I don’t really care if that object is a derived type or not – I shouldn’t be the one making that decision… and I don’t want to think about how that object is constructed.  Maybe you want a factory pattern?

I need an action performed for me.  I know what kind of inputs I’ll have every time, but I really don’t know what the content or algorithm of the action will be. I just need to know I can invoke it and it’ll behave consistently as far as I’m concerned whatever other stuff is really going on inside.  Sounds like a strategy pattern.

The thing about design patterns in software is that they make /some/ things easy to change, both in terms of implementation behind the pattern, and the consumers in front of the pattern. But once you’ve decided on a design pattern, the pattern itself becomes hard to change.

So every use of a pattern is a trade off. You say “I’m going to sacrifice being able to change this later – because I want to be able to change that instead.”

In the GoF Design Patterns book, each pattern is described alongside what it makes easy to change. The trade off is the pattern itself.

So what am I saying – are patterns bad?

No. Clearly.

They’re not good either. Design patterns are a tool. Effective programmers may be more effective because they use design patterns effectively, in context, and with knowledge of what is being traded.

Ineffective programmers may be ineffective because they don’t know about design patterns and so don’t apply them.

Seriously ineffective programmers – well they might know some patterns and apply them blindly and inappropriately – like a confused plasterer in a new house, with every floor, ceiling and wall tiled painstakingly carefully in mellow blue and green colours. “I worried it might get wet,” they say, “so I copied this thing I saw in a swimming pool once.”

Specification by Example – show, don’t tell.

CLIENT: And then you just take the base policy payment, perform a look up against the user’s postcode and apply a crime risk multiplier. And that gets you the initial monthly premium for the policy.

DEVELOPER: (Writing as he talks) So we’ll need a feature definition that says,
GIVEN I live in Canvey Island,
WHEN I apply for insurance,
THEN the monthly policy premium should be the base premium multiplied by the appropriate crime modifier for my postcode.

CLIENT: Exactly!

TESTER: Gosh that sounds complicated.

DEVELOPER: Oh come on it’s just one sum! There’s nothing else to it.

TESTER: I don’t suppose you have a real life example?

CLIENT: Sure. (Opening a complicated looking spreadsheet.) So, say I live in Canvey Island. I’ll need a specific postcode. We can use SS89YJ. So I put that in this box on the spreadsheet and I get the premium here. And here is the crime multiplier for the postcode, see?

TESTER: That doesn’t seem to add up.

CLIENT: We talked about the floods insurance multiplier already – didn’t we?

TESTER: No problem, lets figure it out in stages.  I’ll take the numbers we used in the spreadsheet calculation.
GIVEN I live in SS89YJ
AND the postcode crime multiplier for SS89YJ is 0.10
AND the flooding multiplier for SS89YJ is 0.15
AND the base premium is £10.00
WHEN I apply for insurance
THEN the monthly policy premium should be £12.50

DEVELOPER: Gosh that sounds complicated.  Do you suppose we should get some more examples, in case we missed something else?

How to spot the Tautological Test Anti-pattern

When I was starting out with TDD, it took me a while to figure out how important it is that my tests should be clean of any logic.  I remember one time I wrote a test that was supposed to check a method for calculating the net total and tax on an invoice, which duplicated the code it was supposed to test.

When it turned out that something had been missed, my test hadn’t protected me at all.  And it was a pain to rewrite!

I’d have been better off taking an example of one of my client’s handwritten invoices, and turning that into a test.  Then I could just keep coding until my results agreed with theirs.

It’s easy to write tests that don’t protect against errors in your assumptions. Until I recently spotted a bunch of tests that had this problem, the best advice I could give to junior devs was: “Ehhhh this feels wrong.”

If we want to move beyond “feelings” and toward encouraging best practices for our whole team, we’ll need a language to describe the problem, and a way of spotting it at code review.

Suppose you are reviewing the test for a “Sum” method, intended to add two numbers. You put in A and B, and it gives you the sum A + B.

Unfortunately our coder has got the code wrong. They’ve added A + A in their method and in their test. Their test passes because it is a copy of the code-under-test.

public class Calculator
{
    public int Sum(int inputA, int inputB)
    {
        return inputA + inputA;
    }
}

[TestFixture]
public class CalculatorTests
{
    [Test]
    public void Sum_Test()
    {
        var inputA = 1;
        var inputB = 3;

        var result = Calculator.Sum(inputA, inputB);

        var expected = inputA + inputA;

        Assert.AreEqual(expected, result);
    }
}

The first issue is that the test is incorrect; it can only pass if the Sum logic produces an incorrect answer.  The fact that it does pass means that the code it is testing is wrong too!  But this isn’t the lesson you want your reviewee to take away.

How did the bug get there? Why is it hard to see?

The test is tautological.

Which means it repeats the essence of the code it should be testing.

That test should never have included a calculation to get the value of the ‘expected’ variable. That makes the test as complicated as the method it is testing – ask the developer – Are you really going to write supertests to check the logic in your tests?

In The Art of Unit Testing, Roy Osherove warns the reader to “Avoid logic in tests”. He gives examples of loops, ifs, threads and so on as things to avoid. I would go much further than him in this regard.

Here’s some advice that would have helped me when I started out:

  • Never calculate an expected value to check against within your test. This is almost always duplication of the production code you are trying to test.
  • Logic driving the assertions in your test code is always a smell – if the WHEN step of your test doesn’t require the logic, then you can guarantee that your THEN step is doing too much.
  • Always work from real examples whenever you can. Seek a stakeholder who can provide concrete examples, or if you have no other choice, prepare your data by hand – not automatically.
  • Never write test code that assumes it knows how the method under test should be implemented – that is what we mean by tautological tests, and the sooner you can recognise them, the better.

Read more about tautological tests and why testing using mocks is like serving your Friends sauteed beef in custard and sponge cake.