In my previous post I told about Mr. Work and pointed out that one of his tasks would be to fail fast and often. In this post I’ll explain why I would like to have him fail fast and often and give a fwe examples of code that examplifies this.
A lot of time is used debugging no matter if you have an Test Driven Approach to development or a more “I’m a supreme being and don’t make errors” approach you are going to debug at some point (and in the end even you will have to realize, you might be just semisupreme).
How much time you will spent on debugging, is in more than one way up to yourself. I have seen people that simply turned their back on all bugs saying that is was not their problem.
A very common scenario for this is when the problem is based in a different phase, than the one it’s realized in.
We might not be able to change how Mrs. and Mr. Work behaves to every one else but we can change how they behave to us. My Mr. Work has learn to report every error and do it fast, that is I always emphasize to my peers to write code so that unexpected situations are easily spotted. I find that having a function misbehaving because an expected state was miscoded, is usual easy to find and correct, whereas debugging a function misbehaving because of a state you didn’t expect is often a lot trickier.
Say we have an enumeration like this:
internal enum ZooAnimals{
Zebra,
Chimpanzee,
Tiger
}
and somewhere in our code we then use it in a method like this:
public bool CanEatOthers(ZooAnimal possibleHunter){
switch(enumeration){
case ZooAnimals.Tiger:
return true;
default:
return false;
}
}
and we have a unit test giving us 100% statement coverage with asserts like:
Assert.IsTrue(CanEatOthers(ZooAnimal.Tiger);
Assert.IsFalse(CanEatOthers(ZooAnimal.Zebra);
Assert.IsFalse(CanEatOthers(ZooAnimal.Chimpanzee);
That’s not a lot of code and it should be easy to see what it does. This imaginary application is used to allocate savannah space in the local Zoo. It’s fully automate, moving around fences from day to day.
Always making sure that those animal that can eat other’s are kept alone whereas the rest is mixed.
One day the Zoo recieves a new animal, a lion so the enumeration is changed to include lions and we rerun our unit test and find no errors based on our changes.
The system will of cause fail but im not sure the Zebra will think it’s fast enough when it’s being chased by a hungry lion.
I’ve made quite a few errors like that, they creep up on you and you might not catch them even with a high coverage in your unit tests.
To me the problem is the way the switch is responsible for the Zebra becoming lunch.
Adding a value to an enumeration should be safe. You are adding new information to the system not changing anything already being used. I have only one use for default and that is to make the code fail very close to the source. I think the switch should look like:
public bool CanEatOthers(ZooAnimal possibleHunter){
switch(enumeration){
case ZooAnimals.Tiger:
return true;
case ZooAnimals.Zebra:
case ZooAnimals.Chimpanzee:
return false:
default:
Debug.Fail(string.Format(“Unknown case {0}”,enumeration));
}
}
The system still fails but no one is getting eaten this time. We end up in a situation where the code as soon as possible tells us that it’s failing and debugging this case should be over in a few minutes.