In my last post I offered a concise snapshot of how I’m practicing Behavior-Driven Development. Based on feedback, it was probably a little too concise and meta to provide any kind of valuable takeaways or discussion points, so I’m going to unpack what I said there over a few, more-specific posts.
I’ve experienced success with BDD as an integrated component of a larger suite of Agile practices. Specifically I see BDD as a mapping activity between user stories and code. Think of an iteration or sprint as a pipeline: you put stories in at the beginning and the necessary code comes out at the end. The BDD process starts before you put stories into an iteration; you provide acceptance criteria (in many forms, more on that later) in order to understand the nature and implications of the story. These acceptance criteria then serve as a context for the developer in modifying a codebase.
To be clear: specifications describe code and a developer specifies the code.
Think of story structure, in this light, as an aggregate root. One story has zero-or-more acceptance criteria. Acceptance criteria come in many flavors. Falling back on the object oriented metaphor we can say that a specialization (or subclass) of a criterion is a “User Interface Prototype.” We can define another specialization as the “Scenario.”
Now we’re all probably familiar with these scenarios. They’re the ones given in Dan North’s introduction (and many others), something like:
After depositing $100 dollars into an Account with a balance of $0, the balance should be $100.
Sidebar: you’ll note that I’m not a big fan of the Given/When/Expect formalism or even the less restrictive when/then format. Story scenarios should read like Plain Old English (POE). Well maybe not plain OLD ENGLISH: whence ye olde account hath taken deposit.
I’d contend that these are bad examples, the plague of our industry. You might find this exact scenario appear in an executable class specification several times. It might surface as a specification of an Account entity in a model. It might also match a specification of a controller pattern in a presentation layer. Are the two the same? Nope. Would you express that surface duplicity in the story. Surely, no.
Furthermore we’ll have a number of technical or infrastructure things we need to do. Our end user won’t care about that. Sorry, you can try to make them, but they won’t. They certainly won’t author those specifications. It’s up to the developer, when working on a story as a vertical slice through a system or through multiple components in a non-monolithic application to author specifications while working. The process of writing specifications continues past the process of estimation and admitting a story into an iteration.
So, yes, mapping is what we’re doing here. Mapping and continually adding specifications. We’re mapping specifications that came in to an iteration to things like the presentation layer and the domain model. We’re developing specifications and subsequently mapping them to infrastructure bits to fulfill a complete, working feature and we constrain ourselves to just doing enough to make that feature “potentially shippable.”
Define: “Behavior” and “Specification”
What exactly is a behavior? Is a behavior a feature? I vote no. I like to think of a behavior as the smallest possible expression of one (and only one) thing that a code artifact accomplishes. Sometimes that’s a state change in a single object and sometimes that’s a collaboration between multiple objects. Sometimes a behavior will be technical, sometimes domain-specific or business oriented.
Features, on the other hand, are closer to stories. A feature (not always, but usually) will require a family of behaviors be present to work. And not all features are created equally. Users tend to think of features as larger workflows. These larger features, epics or I’ve taken to calling them narratives, are sometimes a little big for a small, tight iteration so I try to break them down to the smallest possible story that’s still readable, understandable, and able to be prioritized by an end user.
For me specifications describe behavior and behavior is a description of code: classes in an object system. It’s a happy side-effect that sometimes our domain model behaviors mean something to an end user, but an Account entity with a fully functional deposit method does not a feature make.
Where’s the value?
The flavor of BDD I’m talking about are class specifications. That’s to say that I had the best outcome by trying to derive value from BDD on a technical front. We take a story, provide enough acceptance criteria in the form of scenarios to estimate, and use those scenarios to create executable specifications that prove our code’s behavior.
It’s a little software value chain.
The value from this process is tremendous. First we get our refactoring safety net. By having a well specified codebase we can make changes with aplomb. We now have a nice regression suite and we get all of the quality benefits of unit testing and the design discipline of TDD.
What sets BDD (and specifically this class specification style of BDD) apart from TDD or unit testing is the fact that our specifications are now documentation. The create a localized codebase that can be entered by any developer: we’re closer to collective ownership. It does it in a way, however, where we can now start talking in a kind of mapping language. That mapping language involves both the ubiquitous language of the domain model(s) we have and the vocabulary around recipes a team will evolve for infrastructure (“oh, hey, use the Logger”).
It’s Not Over (Sorry)
This is a huge topic. I’m afraid I have more to say on the subject but in the interest of getting this out there I’m hitting the publish button. As a final sum-up, I’ll say that in my experience class specifications are the way to go.
Viewing BDD in this light has immediate benefits. I’m not throwing out the possibility that executable acceptance tests, “story runners,” or FIT-hybrids are a bad way to go, but I think they’re much more toward research and development. Class specifications done in a BDD style are the real deal. They work in the hear and now, so that’s where my enthusiasm and effort is directed.
I’ll unpack my theories about story runners in a future post. I’ll also talk a little bit about working vertically with BDD and this concept of Iteration I/O. We’re trying a few new things at my company that should provide some empirical basis for how we’re tackling questions around user documentation, acceptance testing, etc.