We Need to Better Define Acceptance Criteria
One of the problems with traditional specifications is that it often does not clearly delineate exactly when a feature is finished.
Join the DZone community and get the full member experience.Join For Free
Photo credit by Air Force Marathon Office
"You are done, finished. Time to move on."
How I long to hear those words when I'm working on a task. Specifications can be squishy, and it can be difficult sometimes to determine if the task is complete or not. Software developers don't want to gold plate. The problem is that we often don't know how our software is going to be used, and we don't want to it fail in the field. As a result, we often try to make our code as robust as we can. In that process, we can end up overbuilding.
But there's a solution to this dilemma. It's really easy. Define upfront what has to happen in order for the task to be completed. In other words, before you start, ask yourself how you will know when you're done? It seems like a reasonable question. Before we embark on any journey or on any task, we should ask that question because when we fail to do so, it's entirely possible that we will miss our mark. One of the problems with traditional specifications is that it often does not clearly delineate exactly when a feature is finished.
But there is a way to do this. We call them acceptance tests, and whether they're done manually or are automated, they essentially serve the same purpose: to tell us when we are finished with the task so that we can move on. Moving on is important. It gives us the opportunity to work on other tasks and even come back to the first task and enhance it later.
Building maintainable, resilient systems requires thinking about the software development process a bit differently than most people do. It requires understanding the nature of change so that we can accommodate it when it happens.
When defining "done" we have to take in several dimensions. In order for a feature to be considered done it not only has to work as expected but it has to be built in such a way that it's straightforward to work within the future. Just getting a feature to work is not good enough, not when that feature has to be maintained through time.
The software we write must be understood not just to the person who wrote it but to other professional developers as well. That means that we have to adopt common standards and practices for building code. If we're working in an object-oriented language then we have to know when to use inheritance and when not to. But unfortunately, the software industry is not as mature as other industries and professions so we're still struggling and reinventing the wheel in many places.
Today, acceptance criteria are central to my way of thinking about features. The very definition of a feature includes its acceptance criteria because that's how all know when I'm done. I often express this using the "given, when, then" syntax. This says that given some initial conditions, when a trigger occurs that invokes the behavior that I want to create, then the system will be changed in specific ways. I can then compare these results to what I expect to determine whether my acceptance criteria have been met or not.
Acceptance tests are just the formalization of our acceptance criteria expressed in the form of a test or an assertion. This can be manual or it can be automated. Again, we are simply asking the question, "How will I know when this feature is finished, what result will it produce?"
When I have clearly defined acceptance criteria for the features that I'm building then I find I waste far less time overbuilding but even more important than that I find that I can move on without worrying or feeling guilty that I haven't done enough because when my acceptance test passes, I know that I have accomplished what I set out to.
Published at DZone with permission of David Bernstein, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.