Friday, 3 January 2014

Stretch zone

This model is by Karl Rohnke, an outdoor adventure instructor. I like the way it reduces the black and whiteness of the concept of comfort zones.

comfort-stretch-panic model

Thursday, 10 October 2013

Make them work for it

I think this campaign from Transport for London is fantastic.

'Drivers, look out for cyclists' poster

I love that everything is parallel, the bike is behind the vehicle and the road edge extends to the full width of the poster. It looks like there's no danger, so you have to use your imagination to make sense of the caption.

I also suspect that the campaign is not really aimed at drivers.



By the way, if you can't see the picture, try a different browser! I've been moving away from bitmap images to SVG (vector graphics), to support high-resolution devices. I've updated most of my previous posts with SVG versions of the pictures. My assumption is that most people who read my blog will have a modern browser.


Monday, 15 April 2013

Expressing your thinking in code comments

Comments are sometimes warning signals

When you feel the need to add a comment to a piece of code it is sometimes a signal that the code is getting too complicated. It's generally better to fix the underlying design problem than write a comment to explain the mess. As soon as code starts to become complex it is very easy to descend into a negative spiral.

However, some explanatory comments can be very helpful

I have found a lot of value writing comments to explain the rationale for a design and possible future directions that I might forget or that others will find useful. I've got a brain like a sieve and I used to find that I frequently ended up rewriting code I'd previously written because I couldn't remember the direction the design was going in or how it fits together with other pieces. A real waste of time. The comments have almost completely stopped that, but they can cause a new problem: I sometimes find it hard to resist the temptation to start implementing the future-direction ideas I'm explaining in the comment.

Wednesday, 4 July 2012

Separating Look/Feel from View/Presenter

Here's a demo of a working iPad-style on-off switch that I wrote in SVG and Javascript (GWT).

SVG seems to work pretty consistently across platforms – including the iPad, iPhone and all modern desktop browsers, astonishingly even IE 9. The only unfortunate exception is Android where, apparently, SVG support was actively removed to reduce the browser footprint (by a measly 1MB). You can work around it by installing Android Firefox which supports SVG though not multi-touch.

As I developed the on-off switch control, I separated out two distinct interfaces that I called: View and Look. To give them a proper namespace, without too much clutter, I nested the interfaces inside an outer interface for the OnOffSwitch something like this:

public interface OnOffSwitch {

interface View {

void setOn(boolean on);

boolean isOn();

HandlerRegistration addValueChangeHandler(
ValueChangeHandler<Boolean> handler);
}


interface Look {

void knobDown();

void knobUp();

/**
* @param position
* A value between zero and one (0 = OFF, 1 = ON)
*/

void setKnobPosition(double position);
}
}

The Look is called by a Feel object that translates mouse-clicks and touches. The View is called by the application code. My SVGOnOffSwitch widget implements both Look and View interfaces and hooks itself up to a default Feel object. Testing the Feel object was easy to do by passing it a mock Look.

It's always hard coming up with good names for interfaces and objects. I thought I'd post this because I was pleased with the way the code ended up.

Tuesday, 19 June 2012

A "new" alternative to Spring

Objects are composed of objects. The pen in your hand is composed of a nib, a cartridge, and a plastic sheath. The cartridge contains ink, some kind of valve and so forth. The word "pen" is an abstraction that allows us to communicate at a higher-level and ignore all that detail.

However, when you use a dependency injection (DI) framework, like Spring, to wire objects together, everything appears to be at the same level of abstraction.

Abstraction is the key to dealing with complexity

Without being able to distinguish higher-level abstractions it's easy to become mired in low-level implementation detail. The complexity makes it harder to reason about the application and hard to maintain a clean separation of concerns.

Find clusters that can be abstracted

To work at higher levels of abstraction, we need to encapsulate a graph of lower-level objects inside a simpler façade. The GOOS authors call this "the rule of composite simpler than the sum of its parts" (p.53).

Inner objects are not peers

The encapsulated objects are inside the higher-level object. They are not external collaborators of the object. The inner objects are an implementation detail.

