Two things that really help me in this area are examples and objects. This article describes how to combine these with a method I am calling object cases.
An object case is an example of a user function connected to domain objects. It consists of 4 parts:
- Initial objects
- Result objects
A typical week using object cases can be as follows:
- Monday morning: Go through new functionality with the client.
- Monday afternoon: Planning and estimation.
- Tuesday: Implement automatic tests.
- Wednesday - Friday: Implement the actual functionality.
A consequence of this is that the plans are really good. It doesn't happen often that we forget tasks in the plan.
Another experience is that after Monday, I hardly need to discuss anything with the client. The object cases give me all the details I need to implement automatic tests and production code without guessing.
ExamplesI always use some examples to make things concrete. This helps to clear out the inevitable misunderstandings and reveal details we did not think of.
By example, I mean a concrete example of something a user can do. For instance, here is an example of how to use a system for enrollment in university seminars:
Note that the example has a concrete user and concrete input and output values everywhere.
I have never studied in America, so I am sure there are some mistakes and missing details. But that is one of the main points of using concrete examples: It is easy to spot mistakes.
The alternative is an abstract requirement, such as a use case:
(Source: Agile Requirement Modeling by Scott W. Ambler.)
The use case above is actually very good, but the example has more information:
- A student number is in the format 111-222.
- The University has seminars that are called for instance ENG 103 and COM 402.
- A typical fee for a seminar can be $800.
- The bill includes information about the student name, seminars, semester and total price.
When I discuss the example with the stakeholders, they are likely to find errors in my assumptions and point them out. This gives me better quality of the requirements before I start development.
More importantly, examples enable further discussions with the customer, such as:
- Which information should be displayed in the list of seminars?
- Which seminars shall be listed? This may for instance be: "All seminars with seats left that the student is eligible to." An obvious follow-up question would be what it means to be eligible. Be sure to ask for some examples.
- How is the fee of $800 calculated? The answer may be something like: "A fee of $100 per term and $700 for ENG 103."
The answers to these questions will likely lead to requirements for more functionality that the system needs to support. For instance, functionality is needed to edit course fees.
ObjectsThe next step is to model these examples as objects.
In the example above, we need the following initial objects:
In the resulting objects, a Bill object should be created and a Seminar object updated:
The objects give structure to the examples. This makes it easy to find missing pieces in the requirements. They inspire more questions, such as when is the Student object created, what happens when the Bill is paid or not paid?
Just using examples and objects informally will greatly improve the communication between stakeholders and programmers. The stakeholders understand the examples and the programmers get all the information they need. Another benefit is that the examples can be used as functional tests.
CompletenessThe examples can be used to find objects, which can be used to find more examples, and so on. In this way, we can build a complete specification.
To ensure that the model is complete, we ask these questions:
- Can all output be calculated from the objects?
- Is all input used to find or modify objects?
This results in the following class model:
We can use the class model to find more examples. We need examples that create, delete, update and read all the classes.
Our example creates a Bill object. But when are Student, Seminar and Term objects created? When are these objects updated and can they be deleted?
If we ask the client, they will tell us more functionality that the system needs to have, for instance:
- Register student
- Plan seminar
- (and some more examples to update and delete objects)
Finally, we can ask the client for examples of how this information is used (read). Our example reads information from Student and Seminar objects. But when are the Bill objects read? Again, this needs to be discussed with the client. Instead of just creating a simplistic user interface with CRUD operations that displays tables of seminars, students etc, we should find out what the users really want to do. This will help us to design a good user interface.
In this case, the client might want the following functionality:
- Print a list of all unpaid bills.
- Print a list of all students in a seminar.
- Send email to all students in a seminar.
- Calculate the total seminar fees for a term.
When we make concrete examples with input and output for all this, we will probably need even more objects, and so the requirements grow. Connecting objects and examples is a great way to discover missing functionalilty.
How does this help?Examples improve the communication. They give clients, analysts, developers and testers a common understanding of what the system needs to do. They are sufficiently detailed so people don't have to guess.
Objects give structure to the examples. This helps us to make the examples consistent and complete.
Objects and examples is a great starting point for developers. Firstly, they have very detailed requirements. They don't need to guess or ask the client all the time. Secondly, the developers can use the object model as a basis for implementation. And thirdly, they can write automatic tests from the examples.
The examples are testable, so the testers can basically test the examples, but they will need to write more examples than the "sunny day" scenarios that clients and developers come up with. It is a good idea to involve the testers in defining the examples to discuss these details early.