So lately I’ve been reading the beta version of the RSpec book which is supposed to come out last year, and after reading the philosophical chapter 2 that talks exclusively about Behavior Driven Development, I decided to take some notes and post them. Like my other reviews, I’m writing this mostly as a quick reference guide that I can check from time to time and reinforce some concepts and I suggest everyone who decides to read this to do the same.
First there’s an introduction on agile methodologies and how they came to be, so if you’re just interested in the BDD part, click here and jump right to it.
The chapter starts by mentioning how ‘traditional projects’, that is, those who do not apply Agile methodologies, fail. Usually, it’s because of one (or more) of these reasons:
- Delivering late or over budget
- Delivering the wrong thing
- Unstable in production
- Costly to maintain
Ok, so, why? As we know most software projects go through the sequence of Planning, Analysis, Design, Code, Test and Deploy. The biggest reason for all this organization to happen is so we can avoid big changes later in development, which may screw up the whole project or at least give us a huge repairing cost. We don’t want that. So we make sure everything is ‘perfect’ by writing gigantic sets of documents to specify what each little functionality does and that we are predicting every single detail in the system.
Alot of people manage to work like this and others try to improve the process by having wonderful ideas such as creating review committees and stablishing standards and whatever. Even so, mistakes do manage to get by and when something gutters up in the testing phase (where everything is supposed to be unicorns ready to go into production) such as an entire feature that was overlooked…then everyone goes mad and the whole process needs to be redone and reviewed etc etc etc.
As you can see, what seems to make the process not work is the way the process is being executed in the first place! We can understand why we’re taught to do things this way — people simply thought: “hey! here’s something brilliant, how about we apply the same concepts of civil engineering on software and turn it into ‘software engineering’?!?!”. It makes sense to spend a huge amount of time thinking about how do build an entire building before actually starting to build it, realizing that you needed an extra pillar to hold the building after getting the third floor done is not cool. The difference is that software, and I quote the book on this, ‘is soft’, it’s supposed to be malleable to change and not to stay the same way forever (such as a building), so you can see how we’ll be needing a redefinition of things.
That’s where Agile comes in. First, read the Agile Manifesto. Read it like 50 times. In short, it values ‘doing software’ instead of mostly documenting it. One of the central principles of agil development is the use of iterations, which work like mini-projects: instead of delivering a final grand piece of software, you deliver small pieces of it as development evolves. This helps us solve those first four problems traditional projects encountered:
- No longer delivering late or over budget: iterations help us predict how long we’re gonna take based on time spent in each iteration vs the number of iterations we defined.
- No longer delivering the wrong thing: since we’re delivering working software from time to time we can get feedback from our stakeholders and change anything that was requested with ease.
- No longer unstable in production: by delivering on each iteration we are making sure that our software is constantly working all the time.
- No longer costly to maintain: after the first iteration everything becomes maintenance, so the team is always worried about keeping everything working continuously.
But not everything is marshmallows, agile development is, well, hard. Keeping a team organized enough to launch software every week or so is tense. The good news is that since agile is not a recent practice, most of its problems have answers:
- Outcome-based planning: all we know is that everything is bound to change, so we need to find a way to estimate despite all this uncertainty.
- Streaming requirements: creating large documents of requirements won’t be able to keep up with our new delivery process, so we need a way of describing features more rapidly.
- Evolving design: with the project changing in each iteration we’ll need to always keep redesigning our software as it shapes up.
- Change existing code: as the project changes so does the code, and being able to refactor the code and add new functionalities to it without much difficulty is essencial.
- Frequent code integration: everything needs to keep working together.
- Continual regression testing: as new features are added and code is refactored we need to make sure all the work already done keeps on working and the tests keep on passing.
- Frequent production releases: all previous aspects are behaviours we can adopt ourselves, but releasing working software frequently requires co-ordination with the downstream operations team who have to keep a formally controlled environment into place. But still, we need this and if we can’t get this right then everything else doesn’t really matter because software only starts making money when in production.
- Co-located team: for everything to work you can’t afford to waste time on office bureaucracy, everybody even remotely connected to the project need to be in touch for easy communication.
Behaviour-driven development is about implementing an application by describing its behaviour from the perspective of its stakeholders.
To help us understand the perspective of a stakeholder we use a technique called Domain Driven Design, and keep in mind that a ‘stakeholder’ is anyone interested in the project. A huge premisse behind BDD is ‘writing software that matters’, which is exactly what we can acomplish from viewing this from a stakeholder’s perspective, because this way we know that what we’re doing has value. To help us focus on what’s really important, BDD follows three principles:
- Enough is enough: simplicity, the art of maximizing the amount of work not done, is what we aim for.
- Deliver stakeholder value: if something is not delivering value nor is it helping you deliver value, forget about it and aim for something important (to the stakeholder!).
- It’s all behavior: whether you’re designing or coding, remember to always keep in mind that we’re dealing with behavior, it’s not about what something is, it’s what it does.
Cool, we know all the theory behind BDD, and how do we apply that theory? Since BDD has major focus on stakeholders, we start from them. The first thing to do when creating a project is gathering the stakeholders and stablish a vision (or purpose), which will be the overall goal of the project. Of course this is something extremely high level but it keeps us reminded on what we’re aiming for in the long run. For instance, the vision of this project I’m developing is to “integrate the CRM to our specific business needs”.
The book also uses the concept of incidental stakeholders which are those who will help the core stakeholder’s problem. In short, core stakeholders define a vision and incidental stakeholders help them understand what’s possible, what cost and with what likelihood. After defining the vision, we continue on working with the stakeholders to define goals (or outcomes), which are tangible achievments that we’ll need to address in order to know that we’ve reached our final purpose. To help keep these outcomes objective enough we could use a set of characteristics called SMART, which stands for Specific, Measurable, Achievable, Relevant and Timeboxed.
To get to these goals we’ll need solid software, and to describe what the software will do to achieve them we use feature sets (or themes), which are composed of, you guessed it, features, which go down to the level in which we work on day-to-day. In a nutshell, a feature adds value to a feature set which is included in one of the goals that achieve the overall purpose of the project. This way we are certain that what we’re doing is somewhat connected to the big picture we’re trying to solve. Here’s a badly drawn diagram to show that small hierarchy:
In a more practical side of BDD, various roles work together to get an amount of work done, so a BDD delivery cycle would work something like this: a stakeholder and a business analyst discuss requirements in terms of features that make sense to the stakeholder (DDD helps alot here) and probably breaking them down into even smaller chunks called stories (which take no more than a few days work). Next the analyst talks to a tester to define the stories’ scope, remembering to do just enough to get it done. Finally the developers then implement only enough to satisfy those determined scopes, and no more (this is where Red, Green, Refactor comes in).
Getting a bit more specific on the development phase (which is the one that matters most to all of us devs anyway =P), BDD emphasizes the importance of automating these scenarios and that they should still be understandable by stakeholders (Cucumber is largely used here). The developers should focus on coding by example, which is basically TDD with a laser-sharp focus on behavior, so you write a code example by describing the behavior you want and then implement just enough code to make it work (this is where RSpec, for Rubyists, comes in) and we iterate through this process until all scenarios are done. This way we have working scenarios that we can demonstrate to the stakeholder and the story is done.
Since we work with stories (chunks of features) in a day-to-day basis it’s important to know deeply about them. A story is made up by 3 things:
- Title: so we know what story we’re talking about.
- Narrative: tells us what the story is about and should at least include a type of stakeholder, benefit and a description of the feature. There are 2 formats people usually follow to narrate their stories, the first one is the Connextra format: As a |stakeholder|, I want |feature| so that |benefit|. — and a similar format that focuses more on the benefit: In order to |benefit|, a |stakeholder| wants to |feature|.
- Acceptance criteria: so we know when we are done. In the case of BDD the acceptance criteria takes form of a number of scenarios made up by individual steps. (take a look at Cucumber to get a more detailed specification on this)
It’s usually a good practice to define stories before actually starting an iteration and that all the stories uses the language of the stakeholders so everyone uses a consistent vocabulary.
Summarizing this whole process in a nutshell: we start a project by understanding its purpose and nailing it down into smaller, doable features and then into stories and scenarios, which we automate to keep us focused on writing software that actually matters to the stakeholder. These automated scenarios become acceptance tests to ensure the application does everything we expect, and BDD thrives in supporting this model of work by making the process of automation quite easy while clearly understandable by stakeholders.