To construct our objects we have two basic choices: either (1) we pass inner objects in through the constructor/setters (à la Spring) or (2) we create the inner objects inside the outer object.

Injecting inner-objects breaks encapsulation

If we pass objects in, we make it hard to distinguish internals from peers and we break encapsulation because we are forced to know how the object is implemented when we construct it.

Use "new" instead

The simple alternative is to use the new operator to create the internal objects and wire them together in the outer object's constructor. If we do this consistently through our application, we don't actually need a DI framework. Objects themselves are quite capable of performing the role that a DI container would perform.

If necessary, mix the two approaches

There are occasions when having separated configuration can be useful - e.g. for supporting plugins. There is nothing stopping us from adopting a hybrid of the two approaches. We can use a DI container for those specific objects that need it.

And vice versa: if we're already using Spring, there's nothing to stop us pulling out clusters of objects from the Spring configuration and assembling them in code, one cluster at a time. It doesn't have to be an all-or-nothing transition. It can be done gently.

Saturday, 11 June 2011

Eli Goldratt RIP

I just received very sad news that Eli Goldratt died today. He had aggressive lung cancer, presumably brought on from a lifetime of pipe-smoking. I feel extremely lucky to have met him. He has influenced my life tremendously. I only wish I'd met him earlier. :-(

Picture of Dr. Eliyahu M. Goldratt

Friday, 29 April 2011

Why do teams fail to sustain code quality?

Code quality always seems to get worse and worse. Even when a team is actively fighting against it, complexity inevitably wins in the end. What's going on? Why is this pull towards complexity such a powerful force?

In my view, a lot of the problem stems from the wrong actions being taken, with the best of intentions in mind.

Code quality quickly spirals down

Developers don't want to introduce bugs, so they naturally take actions to avoid doing so. Making changes to working code is risky, so developers make heavy use of conditional logic ("in my particular case do this, otherwise, do the same as before") and duplication to minimise the changes to existing code.

There's a good intention behind it. Unfortunately, it makes the code increasingly difficult to work with—to understand the ramifications of a change— and subsequently increases the pressure to tread carefully and avoid making those bigger and bolder changes to the design that are really needed to keep the code clean.

Automated regression tests aren't enough to stop it

Agile teams tend to make heavy use of automated regression tests. This not only allows the team to release code frequently, but allows them to refactor it and keep the design in good shape. The tests should catch any bugs introduced when the design is reworked.

That's the theory, but, in practice, the developers don't keep the design clean. Why? Because their old "don't make unnecessary changes" habit is so deeply-ingrained. And so, the vicious circle continues.

You have to change the habits too

How do you change habits? Education, constant reminders, code reviews, management oversight, tie a knot in your handkerchief... whatever it takes because if you don't change the habits your code quality will deteriorate and your team's agility will disappear with it.

"Circuit Diagram" for Options

After drawing the diagrams for my last post, I'm playing with ideas for a notation for describing options. What I've come up with so far isn't very good — I'm not even very clear on what the dimensions are... I think it's roughly time along the x-axis and choices along the y-axis, though I think I may be mixing other concepts in as well — but, anyway, I thought I'd put it out in the hope that someone else might help me improve it.

Here's a real-life example from my last project (read it from left to right):

We actually followed these steps. The team in Hong Kong worked on improving the speed of the database reports, while, in London, I built an alternative report generator that wasn't as flexible, but was very fast. By release time the Hong Kong team had ironed out all the problems with the queries and optimised the databases indexes so their reports were adequately fast. In the end, we went with a mixture of the two.

I also got in trouble by trying to be too clever. I put code in to the test environment to do live cross-checking of the reports generated by the two methods. It did reveal some discrepancies. But I got in trouble because they were trying to do speed tests at the time. Communication, communication, communication...

