Defining Done
People often use "building a house" as a metaphor for software engineering. Ironically, they use it from both sides of several arguments. For example: a Waterfall proponent may suggest that you don’t start swinging your hammer until you have the architectural blueprints drawn up and the construction schedule reconciled with contractors and suppliers. An Agilist would counter that you don’t have pick out the curtains before you begin pouring the foundation. Both are right (at least this specific argument). Its not good practice to dive into a software project without a plan but you don’t have to plan three years out, just far enough to set expectations for delivery.
Visualizing your Goal
Far more important that your plan is your vision. Plans should change when new information is discovered along the way. However, vision should be pretty much consistent through changes in climate and circumstance.
With software, your vision is what the end user does with the system. It is the user experience, from their perspective, for how they use the new or enhanced features. If its a small project, that’s usually easy. When its a major feature enhancement, this can be more difficult. By removing the UI from your description, you can usually be more accurate (through changing requirements) and keep the details simple.
For example:
Let’s say you are building an online flight search tool. Your description of the completed work should be: user can search for flights from origin to destination within a certain date range and optional time range. That’s pretty high level. No talk of drop down menus, page navigation, font color, etc. If you start there, you can then narrow the focus during design.
This should be done before you begin swinging your hammer. Agile doesn’t mean sprinting headlong into uncertainty. Its important to understand what means "done" before you begin.
Tests as your Benchmark
So let’s say you begin your project and you stop to define what it is that you are trying to build. You establish you high level description of a successful outcome. Now what?
Break it down into tests! If you are given a broad-scoped feature request, a logical thing to do is decompose that into smaller tasks necessary to accomplish the goal. Do the same thing from vision to tests. In the above example, you can elaborate that a user must select a date range. The second date must be equal to or later than the first. Time is not required. Same rule for second time selection, however. An origin and a destination are required. The rest of the details, you may have to discuss with the business owner to get consensus.
Once you have this list, write them in a format that can easily be implemented as input / output tests. This should be done during design elaboration of the feature. As you are designing how the program will implement the feature, you should be detailing how you will validate that it works.
This list should be converted to unit tests as much as possible. Those items that cannot should be written as automated UI tests. This should be done before you begin coding. If you have a QA department, great, they should write the UI tests and help develop the unit tests (at least in human language). If you don’t, that ain’t no free pass. Taking the time to validate your outcome before you begin will save you a tremendous amount of time and guarantee that you won’t cut corners as release time approaches. You’ll find that you are "done" sooner and that you are more "done" than if you hadn’t taken this step.
Less Time Chasing Rabbits
Another benefit of this practice is that you can produce executable documentation for your feature. Yes, it lives with the code and continues to validate the business rules you worked so hard to support. Just as importantly, you will have something to share before you have a screen to show. Anyone involved in the project can review those rules and find an opportunity to add additional detail or call out a conflict. If you have just begun to build your object layer and someone informs you that login is required to access the feature, you don’t have to toss a bunch of code around to support that. You learn earlier what needs to change and you can implement that change more easily and for a much lower cost.
How do I Test That?
The basic message to take away is that a "test" is your best way to define done. Having a test to start with will help you reach done faster. It will help you be more done and spend less time responding to "issues" found in your code. A solid, consistent practice for testing first will allow you to satisfy both sides of the "build a house" argument and reach a happy compromise between code slinging and sandbagging.
Leave a Reply