![]() |
![]() ![]() |
Requirements review must involve representatives of both the customer(s) and the development team, as well as any necessary managers. The goal is to achieve basic agreement among all parties that the use cases, together with the domain model and whatever prototype elements are in place, capture the functional requirements of the system. This works best when everyone is in a room together, with a facilitator/moderator who keeps the conversations on track and a scribe who records the results and the action items. The key word is traceability: it should be clear how each requirement traces into one or more use cases, and how one or more classes from the domain model and one or more elements of the prototype work together with those use cases to address the requirement.
One of the fundamental questions that every development effort must ask is this: What are the real-world objects we need to model, and how do they relate to each other? Within the ICONIX process, domain modeling forms the foundation of the static part of our UML model. When we build a domain model, we start by trying to identify abstractions in the real world-that is, the main conceptual objects that are going to participate in this system.
When you design object-oriented software, you try to structure your software around these real-world, problem space objects because the real world changes less frequently than the software requirements. The basis for our whole object modeling activity, particularly the static modeling part of the activity, is a model of these problem domain abstractions. You're going to evolve the initial class diagrams that show the domain model to the point where you can code from them, so it's critical that you capture the key abstractions early and effectively.
Another of those fundamental questions for a development effort is this: What are the users of the system trying to do? During use case modeling, and, by extension, requirements review, we're going to focus our efforts on trying to nail down our users' behavior in great detail, because the software behavior is dictated by the user requirements. In other words, what we need the software to do depends on how the users are accessing it and what the users are trying to do. Keep in mind that the more well-defined the system behavior, the easier it's going to be to build the system.
As you can see from Figure 1-1, we think it's a good idea to use prototypes to help define the use cases. We encourage our clients to use rapid prototyping as frequently as possible. The idea is that developers and users sit down together and build something that will demonstrate "proof of concept." However-and this is the big "however" that separates us from the eXtreme Programming (XP) community-don't mistake your proof of concept prototype for deliverable, shippable software-even if you've run some unit tests 300 or so times-unless you're fond of your users pressing Ctrl-Alt-Delete when confronted with the "blue screen of death."
Proof of concept prototypes are built with the goal of rapid delivery at the expense of robust, "bulletproof" design. When you're trying to demonstrate proof of concept, you're trying to get something that looks cosmetically close to what your users might be seeing built, as fast as you possibly can. So, you're likely to "do the simplest thing that can possibly work," to borrow a catchy slogan. It's like bringing in a construction crew to put up a movie set: They can build a "house" (actually a facade of a house) that looks fantastic from the outside, in just a small fraction of the time it takes to build a real house, but imagine trying to refactor this movie facade into a real house. For a real house, you need blueprints, electrical schematics, and plans for the plumbing. Always keep in mind that your proof of concept prototypes are just like movie set facade houses. What do you do if you have pointy-haired management that can't tell the difference? It's simple. Don't build your prototypes in code. Just work with pencil and paper line drawings. Some of our clients use an abstraction of the GUI called an interaction flow diagram very effectively for this purpose. This is essentially a large sheet of paper that shows small line drawings of the screens and the options for navigating among them.
Taking this idea one step further, we've found that exploring the graphical user interface (GUI) design in parallel with the required system behavior is generally an excellent approach. This involves iterating, with the users, the presentation aspects of the system, and after achieving closure on a couple of screens, writing the associated use cases. This bouncing back and forth can be very effective in the right environment. You should extend this thinking to your requirements review: the text for a given use case should match up well with the associated GUI element(s), in terms of the use case's descriptions of the basic nature of those elements and the system's responses to actions that the actor performs.
Some prominent people in the object-oriented (OO) community advocate the opposite: They insist that you shouldn't talk about GUI specifics in your use case text. They also insist that you shouldn't talk about much of anything specific, that you should leave your text as abstract (or teleocentric, which means goal-oriented) as possible. ("Teleocentric" is our favorite new vocabulary word.) We believe that you can't drive an abstract use case down through code nearly as effectively as you can drive a specific use case. You shouldn't talk about whether this field contains a set of radio buttons, or that window has both vertical and horizontal scroll bars in your use cases, but you should definitely talk about the "call and response," of actor and system, respectively, and you should name the objects that come into play, as well. Doing this is the best way to ensure a high level of traceability of your use cases into your analysis and design.
You should also do a grammar check on your use text during requirements review. A use case is most effectively stated from the perspective of the user as a set of present-tense verb phrases in active voice. The tendency of engineers to use passive voice is well-established (know anybody who writes like this: "The engineer shall use passive voice to articulate all possible behavioral options that may be presented by the system."?). However, as we just said, use cases should state the actions that the user performs and the system's responses to those actions, and this kind of text is only effective when it's stated in active voice.
Another critical aspect of use case modeling involves alternate courses of action. As we explained in Chapter 3, it's very important to think of all possible alternate courses of action for each use case wherever possible, which should be a large majority of the time, by asking, "What else can happen? Are there any other things that can happen? Are you sure?"
As we described in Chapter 3, you should also stay away from long, complicated use case templates that have spaces for the likes of preconditions and postconditions along with many other things that tend to be redundant at best and annoying at worst.
![]() |
![]() ![]() |