Let me know if you have any ideas about a notation for describing options (I'm talking about real-life options, not financial options).

Thursday, 28 April 2011

Always have a plan 'B'

You cannot predict exactly what's going to happen in the future. Having options allows you to respond quickly as different situations arise.

Option to Abandon

Lifeboats on an ocean liner are an example of the option to abandon. The same with backups of your software. With luck you'll never need them, but it's worth creating the option just in case.

Option to Backtrack

The option to backtrack is similar to the option to abandon, except that you don't abandon the direction completely, you go back to a previous "safe" point ready to try again.

If you release a new version of some software and then find it's unstable, you want to be able to go back to the previous version. Any kind of "rollback" or "undo" capability is providing the option to backtrack.

Being able to backtrack is important for learning. To experiment with a piece of software, try out a new refactoring, or test the boundaries of a technique you want to feel safe that you can go back to where you were.

Option to Choose

This option is about alternatives. To travel between cities you might take a train, but if the train drivers are on strike you'll need to find another way. By thinking about your choice of options in advance, you won't need to panic.

An example in software is where the business logic is decoupled from the data storage technology, so that users can choose between several different databases. This can create value by widening the potential market.

Option to Defer

This option is about timing. Do we have to decide now or can we decide later? The option to defer is about pushing back decision points, to allow more information to come in, or being able to put something on hold, with the possibility of returning to it later on — for example, postponing a space shuttle launch due to icy conditions.

Traditional software development methods force the development team to commit to features a long time before they are developed or deployed. Agile methods let you defer commitment (see this article by Chris Matts and Olav Maassen for a more in-depth explanation of how options-thinking relates to agile).

Option to Expand (or Contract)

This option is about resources. If a customer wants to place a huge order with you, can you accommodate it? Can you recruit quickly? Can you move resources from a less successful project to another more successful one?

Tuesday, 29 March 2011

Start with clear acceptance tests

One of the advantages of acceptance test driven development (ATDD) is that it helps a team to agree on the objectives before diving into coding. The clearer the acceptance tests, the fewer misunderstandings there are likely to be. Every misunderstanding wastes time and adds cruft to the software.

Releasing frequently gives an opportunity for feedback and correction. Small corrections early on can prevent the need for large corrections later.

1. Well-articulated acceptance tests and frequent releases:

Relatively straight line

2. Poorly articulated acceptance tests:

Line with some zig-zagging

3. Longer times between releases exaggerate the deviations:

Line with fewer segments and severe zig-zagging

4. Without any vision or objectives:

Random loopy patterns

This often happens in start-ups where a product idea is hazy and the team is basically chasing every hare that runs past. Eventually they might happen to catch one, but it's a pretty inefficient way to work.

Friday, 25 March 2011

Evaluating start-up business ideas

I often have ideas for start-up businesses and get quite excited about them until it slowly dawns on me there are major flaws. In a bid to spot the flaws sooner, I've come up with some evaluation criteria. I thought I'd post them, in case anyone finds them interesting or has any of their own thoughts on the subject they'd like to share.

Judging a business

Large scope for growth

Judging a business

Risks can be kept low

Judging a business

Friday, 21 January 2011

What's wrong with the Agile Manifesto?

I've never liked the Agile Manifesto. I'm not blaming the authors because I know it must have been a nightmare trying to come to a consensus, and the manifesto has served a useful purpose bringing like-minded people together under a single brand. It is slightly ironic that the wording hasn't changed in 10 years, but there you go. I'm not brave enough to propose an alternative yet. In this article, I'm just going to explain where I think the logic is faulty.

Here is the wording of the manifesto:

Manifesto for Agile Software Development

We are uncovering better ways of developing software by doing it and helping others do it. Through this work we have come to value:

Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan

That is, while there is value in the items on the right, we value the items on the left more.

It doesn't distinguish agile from "slapdash"

The aim of the manifesto seems to be to try and distinguish agile from waterfall. Unfortunately, agile's worst enemy isn't waterfall but the "we don't write documentation, so we're agile" brigade. And the manifesto doesn't defend agile very well against this threat. Perhaps there's something in the twelve principles but who on earth reads them? Certainly not the slapdash developers claiming to be agile.

It mixes up goals and solutions

"We value working software over comprehensive documentation". OK, but surely whatever software development method you select, working software is the ultimate goal, isn't it? Some people believe that by writing comprehensive documentation you are more likely to produce working software. That's part of their solution. But you can't go round comparing goals with solutions. It's nonsensical. Perhaps what the manifesto authors wanted to convey was that "the code is the documentation", or something along those lines, but couldn't agree to write it, so plumped for the goal as their solution. That's cheating!

The dilemmas are easy to solve

The manifesto poses dilemmas and then tries to position agile at a certain point in each trade-off continuum. But why are we compromising? If both sides have value (as the manifesto plainly says), why don't we find solutions that resolve the conflicts? Let's take each one in turn:

I don't know whether the value of documentation is to do with maintainability, improving clarity or good governance. The point I'm trying to make is that there does not have to be any compromise between those needs and agile methods.

So what is agile then?

I'm not sure. Please can you give me feedback on this post and your ideas. Leave a comment, or blog about it, or tweet me (@davidp99). Thanks.

Tuesday, 11 January 2011

FlowChain - Ideal company structure?

"If you could start from a clean slate, how would you structure a large company?"

A little Twitter conversation with Simon Baker (@energizr) about product streams, reminded me of a talk at last July's Agile Coaches Gathering, where Bob Marshall (@flowchainsensei) answered the question above by describing his "FlowChain" concept.

This is my interpretation of what he said (from memory) so it may not be quite right and he's probably refined it since then.

Running the whole company in an "agile" way

Essentially FlowChain scales agile practices up to the company level. There is a single (large) development team that works from a prioritised backlog of MMFs (Minimal Marketable Features). I'm not sure who manages the backlog. I've called it a "product strategist", but that's my name for it not Bob's.

The team works on multiple value streams. Each value stream has its own operations staff.

Zooming in:

Extreme flexibility

What I like about FlowChain is the flexibility it provides. If a value stream is doing well, resources can quickly be redeployed to capitalise on its success. Alternatively, new products (value streams) can be developed. In most organisations, moving developers from one project to another is a major upheaval, and that puts pressure on the project to be a success. When you can move developers quickly to something else, it relieves the pressure and allows the company to tackle more risky (but potentially more lucrative) opportunities.

Note that in a large company, the pool of resources for developing products could be very large, and there may therefore be many MMFs in progress at the same time. Bob didn't explain how to resolve resource conflicts, sequencing etc. We may have to wait for his book...

Prototypes, Spikes and Tracer Bullets

Here's an attempt to classify various development techniques and the sequence in which they tend to be used.



Monday, 10 January 2011

Don't kid yourself

"Our team's agile, but we haven't released yet because some of the teams we depend on aren't agile."

Fine, then you're not agile!

Sunday, 9 January 2011

BDD: Concrete Examples Aren't Enough

The Given/When/Then style of Behaviour Driven Development (BDD), favoured by Cucumber and JBehave, puts a lot of context in the examples that I claimed was unnecessary clutter, but I had quite a few comments that puzzled me until it dawned on me there's another difference in my approach compared with the Given/When/Then style.

I always state the required behaviour in a sentence or two before giving the examples. Each behaviour is described by a specification like this:

Maybe it looks like a lot of work to write, but it isn't really. The structure is standard and each part is just a sentence or two.

Whereas in the Given/When/Then approach the business rule describing the behaviour generally isn't made explicit. The reader is expected to guess the rule from the examples, so naturally they have to have more context.

Occasionally it's difficult for the domain expert to immediately state the abstract rule and easier to start with concrete examples, but once the expert has explained a few examples then we can usually begin to take an educated guess at the rules behind them—"Ah OK, so the rule is X?"—and then have a useful discussion.

But if we don't make the rule explicit we only have the concrete examples, so they have to be made much more verbose—and potentially implementation-specific—so that readers can correctly interpret them.

It is true that Given/When/Then style examples are much better at avoiding implementation lock-in than test scripting ("click this, click that..."), but I would argue that context-free examples with explicitly stated rules are even better, both in terms of avoiding lock-in and in terms of readability (how long it takes the reader to understand the behaviour expected).

Friday, 7 January 2011

Object-Oriented Example

For ages I treated objects as glorified data structures to be operated on by procedural code. It took me a long time to get out of the procedural mindset and into an object-oriented mindset.

Well-written object-oriented code helps you deal with complexity by hiding internal details so that you can operate at ever higher levels of abstraction. Object-oriented code increases flexibility – objects can be plugged together in different ways like Lego™ pieces – and it keeps duplication and churn to a minimum by keeping data and operations in the same place instead of spreading them throughout the code-base.

The recent discussion on the GOOS mailing list has made me realise that others are also struggling with the transition. Nat Pryce has posted a couple of blog entries today, and I'd like to pick up the same theme with an example in the hope it might help.

Let's start with a simple PopGroup class that implements the role of SongPerformer (in Java this would be an interface):

To construct a valid PopGroup you need a Singer, a Drummer and a Keyboardist. These are the PopGroup's dependencies.

The responsibility for coordinating the various activities to perform songs is the responsibility of the PopGroup object, but the actual acts of singing, drumming and keyboard playing are separated out. This is the single responsibility principle combined with dependency injection.

This approach makes the design highly flexible because we can plug together all kinds of variations. As long as the dependencies we inject implement the right interfaces we can make the pop group perform a song.

For example:

If we don't have a DrumMachine, we can substitute a PhysicalDrummer and the PopGroup will still function the same.

Our PhysicalDrummer object depends on interfaces not implementations. If we're desperate we could grab a passer by, a dustbin and a broom handle and create a drummer:

Unfortunately the BroomHandle class does not implement the Drumstick interface. We could make it implement Drumstick, but the BroomHandle is in a different domain. It's in the domain of sweeping, rather than musical performances. We don't really want to couple its class to an interface from the musical performances domain, so we create an adapter to map between the two. This is known as a ports and adapters architecture.

To make things easier to understand we can wrap the objects into a class that has a name that better expresses the intent.

Now we've hidden all the complexity and we're operating at a higher-level of abstraction.

In reality, a ports and adapters architecture is not so much mapping between entirely unconnected domains as mapping lower-level domains to higher-level domains, so that the technical detail is hidden within simpler more abstract concepts.

Concordion Extensions

Nigel Charman has started a concordion-extensions sub-project that adds some useful extra features to Concordion, such as the ability to add screenshots to the Concordion output so you can more clearly see what state the application is in when something fails.

Another valuable extension inserts a little icon into the output and when you hover over it, it shows logging output that occurred during the test. This is a neat solution to a dilemma that I've sometimes encountered: "If I don't write down the steps, how can I be sure the test has been implemented right?"

We want to write high-level tests that express the business requirements without reference to a particular implementation, so we can change the implementation later. To do this, we hide the test's implementation steps in its accompanying Java fixture. But some people aren't comfortable navigating and reading Java code. If you're a non-developer tester trying to make sure the system is well-tested, it can be scary to "trust" the developers to implement your tests correctly.

The temptation is therefore to explicitly write into the test specification the steps required to execute the test. The trouble is by encoding the "how" you end up locking the test into a specific implementation. The lock-in problem is exacerbated by duplication across tests. When you're detailing all the steps, you find that many tests require a similar set of steps.

Our conflict cloud looks something like this:

Testing Conflict

Some testing frameworks, such as Robot and FitNesse, allow you to pull out common set-up but this is a compromise. Effectively what you're doing is programming, but not in a proper programming language. The intentions of your tests become lost amongst increasingly complex interweaved test scripts.

Nigel's solution allows you to write the tests in a way that retains a clear separation between intent and implementation, yet allows non-developers to be reassured that the test has been implemented correctly.

Testing Conflict Resolved

Friday, 3 December 2010

BCS SPA 2011 Conference

SPA Conference

I'm the newly-elected Chair of the BCS Software Practice Advancement group. I'm not sure how it happened, but I'm very excited about it.

Unfortunately, I joined too late to be actively involved in organising the next SPA conference (London, June 12-15th 2011). That responsibility lies with Ivan Moore and Mike Hill as conference chairs and Willem van den Ende and Rob Bowley as programme chairs. However, I'm definitely going to attend the conference having just snapped up an early-bird ticket.

What I like about the conference is that it's not oriented around a particular technology or approach, and the attendees tend to be at the expert end of the scale. In my opinion, it's the best conference having your thoughts challenged. That's what I want from a conference.

Thursday, 2 September 2010

Refactoring Given/When/Then

I've come to the view that Given/When/Then is a poor way to think about scenarios, and is even worse for writing them. It makes me turn even the simplest situations into a ramble. And I don't think it's just me.

Given a user called Fred
And user Fred is logged in
And user Fred has an empty shopping basket
When Fred adds a $15 screw-driver
And Fred adds a $12 lamp
And Fred adds a $12 lamp
Then the total of Fred's bill is $39

If I start with Given/When/Then, I end up having to go through a laborious process of simplifying, getting rid of unnecessary details. In our example, above, Fred may be needed behind the scenes but doesn't add anything useful to the description.

Given we are logged in
And we have an empty shopping basket
When we add a $15 screw-driver
And add a $12 lamp
And add a $12 lamp
Then the total bill is $39

Do we need that bit about being logged in? No. Readers will likely assume it and, even if they don't, who cares anyway? It's irrelevant to what I'm trying to explain.

My rule of thumb is: if the context is unexpected (e.g. we're trying to explain what happens when you aren't logged in) then we need to mention it, but if the context can be inferred from the other parts of the scenario, or from common sense, then leave it out. There's a feeling that adding context will remove ambiguity, but all it actually does is complicate the example.

Given we have an empty shopping basket
When we add a $15 screw-driver
And add a $12 lamp
And add a $12 lamp
Then the total bill is $39

Are the words "screw-driver" and "lamp" necessary? I think they are. If we removed those words and just had the prices, the example would be harder to understand. You need something to show that the prices represent items. Using more abstract labels (e.g. "item A", "item B") is a possibility, but doesn't seem to buy us much.

What about the "empty shopping basket"? Can that be reasonably assumed? Yes, but rather than starting with an empty shopping basket, how about starting with a full one and dropping the "when" part?

Given a basket containing a $15 screw-driver
And a $12 lamp
And a $12 lamp
Then the total bill is $39

Finally let's remove the duplication.

Given a basket containing a $15 screw-driver
And 2 x $12 lamp
Then the total bill is $39

OK, this doesn't suck as much as what I started with.

But why not just write this:

1 x $15 screw-driver
2 x $12 lamp

Total bill = $39

This is what I might write on the back of an envelope if I were giving an example to somebody. With the right tools (e.g. Concordion), I can code it up exactly as I just wrote it. I don't need to use Given/When/Then. I used to think it was a good way to structure the example, but I've changed my mind.

Tuesday, 2 March 2010

Growing Object-Oriented Software, Guided by Tests

Almost every programming book I've read has irritated me. I get irritated easily (I don't get enough sleep), but Java books are the worst because Java's the language I use most and know best. I still read them because there are usually a few good ideas buried inside, but it irritates me that I have to wade through so much tosh.

