Archive for January, 2006

Shared Memory in Teams

Sunday, January 22nd, 2006

A while ago I read the The Tipping Point. There’s a section there on how partners share memory - two people who are in a relationship remember differently than single people.

The study cited is here:
Transactive Memory in Close Relationships

When reading it, you may note the Grossly Misleading Graph (Figure 1) - but apart from that the results are interesting, and seem fairly familiar. I guess we all know long-together partners who finish each other’s sentences, where one will delegate a question to the other saying the other “always remembers the birthdays” for example.

It makes sense that the same effect occurs in development teams after a while. We delegate memory - the team naturally spreads the knowledge around, and people end up with different levels of “expertise” in different parts of the system. We need to be aware of this when we talk about sharing the knowledge in XP - it means that we will never get complete knowledge transfer. It is normal healthy humanity that some people know more about a certain part of the code.

But that doesn’t mean that the attempt to break apart the “silo” and spread knowledge is a waste of time. Rather, it should inform the way we go about it. Basically, I think it means that we should strive to achieve a common understanding of the system rather than an equally detailed understanding of it. There should be plenty of people who “know where to look” as Vishy put it once.

As an analogy, one of that couple may do most of the cooking. That doesn’t mean that the other cannot cook, or doesn’t want to, it just means that they mostly don’t - maybe they just help out with the vegetables. Even so you can be sure that they both know which cupboard has the spices. Just as we try to avoid “silos” in development, we would be worried if the cook hides the spices, or locks the cabinet, or even worse, locks the door to the kitchen.

So I think it is unrealistic expect everyone in the team to get to the point where they know all parts of the system equally well. Rather, make sure that the team has a common language and way of doing things - so they know where to look.

Grossly Misleading Graph

Sunday, January 22nd, 2006

From:
Transactive Memory in close Relationships

Figure 1 from Transactive Memory in Close Relationships

This falls into a classic error in displaying data - note the y axis starts at 20, not zero. This magnifies the effect - it makes it look like the difference between the values is relatively much greater than it actually is.

