Composable Features
In Eloquent Ruby, Russ Olsen applies the composed method technique
to a class. He says
"The composed method technique advocates dividing your class up into
methods that have three characteristics. First, each method should do a single
thing—focus on solving a single aspect of the problem ...
Second, each method needs to operate at a single conceptual level: Simply
put, don’t mix high-level logic with the nitty-gritty details. A method that
implements the business logic around, say, currency conversions, should not
suddenly veer off into the details of how the various accounts are stored in a
database. Finally, each method needs to have a name that reflects its purpose.
"
When you apply this technique to classes you end up with classes with a relatively large number of methods each which is very simple. In applying this in detail I find that I create two sorts of methods.
- Methods that do something
- Methods that call other methods to do something
And in applying this technique I NEVER mix the two.
These techniques have been around for along time, as have a number of refactoring to get your code more composable. Use them and you’ll never write another 20 line method ever again - personally anything over 5 lines sends of my alarm bells.
Anyhow if this technique is good for classes, might it also be good for features? And if it is how do we apply it?
A clue lies in how composed method technique helps eliminate proceduaral code. Perhaps we can make our features less procedural
Feature: Title
In order to encourage return visits
As a site owner
I want to support user accounts
Scenario: login
Procedural | | How |
-----------|----------------------------------|--------|
↓ | When I go to the home page | ↓ |
↓ | And I fill in login with 'me' | ↓ |
↓ | And I fill in my password | ↓ |
↓ | And I press submit | ↓ |
↓ | Then I should be logged in | ↓ |
↓ | | ↓ |
↓ | When I go to the home page | ↓ |
↓ | And I login | ↓ |
↓ | Then I should be logged in | ↓ |
↓ | | ↓ |
↓ | When I login | ↓ |
↓ | Then I should be logged in | ↓ |
-----------|----------------------------------|--------|
Declarative| | Why |
-----------|----------------------------------|--------|
Here we see a simple feature being refactored down to its bare minimum. The final feature format may make you uncomfortable
When I XXXX
Then I should be XXXX
seems to simplistic to be valuable. However in practice finding a good XXXX is really useful, and expressing basic functionality in this way is a great starting point for further exploration.
For example we can start dealing with failure very easily
When I login badly
instead of putting in fake credentials into a table.
So what do we get when we apply this sort of technique to a large set of features?
- A very succinct specification of what the application should do and why it should do it.
- No indication of how the application should do something.
- Features that are technically very easy to turn into step definitions
- Features that are very readable
- Features that have just the right amount of information
This last point is contentious. I know many people feel that features need to have more information in them. In particular the idea of features needing to have descriptive examples so you can explore how to do things is a strong argument. However I think this exploration and description is best done by implementation, review and iteration. If you iterate very quickly you don’t need to explore the how up front, you can explore how things are done as you go along.
Why Would You Be Uncomfortable with This
Agile in general is not comfortable, and working in this way builds on that. This discomfort shows itself as
-
the need to plan what will happen, rather than reacting to what is happening.
-
the need to specify how things will be done, rather than provide feedback on how things are being done
-
the need to micro manage rather than delegate responsibility
-
the inability to trust