So far, Growing Object-Oriented Software, Guided by Tests is the only exception. There's no tosh. It's incredible. I've read the book two or three times and each time I felt myself becoming a better programmer. If you haven't read it yet, I can't recommend it enough.

Wednesday, 14 October 2009

Kanban Blog

Having leapt aboard the Kanbandwagon, I've started a new blog about Kanban at, funnily enough, kanbanblog.com. Here's a taster of my first post:

Which of these feature ideas should we select as a priority?

Feature Estimated
Value
Estimated
Production Time
A $100,000 40 hrs
B $80,000 40 hrs
C $60,000 40 hrs

Feature A? It's a no-brainer, right?

Not necessarily...


Monday, 25 May 2009

Concordion 1.3.1

Concordion 1.3.1 was released last month with a handful of new and noteworthy features. There was an announcement on the Yahoo mailing list, but I wanted to wait for the Concordion.NET port to catch up before making an announcement on this blog.

For those who didn't know, there are now versions of Concordion for:

So, if you're using Cucumber in Ruby, or FitNesse in .NET check out the alternative. No other acceptance testing framework lets you create such readable acceptance tests as Concordion's. The key advantage in having readable tests is that when you come back in three months time and wonder what the heck you were doing, you might actually have a clue.

Update: Jeffrey Cameron has started a blog about Concordion.NET and how to use it.

