Monday, May 16, 2011

The problem with use cases

The greatest benefit I get from use cases is that they focus on the user. Use cases help me to think about what the user wants to do instead of only focusing on implementation details.

The biggest problem I have with use cases is that they are not structured. They are basically free text. For instance, if we have a use case Withdraw money from ATM, we may define that it has a precondition that Open account is performed, but we don't get any help from the method to see that.

What happens if someone later changes the Open account use case or defines a Close account use case? How do we find which other uses cases that need to be modified? We can look through the old use case diagrams and find dependencies, but I can almost guarrantee that these dependencies have not been maintained after they were initially created.

The solution to this is to connect the use cases to an object model. I don't mean a use-case realization with view and controller objects like ATM_Screen and ATM_Session, I mean the model objects from the problem domain, such as Customer, Account and Transaction. These are the terms you use when you discuss the functionality with actual users.

If you model the Withdraw money from ATM use case as objects, it could be something like this:
  1. You have an Account object with balance $1000.
  2. You insert a card in an ATM and enters the pin code 1234.
  3. You withdraw $100 from the ATM.
  4. Afterwards, the Account balance is changed to $900 and a new Transaction is created.

To find dependencies between this use case and other use cases, we ask where the Account object and balance came from. This is something to discuss with the client or end users. They may answer that you can open an account and deposit cash.

The Open account use case can be modeled as follows:
  1. The customer gives name and address and shows id to a teller.
  2. Create an Account object.

The Deposit cash use case can be modeled as follows:
  1. You have an Account with balance $0.
  2. The customer gives the account number 12345678 and $1000 in cash to a teller.
  3. The Account balance is updated to $1000.

There you have the dependencies between Open account, Deposit cash and Withdraw money from ATM: They all use Account objects.

Analyze objects to find more functionality

We can continue with our analysis by asking questions such as:
  • Can the balance be changed in any other way than Deposit cash and Withdraw money from ATM?
  • Where did the Account number come from? Can it be changed?
  • How is the pin code set?
  • Can Accounts be deleted?
  • In which ways can you read Account numbers, balances and pin codes?
  • How can Transactions be created, updated, read and deleted?

The questions above deal with creation, deletion, update and reading of domain objects. They will help to discover more functionality, which can be analyzed further, and so on, until you have a very complete functional specification.

There are a few more questions that can be helpful to discover more functionality. They are based on 4 kinds of classes: People, places, things and events.
  • Ask which people will perform the various functionality. This will help us to model users, roles and privileges.
  • Finally, ask which information to store about user actions (events). Transaction is such a class that stores information about changes of Account balance.

This method is a fast way to come up with lots of requirements which would otherwise take days or weeks of brainstorming. It is similar to use cases in that focuses on what the users can do. But it is different in that it models this as objects. Therefore, I am calling this method object cases.

What exactly is an object case?

An object case is a use case scenario connected to domain objects. It consists of 4 parts:
  1. Initial objects
  2. Input
  3. Output
  4. Result objects

The input, output and objects are specified with concrete values. In my experience, this improves communication with clients and end users, because it reduces misunderstandings and help to find missing details.

Object cases are also a great help for developers; they have all the information they need in the object case and don't need to ask for clarifications so much.

Testers can also benefit from object cases. Instead of writing test specificiations based on use cases or some other abstract requirements, the object cases are ready to test.

Objects can also be used for project planning: Develop the functionality around a domain class together. Start with the function that creates objects of that class.

Tuesday, May 10, 2011

Getting the requirements right with object cases

One of the biggest problems in software projects is poor requirements. We always seem to misunderstand what the user is really trying to do or discover some missing functionality at the end of the project. Agile methods reduce this problem with short feedback cycles to discover misunderstandings early, but it would be even better to get rid of the misunderstandings before implementation.

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:
  1. Initial objects
  2. Input
  3. Output
  4. Result objects

A typical week using object cases can be as follows:
  1. Monday morning: Go through new functionality with the client.
  2. Monday afternoon: Planning and estimation.
  3. Tuesday: Implement automatic tests.
  4. Wednesday - Friday: Implement the actual functionality.
My experience is that object cases help us a lot in all this activities. When discussing requirements, the objects generate questions such as "How do I find this object?" or "When is this object created?" These kinds of questions helps us to discover missing functionality early and saves us lots of rework.

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.


I 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:

Jane Enrolls in Seminar
  1. Jane enters her name: “Jane Jackson” and student number: "111-222".
  2. System displays the available seminars: ENG 103, COM 402.
  3. Jane chooses seminar ENG 103.
  4. System calculates and displays fees: $800
  5. Jane indicates she wants to enroll.
  6. System enrolls Jane in the seminar.
  7. System sends a bill to Jane Jackson with the following content: ENG 103, fall 2011, $800
  8. System prints an enrollment receipt: Jane Jackson, ENG 103, fall 2011.

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:

Enroll in Seminar
Basic Course of Action:
  1. Student inputs her name and student number.
  2. System verifies the student is eligible to enroll in seminars. If not eligible then the student is informed and use case ends.
  3. System displays list of available seminars.
  4. Student chooses a seminar or decides not to enroll at all.
  5. System validates the student is eligible to enroll in the chosen seminar. If not eligible, the student is asked to choose another.
  6. System validates the seminar fits into the student’s schedule.
  7. System calculates and displays fees.
  8. Student verifies the cost and either indicates she wants to enroll or not.
  9. System enrolls the student in the seminar and bills them for it.
  10. The system prints enrollment receipt.

(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.


The 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.


The 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:
  1. Can all output be calculated from the objects?
  2. Is all input used to find or modify objects?
In the example above, this becomes:

Jane Enrolls in Seminar
  1. Input name: “Jane Jackson” and student number: "111-222". (Used to find a Student object.)
  2. Output available seminars: ENG 103, COM 402. (Calculated from the Seminar objects.)
  3. Input seminar ENG 103. (Used to find a Seminar object.)
  4. Output fees: $800. (Calculated from the Bill object.)
  5. -
  6. -
  7. Output bill: ENG 103, fall 2011, $800.
     (How is 'fall 2011' calculated? We need to add this to the object model, perhaps in a new Term object.)
  8. Output enrollment receipt: Jane Jackson, ENG 103, fall 2011. (Same as above.)

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.