One of the biggest problems I encounter with BDD is that it was started by developers, for developers, so that we could get a better grip on what it was we were developing.
As we began to understand the complexities of what we were developing, conversations with business stakeholders started to become more fluid. We started to understand what it was like to handle multiple stakeholders; to have uncertainty around requirements where stakeholders weren’t really sure about the outcomes they wanted; to pay to delay decisions about implementation until later.
There are three practices / principles / bodies of knowledge and experience which I use and teach as part of BDD, and I don’t think BDD works well without them. Good BDDers have taught these practices anyway, sometimes without giving them a name, so I wanted to call them out explicitly so you know that they’re there and can use their names to go find out more.
This is the stuff that happens in conversation, before developers get anywhere near a keyboard.
Feature Injection
A large number of Agile projects have backlogs of user stories. Some of these backlogs can be quite large. One team had over a year’s worth of stories, covering four walls of a room. Scrum and other Agile practitioners talk about “grooming the backlog”; reacting to their growing understanding of the real problem by removing some stories and adding more in. Even Agile teams can be sidetracked by “quick” two-week-long analysis phases, or two-hour planning sessions, or additional functionality that still fits within their deadline when they could have shipped three weeks ago.
What if you didn’t have to do this?
Lean proponents talk about minimum viable products or increments, in which we determine the smallest thing that could make a difference to the problem, then do the minimum necessary to ship. Feature Injection, introduced to me by Chris Matts, is a fantastic technique for discovering that minimum. Here’s how it works.
- Every project worth pursuing has a vision – either something new, or something that you’ve seen someone else do and you want to do it too. The vision is designed to increase revenue, decrease costs or protect revenue – for instance, keeping customers from going to a competitor (note that there’s no ROI for a vision like that!)
- There may be other stakeholders whose goals need to be met in order to allow the vision to go live. Frequently these stakeholders have traditionally gatekeeping roles – UAT, Architecture, Legal, Security. By recognizing these stakeholders early, we get a chance to turn them into educators instead.
- To meet the stakeholder’s goals, we create capabilities. For instance, employees might need the capability to book a holiday. Notice that they could quite easily do that with paper! To make our differentiating vision compelling, we may need a certain amount of commoditised functionality – things that people will expect in that kind of application. When David Anderson talks about differentiators he uses the mobile phone market. An example of a differentiator is the first ever camera in a phone. We’ll also need to be able to make calls, receive calls, look up numbers, etc.
- To deliver the capabilities, we design features. We may decide that some features are too complex, and create manual workarounds instead. The features represent the way in which users will use the capabilities we’re giving them – through a browser, a windows client, a mobile phone, etc. Now we’re starting to move into the areas of UI design, preferably with a UI designer, and developers and testers can really get involved if they weren’t already! Even if the development team wasn’t involved in the conversations before this point, I recommend they should be aware of the outcomes and able to map their features back into the capabilities, stakeholder goals and initial vision. Even better, the team might only have the capabilities on their backlog – breaking them down into features as and when they reach the next capability (see Deliberate Discovery for prioritisation).
- To really explore the features, we talk through scenarios; examples of the outcomes a system should produce when a user uses it in different contexts. We can use the scenarios to decide what we want to get feedback on, and thus divide the features into stories. The main purpose of dividing things into stories is to be able to get feedback quickly.
Scenarios are the BDD artifacts people are most familiar with, but look how much happens before we even get this far! And that’s without budget negotiations, portfolio management, company strategy, recruitment and all the other gubbins needed to get a development team up and running…
- After that, we can move into the traditional development space – TDD (or unit-level BDD if you prefer), code, integration and, we hope, production.
Deliberate Discovery
In Agile projects, we normally prioritise stories by their value. But wait a moment! If we’re doing Feature Injection, our vision is for the smallest valuable thing we could ship (otherwise, that smaller thing would be our minimum viable product). So we can’t really say that one feature is more valuable than another, because we need them all (and if we don’t, that’s our minimum viable product!).
What we can say, though, is that we know more about some of the features than others. Commoditised features, particularly, will have been done before, and we can probably estimate them and make predictions about them, as long as we have enough expertise in the domain. Anything that’s new, or that’s new to the team, we’ll know less about. We can bet that there are some things in there that we’ll discover as we code, some of which will come back to bite us. These are the kind of things which can really derail a project.
In the spirit of failing fast, we’d really like to have our projects derailed early, while we can still change our minds and perhaps think of something else to do instead. Deliberate discovery is the act of assuming ignorance, then going to look for it and optimizing to address it first. There will always be things we don’t know we don’t know – but since those things will usually show up in the functionality we’ve not delivered before, why don’t we do the new stuff first?
If you’re into Theory of Constraints, you know that in a production line environment, you tailor your system to the constraining machine, putting it first where possible. But software development is more like product development; it’s creative knowledge work, rather than doing the same thing over and over again. Ignorance is the constraint.
This is how we prioritise – by the features and capabilities about which we’re most ignorant. It helps us to address the risk early. Since the risky stuff is usually what keeps our stakeholders awake at night, this is a great way of establishing trust, too.
Real Options
As well as the things we don’t know, there will also be things we don’t know that we don’t know. No amount of analysis will ever allow us to discover everything! So we have to keep ourselves ready to change.
Unfortunately, we human beings don’t work well with uncertainty, and have a tendency to try and eliminate it. One of the ways we do that is to break down problems into their components. That works very well for predictable stuff that we’ve done before, but not for new things which we don’t understand so well. Doing this for new functionality only leads to the uncertainty being hidden away!
So what can we do to keep our options open, so that our ignorant ignorance doesn’t bite us?
Chris Matts took the concept of trading options – the right, but not the obligation to buy copper at $1000 a tonne in October, for instance – and worked out which aspects of options still apply to Real Life. Here are his principles:
- Options have value.
- Options expire.
- Never commit early unless you know why.
With Deliberate Discovery, we’re getting what information we can before we make a larger commitment, so Deliberate Discovery plays into this very nicely. There’s another thing we can do, though. We can pay to keep our options open. This is what we do when we take time out to design our code well or refactor it so that it’s understandable. We’re creating options for the future.
When we talk through our scenarios and we see our P.O. frowning or saying, “Um…” then we know there’s uncertainty there. It might be worth spiking out a feature cheaply, to see if it does the job, before pinning that feature down with automation (or even, dare I say, unit tests). Discovering that uncertainty and ignorance is at the heart of BDD – not finding the examples, but finding the examples we can’t find.
Another practice Chris taught me off the back of this is, “Don’t pick the right technology. Pick the technology that’s easy to change.” Whenever we have a choice and not enough information to help us make the decision, picking a decision that’s cheap to change later usually turns out to be a good way forward, as we can change when we have more information (or keep it if it turns out to be good enough!)
BDD is just TDD?
Sure, if you’re a developer, and you only get to see the stuff that happens in development. Even then, it may be worth talking through not just the scenarios, but the larger-scale picture; discovering uncertainty and ignorance, paying to keep options open, and working towards a clear and compelling vision to deliver software that’s not only well-tested and functional, but which really, truly matters.
In this post, I’ve focused on the differences between BDD and TDD, most of which have been spawned by the language of BDD which allows for more appreciation of uncertainty than the language of TDD. For the similarities, and more about the history of how BDD was originally derived from TDD, see this article.