Thursday, 19 February 2009

Avoid not using positive method names

I'm integrating with Spring Security at the moment. It seems to be a well-designed framework, but I got myself confused this morning trying to implement some methods of the UserDetails interface:

boolean isAccountNonExpired()
    Indicates whether the user's account has expired.
boolean isAccountNonLocked()
    Indicates whether the user is locked or unlocked.
boolean isCredentialsNonExpired()
    Indicates whether the user's credentials (password) has expired.
boolean isEnabled()
    Indicates whether the user is enabled or disabled.

I imagine the designers wanted all the answers to be true for the normal "happy" situation. But my brain couldn't cope with all the negatives, so I ended up writing a second set of positively-named methods to call from the negative ones. :-)

public boolean isAccountNonExpired() {
return !isAccountExpired();
}
... etc.

Thursday, 12 February 2009

GWT 1.6 Milestone 1

In case you weren't aware, GWT 1.6 Milestone 1 has recently been released. The biggest change is that projects are now laid out using a standard WAR file structure. This makes hosted mode much better because you now have full control over the web.xml file. They've also switched from Tomcat to Jetty internally (Jetty's start-up time is quicker) and they've added a button to restart the server without having to exit and restart hosted mode. Very convenient.

I'm combining GWT with Tapestry 5, in my current project, so these changes are very helpful. I can now run them together in hosted mode.

Tuesday, 14 October 2008

Label verbose items to simplify back-references

This is quite an obvious little pattern, but I think it's still worth documenting.

Some repetition is harmless
When I'm writing an example of a required behaviour, I find that I often have to refer to something I've already mentioned. For example:

Given the following names: Charles, Naomi, Melissa, Arnold
Searching for 'ar' should find: Charles, Arnold

Here, I have mentioned the names Charles and Arnold twice: once when describing the context and once when describing the expected outcome. This isn't a problem because I purposely kept the names short to make the example easy to follow.

But repetition can become awkward
If the values are long or complicated then the examples can become hard to read and maintain. For example:

Given the following addresses:
18 Cedar Row, Enfield, Middx, EN8 9TT
"The Grange", 177 Hounslow Road, Epping, Essex, HA10 4PL
2b Armsfield Avenue, London, SE1 2BN
80 Commercial Street, Aberdeen, AR19 1TB
Searching for 'ar' should find:
18 Cedar Row, Enfield, Middx, EN8 9TT
2b Armsfield Avenue, London, SE1 2BN
80 Commercial Street, Aberdeen, AR19 1TB

So, use labels for verbose values
Labelling each item allows you to use the label, instead of the value, whenever you need to refer to it.

Given the following addresses:
(1) 18 Cedar Row, Enfield, Middx, EN8 9TT
(2) "The Grange", 177 Hounslow Road, Epping, Essex, HA10 4PL
(3) 2b Armsfield Avenue, London, SE1 2BN
(4) 80 Commercial Street, Aberdeen, AR19 1TB
Searching for 'ar' should match addresses: (1), (3), and (4)

I call them labels or pseudo-identifiers to distinguish them from real identifiers in the system under test. For example, in the implementation we might have a database table called Address with an identifier column called addressId. But the identifiers we use in the examples are merely a way of making the example easier to read. They are not a reflection of any particular database model. Any mapping between real identifiers and pseudo-identifiers must always be handled behind the scenes in the fixture code.

The labels don't have to be numeric. They could be letters (A, B, C) or other more meaningful short strings.

Labels can also help you to hide details
Another advantage of labels is that they can let you gloss over unnecessary details. For example:

Example acceptance test showing use of pseudo-identifiers

Using labels for bookings (1, 2) and for booking references (A, B) means we don't need to go into any details of what we're booking or what the booking references look like. If the format of the booking references is important, we can cover that in another test, but, in this test, we're not locking ourselves into any particular format. All we're doing is demonstrating the rule: "Each booking is given a unique booking reference that can be used to look-up the booking."

The fixture code will have the following methods:


public class IdentifyingBookingsTest extends ConcordionTestCase {

public void makeBooking(String bookingNumber, String bookingRefAlias) {
...
}

public String lookupBooking(String bookingRefAlias) {
...
}
}

Having this extra level of indirection may make the fixture code work harder, but that is not a problem. It is much better to put complexity and implementation-related assumptions in the fixture code, where we have powerful refactoring tools at our disposal, than to complicate the specification and make it more fragile.

Tuesday, 7 October 2008

Friday, 2 May 2008

Concordion for Ruby and Maven

Concordion for Ruby
Ben Goodspeed has written a very neat Ruby port of Concordion and packaged it as a gem. There are currently some minor syntactical differences between the Java version and the Ruby version because the Ruby version doesn't do lookahead variable bindings yet (Ben's working on that) but the core functionality is already implemented (set, execute, assertEquals, and verifyRows).

