A pervasive problem in software development is finding the line between what is a sufficiently detailed description of a product requirement and describing the "implementation details" of that requirement. Put simply; it is a problem of finding the line between what and how. A product requirement should contain everything about the "what" (and leave no part of the "what" missing), and contain nothing about the "how".
This is a basic problem that anyone going through "agile training" is familiar with. A "user story" should express "what", not "how". But in my experience, the training programs just state this as a principle, then move on. This would be like a training course on "how to make the world a better place" taking one sentence to say, "just cure cancer", then move on to the next slide.
The problem is we don’t know how to do that! What does finding the line between "what" and "how" look like? What items can we check off, that tell us we have successfully found the line? What red flags suggest that we have misplaced the line? By glossing over it so quickly, this problem is presented as if it’s easy, maybe even trivial, to find this line.
Have you ever heard endless arguments going on between product owners and developers about whether a specification is too "implementation specific", and whether or not to call something an "implementation detail" or not? Personally, I’ve lost track of them all, because it happens all the time. Since everyone is handed the instruction to find this line, but given no training on how to do that, usually these arguments go in circles.
The Coffee Example
A common example used in the industry to illustrate the dividing line is the "cup of coffee" requirement. If someone wants a cup of coffee, then the requirement should be, "I want a cup of coffee." The requirement should not be, "I want you to walk over to the coffee machine, pull out a jar of coffee grounds, place a filter in the coffee machine, place the coffee grounds into the filter, add water to the machine, then press the one button, wait for the coffee to finish brewing, then grab a coffee cup, pour the coffee into the cup, then walk over to me, and hand me the cup."
The point is to illustrate what it means to inappropriately provide implementation details. If what I want is a cup of coffee, then whether or not I am satisfied is not defined by whether all those instructions I just listed were carried out. There are other ways a cup of coffee can be made (for example, buying it from a store, or using an espresso machine, or a french press, etc.). It may not be possible to follow those exact instructions (maybe there is no jar of coffee grounds), but there is a way to modify the instructions to still satisfy the actual requirement (go to the pantry and pull out a bag of stored coffee grounds and refill the jar).
Stating the (or rather, a) "how" instead of the "what" leads to brittle specifications: whether they are satisfied or not doesn’t really relate to whether the product owner is satisfied. Quite simply, such a requirement is wrong. It is not correctly expressing what is actually "required". In the context of software and BDD in particular, if we express that sequence of instructions in Gherkin, and use that to write a test, we get brittle tests: tests that end up being meaningless and just create noise and wasted effort in maintaining them. Brittle tests, unfortunately, can lead to teams souring on the very idea of test automation. But automation isn’t the issue. Even if manually run, these tests are brittle.
This example may suggest that the line between "what" and "how" is obvious. But the obviousness of the line was built into the example. Remember what I started the example with: if someone wants a cup of coffee. I provided the actual requirement at the beginning of the example and then compared it to an obviously different specification. Really, this example is just showing us that taking a requirement, and starting to fill in details about a way to do it in the product specification, is bad practice. But we’re facing the much bigger problem of: what are the requirements? We don’t know them ahead of time. That’s what we’re trying to figure out!
Is "I want a cup of coffee" really the requirement? Well, maybe. But maybe not. Maybe any cup of coffee won’t do. Maybe I specifically want a cup of drip coffee, because I don’t like espresso. But maybe that still isn’t enough. Maybe I, for whatever reason, particularly like the coffee brewed from that particular machine. I don’t know why, there’s just something about it. In that case, the requirement is to brew a cup of drip coffee from that particular coffee machine.
As you can see, what we would call "implementation details" if all I wanted was "a cup of coffee", have now become genuine product requirements. There’s no rule saying that I, the coffee aficionado who originated this requirement, can’t be concerned with the details of how the coffee is made.
That doesn’t get rid of the problem; it just moves it. If my requirement is "make a cup of drip coffee from that particular machine", the other details about getting grounds from the jar or handing me the cup at the end are still "implementation details." Let’s say I thumb my nose at pre-ground coffee and insist it is ground fresh. In that case, where the coffee comes from becomes a requirement, not an "implementation detail."
We can go the other way too. What if what I want isn’t coffee at all? What if the requirement is really that I would like a hot beverage? If that’s the case, then "a cup of coffee" itself becomes an "implementation detail." It all depends on what exactly the requirement is. What if the requirement is really that it’s cold outside, so I want a way to warm up? In that case, "a hot beverage" becomes an "implementation detail".
This is why I can’t give you some algorithm or checklist for looking at a particular acceptance criterion and deciding if it’s an "implementation detail" or not. Ultimately, what makes something an "implementation detail" is who are the stakeholders. If anyone except the developer is invested in a part of the requirement, then it is not an implementation detail, no matter how technical it may be. Something only becomes an "implementation detail" when the developer alone can completely change it, and no one else, including the product owner and tester, would care (they may not even know). If a developer changes something and that causes a bug to be filed or the product owner to reject a delivery, then it is not an implementation detail.
Discovering the Requirements
Even after going through those examples, I have still oversimplified the problem. In my examples of the overly picky coffee addict on one hand, and the very flexible guy who hates winters on the other hand, they all still supply the "real" requirement upfront. All of my examples have been, "if the requirement is X, then…" These examples serve only to illustrate that whether something is an "implementation detail" or not depends on the requirement. I cannot, for example, state as a universal rule that "use a MySQL database instead of Couchbase" is an "implementation detail." It is entirely possible that the type of database we use is a business requirement. An example would be if we are building a business-to-business app, and the client wants us to use MySQL so they can integrate their own systems directly into it. If that’s what they’re hiring us to do, then we can certainly debate whether it’s a sensible requirement, but we can’t just decide that it isn’t the requirement.
But I still haven’t even touched on the real problem. When developing a product, we don’t know the requirements. When I say "we", I am including the product owner. The real-world problem is not so much a person who knows exactly what he wants, whether it’s a cup of drip coffee from that one coffee machine, or to just have a way to stay warm. Instead, it is a person who just feels uncomfortable, and is looking for a way to ease that discomfort. Will it be something that warms him up? Hmm, yeah, I think that’s what it is. I’m cold. Okay, well would wrapping myself in a blanket fix it? Ehh, I’m not really feeling that. My throat feels dry too. I’m thinking some kind of hot beverage will really make me feel better. Well, there’s always coffee. But that has caffeine. Hot chocolate doesn’t have caffeine. Well, actually, now that I think about it, I’m feeling a little groggy. Coffee might be exactly what I need! Should I ask the barista to surprise me, or do I know exactly what I’m in the mood for?
This is what the process of discovering the requirements might look like. Is this a personal monologue happening in the head of the product owner? Well, maybe some of it is. But then let’s say I eventually say, "okay barista, I’ve decided I actually want an espresso today. Whether it’s an Americano or Latte, surprise me!" The barista responds, "I’m so sorry, sir, but our espresso machine just broke!" Turns out my requirement isn’t satisfiable (let’s assume it’s a hard requirement that I don’t have to drive to another coffee shop). Then I might ask, "okay, does your drip coffee machine work?" If she answers yes, I’ll change the requirement to a cup of drip coffee. If she says no, I’ll have to change it to something else. I may even decide they don’t have anything I want. I’ll have to revisit how to warm myself up. Maybe a blanket will do for now, if coffee isn’t (practically) an option.
What is going on here? A conversation between the product owner and the developer. The product owner will come to the developers with some kind of idea. But this idea is often impossible to actually build…impossible isn’t the right word, let’s say too expensive. That forces the requirements to change. It’s obvious when we say it out loud, but this spoils the whole idea that "what" and "how" live in entirely separate universes. They don’t. They both feed back on each other. How much about the requirements for a mobile app depend on the technology that goes into a mobile device? Well, a lot! The designer has to make a "startup screen" to deal with the fact it takes time to initialize the app. The unreliability of internet connections forces designers, and product owners, to deal with "error alerts." The fact mobile devices have multi-touch screens causes product owners to imagine a scrollable list of items, with no visible scroll bars. The app that product owners create would be completely different if it targeted a different technology.
Here’s another thing that can happen. I say to the barista, "I want some kind of espresso, but you decide exactly what." She hands me a caramel flavored latte. I look at it, then back at her, and say, "actually, I don’t want caramel flavor. Can I just get a plain latte?" Great, the barista just wasted time and resources making a drink no one wants! That’s waste… exactly the kind of waste we’re trying to eliminate with BDD. This is exactly why developers, learning from experience, really don’t like vague requirements. The more decision about behavior gets put onto developers, to decide on their own, the more likely the product owner is going to receive the finished product and reject it.
Both agile and BDD are designed to mitigate this problem. Agile gets something into the customer’s hands sooner rather than later, to ensure that any kind of "buyer’s remorse" is discovered now, when there’s still time to go back and rework the product. BDD is designed to, among other things, help the product owner figure out whether he’s really okay with delegating something to the dev team.
Finding the Line
Let’s think about how the barista could intelligently handle a customer who says, "surprise me!" Instead of just walking off and walking back with a caramel latte in her hand, she might say, "ohh, how about a caramel latte? That’s my favorite!" That gives me the opportunity to say, "oh, well, no I don’t want any flavor." Awesome. We just figured that out before she wastes time making a caramel latte (in BDD lingo, the discovery was shifted left). Then she might say, "oh okay… hmm, how about a regular latte then"? She can keep asking my questions until I finally answer yes to a specific drink. She might keep pressing me… "okay, so you want a regular iced latte. We have two kinds of espresso, regular and blonde. Wanna try the blonde?" At this point I might say, "oh I don’t care, either is fine." She might say, "are you sure?" I’ll answer "yes." Hopefully, this process has helped me figure out exactly what I care about, and what I don’t. The chances of the barista not knowing what I want, and coming back with a drink I don’t want, are minimized.
BDD is commonly presented as a way to minimize the risk of misunderstanding. It certainly does accomplish this. By going through the exercise of expressing requirements in Gherkin, any potential for a situation like, "I said I wanted a latte, but you gave me an iced latte" are minimized. But it is instructive to think about how BDD does this. It does so by forcing the conversation about detais to happen sooner. This causes the details to get filled in, or to get explicitly and consciously marked as "not important." But this conversation has another very important outcome: it helps the product owner realize he wants (or doesn’t want) something, that he wasn’t aware of.
This is how you find the "what" vs. "how" line. It is the result of a conversation between the stakeholders and the dev team (that includes testers). The product owner has the tendency to drive the line "up" (toward being more abstract and less specific), while the developers have the tendency to drive the line "down" (toward being more concrete and more specific). The idea is to discover every detail for which any stakeholder (customer, product owner, architects, marketing, legal, government regulators, etc.) is invested. The details most often enter the conversation through the developers. Devs are (they must be) detail-oriented, and are the most likely to think of all the tiniest minutiae that will need to be decided when actually turning an idea into a working product. They will drive the, "what about this, what about that…" questions, and the stakeholders will answer.
Developers will also drive considerations about complexity or cost, which will feed back into what the stakeholders choose. In this way, as many details as possible will be considered and either added as an acceptance criterion, or officially marked as an "implementation detail", which delegates it to developers to decide however they wish. The most important element here is that the delegation to developers as "implementation details" is explicit, not implicit. Instead of realizing later that something was never discussed, and therefore left up to the dev team to interpret, hopefully everything is discussed. If something ends up being an "implementation detail", it’s because we brought it up and consciously decided so.
By throwing darts all over the board and marking each one as being on "this" or "that" side of the line, you find the line.