Consider the Natural, assigned and unassigned values on the right 2 bars. As displayed, it looks like the values are 24 and 32 (I am rounding to the nearest whole number - the paper does not specify the totals. So from the graph it would seem that the ‘Assigned Expertise’ is 4 / 12 as high as the ‘No Assignment’ value. That is, a glance at the chart would imply a 3-fold improvement of recall for ‘Assigned Expertise’ over ‘No Assignment’.

What are the real numbers? More like this:

Figure 1 with fixed Y axis

Still an interesting result, but nowhere near as much so as the original chart implies.

You see this a lot in charts during business presentations - it is a temptation to make a result seem as dramatic as possible, but it distorts the actual result, and may bias us towards a particular interpretation. I always look at any presentation chart to make sure that the axis starts at zero.

For more info on charts and best practices, see here:
EIA Guidelines for Statistical Graphs
The page concerning bar charts in particular is here:
Vertical and Horizontal Bars, Pie and Dot Charts, and Three-Dimensional Features

Here’s a comparison of the two graphs, both converted to the same format:

Figure 1 redrawn Figure 1 with fixed Y axis

Musing on Language, Codification and Qualification

Thursday, January 12th, 2006

Ben is presenting a paper tomorrow which compares the language and interpretation of the Canadian Charter of Rights and Freedoms[link] with the codified Edict in Timothy Findley’s Not wanted on the Voyage.

And it got me to thinking¦

It struck me that the language of the law is rarely specific - it is couched in general terms - hedged about with ifs and buts - rarely couched in absolutes. In fact the language of the law is constructed carefully to avoid absolute or exact statements. Its all about nuance and relativity. This (I would suggest) is precisely because the law’s decisions are themselves so final and absolute - Guilty or Not Guilty. So since the decisions of the law are absolute, the “wiggle room” to allow for reality must be provided by a language that deliberately avoids commitment.

Section 27 - Canadian Charter of Rights and Freedoms : “This charter shall be interpreted”

This is not so in science however. Science is quintessentially relative and contingent - it is expected that today’s hypothesis might be disproved or changed on the basis of new discoveries and research. So to make it easier to test a hypothesis, it must avoid ambiguity and nuance. In fact hypotheses are constructed in absolute terms. Often it is the facts, the observations that are nuanced, hedged about with observational error bars and quantified sampling errors.

In my own field of software development, we are starting to move beyond the strictly typed mathematical languages of Java and C#, and becoming more comfortable with (lispers and smalltalkers would say re-discovering) the freedom and “wiggle room” that comes with untyped or dynamic languages such as ruby, python etc. Given these languages inherent flexibility, we constrain our solutions with the unit tests that we write - almost as legal interpretations are constrained by precedent - or scientific hypotheses are constrained by experimentation.

Don’t read too much into this - allegories can only go so far, and I’m not really getting at anything - but I found it an interesting train of thought.

Agile India Goa 2005 Distributed Agile Presentation

Thursday, January 12th, 2006

I gave a presentation at XPToronto late last year on distributed agile, and how we went about transforming one of our own projects that had stagnated. This was an interesting project, not least because it is a large (at its peak about 40 developers, 35 in India, 5 in the US) long-running (5 years) agile project.

Goa Presentation - Even More Agile

This is a presentation that Deven Tolia and I gave at and Agile conference in Goa, India in 2005. Originally we did it with 2 projectors, one showing the photographs, and one the slides. We found then, and it was re-inforced when I did it in Toronto, that the photos are the most interesting aprt of the presentation. Many people haven’t seen an Agile project, and talking about theory is no substitute for seeing it done, even if the images are still.

And (re)-reading Tufte’s excellent The Cognitive Style of Powerpoint reinforces the observation that bullet points are not content. The content is in the conversation and the talking that accompanies the pictures, or the whitepaper that expands on the discussion. Deven and I plan to write this paper up in more detail this year, hopefully to present it at one of the Agile conferences this year. When we do that, I hope we will be able to rework it to address those issues.

Assertions on Domain Objects

Monday, January 9th, 2006

Martin Fowler has blogged on a testing technique he calls TestInvariant.

This reminded me of a related approach that I have used is to refactor assertion methods onto the class under test. Here is how I got there.

Suppose you are was writing some tests on Martin’s bowler class:

public void testConcedingRunsAddsToRunsScore() {
  Bowler botham = new Bowler();
  assertEquals(0, botham.getRuns());
  botham.concedeRuns(4);
  assertEquals(4, botham.getRuns());
}

Now there are 2 code smells here to me.

First, the test has forced me to expose the internal implementation of the Bowler class - bleargh. It is bad enough in domain objects and it is worse when it is just for the purpose of testing. Even if we make the getter package protected it still ollutes the API. And sooner or later someone will come along who will make it public and start using it.

Second, the assertions are not very domain specific - and there is duplication. Lots of developers will make them a bit more informative with a message - like this:

public void testConcedingRunsAddsToRunsScore() {
  Bowler botham = new Bowler();
  assertEquals("Should have 0 runs", 0, botham.getRuns());
  botham.concedeRuns(4);
  assertEquals("should have 4 runs", 4, botham.getRuns());
}

I tend not to do this for assertEquals - it is already informative enough, and the message doesn’t increase readability, it increases duplication. So lets do something else:

public void testConcedingRunsAddsToRunsScore() {
  Bowler botham = new Bowler();
  assertHasRuns(botham, 0);
  botham.concedeRuns(4);
  assertHasRuns(botham, 0);
}

private void assertHasRuns(Bowler b, int runs) {
  assertEquals(runs, bowler.getRuns());
}

That’s nice - we have a new informative assertion that is now making an assertion about the domain, not about the state of the object.

If you look at the testConcedingRunsAddsToRunsScore method, everyhting it does is expressed in the language of the domain - we have a mini domain language right here. Consider the assertion assertHasRuns(botham, 0) - that reads nicely.

But now there is one more code smell - feature envy. The assertHasRuns method is envious of the bowler, and following the precepts of refactoring - we should listen to what the code is telling us and move the method onto the bowler. so lets do that:

class Bowler {
  public void shouldHaveRuns(int expectedRuns) {
    Assertion.assertEquals(expectedRuns, this.runs);
  }
}

I’ve done one extra step here, and renamed the assertion to make the domain language a bit clearer. Let’s look at the test now:


public void testConcedingRunsAddsToRunsScore() {
  Bowler botham = new Bowler();
  botham.shouldHaveRuns(0);
  botham.concedeRuns(4);
  botham.shouldHaveRuns(4);
}

There is one extra really nice thing now - since the assertion has moved onto the class under test, we no longer need to expose the getRuns method. So we can remove it and increase the encapsulation of the class.

This approach also fits quite nicely with the emerging approach of Behaviour Driven Development and Humane Interfaces.

Note though that as shown above, you need to distribute the JUnit classes with the production code, to make the assertion methods object available. I don’t mind this. If you do, you could use Java’s own assert support, or move the assertions onto a testing subclass of the original object.

This is a technique that I have used to “re-encapsulate” objects in legacy systems. Often there are objects that give all their information away through getters, initially for testing and then slowly people start using the methods rather than encapulating behaviour. This allows you to remove the getters incrementally.