Maven Integration
Several people requested that the Java version of Concordion be added to Maven repositories and thanks to José Manuel Beas, Wang Yi Zhou, Craig Walls, and others, this is now done (instructions for usage with Maven are here). Concordion 1.3.0 has the same functionality as 1.2.0 but with Maven support.

Saturday, 15 March 2008

Concordion 1.2.0

I've released a new version of Concordion.

  • Support for full set of JUnit4.4 annotations (@Before, @After etc.)
  • New command: assertTrue
For example, this instrumented specification:
<p>
The first name <span concordion:set="#firstName">Bob</span>,
<span concordion:assertTrue="#firstName.startsWith(#letter)">
starts with the letter <b concordion:set="#letter">B</b></span>.
</p>
Will result in the following output:
Success

A failure would look like this:
Failure

Thursday, 13 March 2008

Big Hairy Tables

I like Keith Braithwaite's "software gauges" metaphor. As he explains, a gauge is a shortcut for deciding whether something passes or fails some criteria. For example, if your bag fits inside the metal cage at an airport then it can be taken onboard as hand luggage. You don't need to use a tape measure. What's interesting about gauges is that you don't necessarily need to be able to articulate "the rules"; if you need to know the rules you can infer them from the gauge.

However, I'm not convinced with what Keith says about trader spreadsheets making good gauges. Obviously he's had success with them, so they definitely can be made to work, but would they have worked even better another way? Basically what it boils down to is that I like tables; I just don't like big hairy tables!

If the hand-luggage cage can be taken as an example of good practice then some of the properties of a good gauge appear to be: sturdy and reliable; correct enough for all practical purposes; obvious; unambiguous; quick to use; and simple to understand by the gauge user.

The spreadsheets Keith showed me contained a large number of sparsely populated columns of denormalised data with lots of magic numbers and magic strings. This doesn't seem to stack up well against the list of desirable traits for a gauge. They're not designed with the gauge user in mind. If your domain model doesn't fit the gauge, is it because the model is wrong? Or the gauge is wrong? Or your interpretation of the gauge is wrong? With so many moving parts, it's got to be difficult to work out, even with help from the traders.

Isn't it better to treat the spreadsheets as a starting point rather than an ending point? And then have someone skilled at analysis and abstraction work with the traders and extract smaller, more practical gauges. There's nothing to stop you holding these gauges in spreadsheets too. I have a lot of respect for the customer, but I don't see why, just because the traders have written a spreadsheet, you can't help them improve it. They've got their skills you've got yours.