Wednesday, September 16, 2009

The decision making triangle

As an avid agilist, I maintain that the manager should do little more than putting the following three powers together.
* The techie.
* The funding.
* The customer.

These are the three roles to any "go"/"no-go" decision making on wether or not a particular technical endeavour is worthwhile.

The "funding" is simply someone who is able to decide cost against benefit. The financial backbone for a particular push within your portfolio is often quite obfuscated in a large organization. When you no longer produce bang for the buck, you stop.

The "customer" is simply the someone who can make a decision on a satsifactory solution to any given marketable feature. The customer represents the totality of the demands. In some cases, being an internal customer that is able to map external requirements to internal technical achievable backlog items is a true assett.
A good customer is hard to come by.

Together, the two can decide on where the efforts can give the most value.

The techie translates solution proposals into estimates.

The main discipline between these three is to identify the MMF's (minimum marketable features) that will individually add to the value of the product. It is sometimes hard for a customer to see that his problem is not an irreduceable all-or-nothing deal.
Again, consider the value of a good customer.

The customer is rarely an external person. When deciding on these issues, there should be as little vested interests (and politics) as possible. An external customer is likely to play up his requirements, is unlikely to be willing to vouch satisfaction at the drawing board and various scopes are subject to contract negotiations.

On small projects, one person can have all these hats.
On large projects, the "customer" can have a full time team of three people behind him doing nothing but mapping classification requirements to the proposed features.

Since the development departments are mostly techies, the two other roles are likely to suffer. Especially the customer part. We have many products where it is unclear who demanded what, and in what manner we fulfill certain requirements.

Every agilist should appreciate a customer who can think on his/her feet.

Friday, September 4, 2009

TDD nails it


Imagine yourself TDD'ing a thermostat controlling a heater. Your first unit test is to set the temperatures in the fake thermometer as well as the Thermostat object, which is the unit under test, and to verify that it actually starts the heater.

Now, in the production code, a TDD beginner will find it tempting to check the temperature and then start the heater. However, the correct thing is to not check the thermometer, but just start the heater regardless of input. This is because this is all that is required to pass the first test. You don't need to check the thermometer before you have a test that would fail if you didn't check the thermometer.

If the TDD beginner followed through with his gut feeling and implemented the check right away and then proceeded to the next feature he would be able to remove the thermometer check, introducing a bug in his software, without any tests failing.

Thus removing the premise to safely refactor and changing without breaking.

TDD nails it.

Now, if you were using hammer and nails to fix a piece of wood (say, a board) in place, a novice could be equally "tempted" to hold the board in place and then just hit a nail in its center before moving on.

This would look all well and good until the forces started acting upon it, in which case the board would quite likely shift out of place.

Now, let us pretend that a piece of functionality is a board and that unit tests are nails.

By using just a single nail, both the piece of functionality and the board would seemingly be held in place by nails, but in reality the real upkeeper for both is friction. Friction on wood surface and friction in the code base. Without neither being be nailed in place.

When I implement a piece of functionality I certainly hope to having "nailed it"!

Thursday, September 3, 2009

"As simply as possible"

Yesterday, I held an internal TDD Introduction workshop for about 10 developers.

I had no slides, just winging it using VS2008 on a projector. And using the whiteboard.

The workshop was in two parts.
1. The common calculator that eventually become string based requiring a tokenizer. This is to push the Red-Green-Refactor envelope. I know : pretty boring, but you want to put the emphasis on the tight cycle of TDD.

2. A case with external dependencies.
The specific use case was a HVAC controller. It starts off as a simple thermostat to control a cooling fan, but evolves to a full fledged HVAC controller.
People discover that the API of a thermostat is principally different than the HVAC controller. For example, "Desired temperature" can be a single number in a thermostat, whereas the HVAC controller needs a desired temperature with an upper and lower limit. The pattern geeks may argue that the HVAC controller is actually two thermostats working in opposites (one for "cold", one for "heat"), which certainly makes for some interesting programming.

The three immediate takeaway benefits are:
* TDD forces you to think about your interface. And working in pairs produces some fruitful debate at a very early stage. Paradoxically, people suddenly find themselves unable to express their use cases against their own API (and then they start blaming me).

* They discover that there is a "secret" dependency on time. One dependency driving requirement is that the airfan should run for two minutes after the furnace has been switched off. Hopefully they'll muck around with DateTime static helpers before realizing that time must be controlled from the tests.

* The manual mocks versus isolation frameworks (Moq). The initial test cases make for slim manual fakes, but the Moq syntax is usually heartly received.

We only had half a day, which went by in the blink of an eye, but I think that we ran into many of the typical subjects.
There certainly is stuff that is hard to get even in the simple world of TDD. We met some speed bumps when we crossed the following:

Problem 1: Lambda expressions.
I have opted for our group to go for Moq as the isolation framework of choice. This is because of the crisp syntax and a lot of sense and intellisense. The most noted objection against Moq is that it makes heavy use of Lambda expressions and therefore is only available in the .NET 3.5. However, that is no concern for us.
We had some MFC programmers in the workshop. Even seasoned and capable programmers are visibly in pain when they try to wrap their heads around Lambda expressions. I wanted to showcase the evolution of bamed method -> Anonymous method -> Lambda, but I messed up the syntax for anonymous method and we were too pressed for time to google it.

Problem 2: "As simply as possible".
However simple as it may sound, this rule is all but simple if you start going down the road creating the wrong kind of simplicity. The TDD dogmatic anecdote is that you shall make a test pass in a manner that is as simple as possible.
This is to make sure that the unit tests enforce the functionality of the production code and that the tests truly drive the development process.

Just a week ago, I was attending TDD Masters class by Roy Osherove. I think that I grocked the concept of simplicity on the second day.

In my dependency use case, the first MMF is to make the controller start the FAN if the THERMOMETER shows a higher temperature than the desired temperature which you have set against the API of the HVAC controller instance.
Now, what exactly does simplicity mean? What should be the first test?

Does it mean to not interact with the mocked FAN?
Does it mean to not interact with the mocked THERMOMETER?
Why would it have dependencies at all? Can't you just put a temperature in and the ask it if wants to start the fan?

This started to take the form of a dug-in debate in the class, which I had to cut off.

I think that there is an important distinction to be made here. You do not program unit tests that you do not intend to make obsolete at a later time. Although the unit tests only run a concrete scenario testing a narrow case, they should still execute and pass against the final product three months from now. You still need to express the complete scenario against what you, at the time of writing, expect to become the final library API for that use case.
If you program against getters and setters and the getters only return true, you are not producing value as you plan to both throw away both the unit test and the production code that made it pass. You are also bestowing a legacy API on a brand new component.

I solve the problem as follows in my very first unit test: I create a mock fan and a mock thermometer (with a temperature), pass them both to the controller as constructor arguments and expect the fan to have been attempted to turned on.
This may seem like an advanced use case, but I think it is as simple as it can be.

People in the TDD domain also argue that you should start with constructor checks. At this point, I am not actually sure if it makes sense to be able to new up an controller without arguments, so I am actually forgoing that for the moment. If a later use case starts by newing up an empty controller, I will create a specific "IsNotNull" test.

Now, here is the correct meaning of "as simple as possible": When I confirm that the test fails, and I go into production code, I totally disregard the thermometer and I merely switch the fan on. I do not even store the thermometer reference which was passed in the constructor. This leaves people speechless. The thermometer is available, why not check it? You know that you will have to check the thermometer before starting the fan in the final product.....?
The key here is to recognize the fact that I would then be able to remove the check without breaking any tests. I would be able to introduce a bug in my code without causing any tests to fail. And if that happens, what good are they? How can I safely refactor the code if the green light does not mean anything?
Everybody agrees that I need at least two test cases to "nail" the functionality in place. And I need the if. And when people realize that, they also realize that I am not doing any extra work, I am just doing it in a different order. And the order has additional benefits because I do not have the overhead of writing unit tests after having the complete functionality in the production code.

If you write unit tests after the fact, you need to change the production code in order to see them fail. It is important that you know that the unit tests you write actually can and will fail.

To sum it up: "As simply as possible" does not mean "as stupidly as possible". You still play for keeps. The production code is "work in progress", but the unit test is supposed to be done, you don't plan on revisiting it. After all, it would be tedious process with a growing amount of unit tests if you planned on rewriting the API they all consume so that they no longer describe a valid scenario.

Wednesday, September 2, 2009

Aftenpostens artikkel om nordmennene i Kongo

(This entry is in Norwegian as it comments on an ongoing debate in Norway.)

Jeg ble overrasket over dagens oppslag i Aftenposten om Tjostolv Moland og Joshua French.

Her tar en velrenommert norsk avis og supplerer "anonyme kilder" til ett åpenbart korrupt lokalt aktorat under pågående rettergang med henrettelse som mulig utfall.

Dette blir da kilder som blir benyttet i rettsprosessen som de tiltaltes forsvarer ikke har noen anledning til utfordre eller kryssutspørre.

Aftenposten forer en korrupt prosess med beleilig ikke-etterprøvbare data. Og således tar en aktiv sentral del i en prosess som ikke er Norge verdig.

For meg later dette til å være toppen av journalistisk og redaksjonell uansvarlighet. Med mulig dødelig utfall uten reell rettergang.

Navnene på journalistene, Thomas Hubert og Sveinung Berg Berntzrød, har iallfall brent seg inn på min netthinne. Håper de er såpass sikre på sine kilder at de er beredt til å inntre som aktor, jury og bøddel.

Jeg så også tendenser til dette under narkosaken i Bolivia hvor pressen ikke har vett til å beskytte folk mot seg selv. Selv om de tiltalte i Bolivia-saken var "skyldige som bare f...", så var det ett tidspunkt hvor så godt som alle aviser sluttet å skrive om saken og nye "versjoner" fra opprørte og ivrige pårørende opphørte.