Concepts and Use Cases
Recall the story about the Silly Game from the
third lecture.
When we jointly analyzed the story, everyone identified at least four concepts: the
game administrator, the player(s), a turn in the game, and the die. The relations
among these concepts are reasonably obvious too:
+--------+ 1 * +--------+
| Admin | ----------------------- | Player |
+--------+ 1 1 +--------+
| 1 | * | *
| | 1 +------+ 1 |
| +--------- | Turn | ---------+
| 1 +------+
|
|
+--------+
| Die |
+--------+
There is only one administrator in the game, but many players. Every single player
may play many turns during a game. Finally, there is a single die, which all the
players must trust.
We also identified four use cases:
- a player notifies the server of his desire to play a game;
- the administrator announces that enough player have signed up for a game;
- the administrator grants a player a turn;
- the administrator announces the end of the game.
Here are the actual use cases:
- sign up:
- a player contacts the administrator
- the administrator notes the player
- ... and produces and acknowledgment
- starting the game:
- the administrator notifies the players that the game is about to start
- the players nod their heads
- granting a turn:
- the administrator grants a specific player a turn
- the player decides to use the turn to roll or to skip
- the administrator notes the score
- the administrator eliminates the player or keeps him around
- the end:
- the administrator decides to terminate the game
- the administrator sends all players a note and the rankings
From Concepts to Specifications
Starting from the concept graph and the use cases we can now identify collections of
data and what kind of functions we want on them. This is called an
interface. Few programming languages actually provide interfaces of this
kind, but they approximate it. (Java's interfaces are a prime example of this kind
of approximation.)
Imagine for each box in the graph an action that someone may demand from this
box. For example, according to the first use case, a player may register with the
game administrator. This suggests an action called register
. The
action consumes information about the player and produces an acknowledgment:
Ackn register(PlayerInformation)
or
register : PlayerInformation -> Ackn
Now re-read the use cases and try to find all such actions.
As you create these specifications, you may realize that a concept
actually represents two distinct ideas. Take the player node from above. It
represents both the actually existing real person who, for examples, consumes the
information that the game has started and that it is his turn in the game as well
as the piece of data that the administrator uses to keep track of personal
information (say credit card numbers) and the game score. If you encounter
something like this, split the concept and re-draw the borderline.
Once you have listed and written down the functions/methods that each collection
of data must implement, you get a specification diagram:
+-----------------------+
| Admin | // represent the player internally
+-----------------------+ 1 * +-----------------------+
| SPlayer players | -------------------------> | SPlayer |
+-----------------------+ +-----------------------+
| Ackn register(Player) | | void inform(String) |
| // add a player | | // accept information |
| // for new game | | // from server |
| | | |
| String play() | | void takeTurn(Turn) |
| // run game, construct| | // play turn |
| // msg about result | | |
+-----------------------+ | void record(0..6) |
| 1 | // record result |
| 1 | |
| +----------------> +-----------------------+
| | | 1
| | * |
v 1 v |
// one turn for player |
// a single die +-------------+ |
+-------------+ 1 1 | Turn | |
| Die | ---- +-------------+ |
+-------------+ | | |
| | | 1..6 roll() | v 1
| 1..6 roll() | | // roll die | // the actual player code
| | | | +-----------------------+
+-------------+ | 0 skip() | | APlayer |
| // skip turn| +-----------------------+
+-------------+ | String name |
^ * | |
| | void inform(String) |
| 1 | // accept information |
+----------------> | // from server |
| |
| void takeTurn(Turn) |
| // play turn |
+-----------------------+
You can now develop code from this specification diagram.
Review of Programming
"How to Design Programs" and "How to Design Class Hierarchies" introduce the notion
of a design recipe. Roughly speaking a design recipe is a prescription of six design
steps that help people go from a problem statement to a deliverable program.
For the level of programming of this course, the six steps are:
- analyze the problem, using concept graphs and use cases, and identify/describe
the key concepts and their relationships
- specify the purpose of the various pieces that your use cases and concept graphs
recognize
- imagine what kind of basic tests your working code should satisfy; implement
this test suite for code that others deliver and/or for your own code
- organize the available information
- code
- run the test and iterate
We have covered the first two steps. Now it's time to move to the actual coding and
to identify what helps with coding.
The Cost Trade-off Model
Finally, as you program keep in mind that programming is affected by four factors:
- cost: how much money does it cost to produce the software?
- time: how much time do you need to finish the product?
- scope: how many features will you implement?
- quality: how reliable is the product?
A lot of managers want minimal cost, minimal time, maximal number of features, and
all that with perfect reliability. Naturally that doesn't work. This kind of
optimization request violates the basic tenets of business school: pick the variables
that you can choose to manipulate and determine the final one from it.
A software producer can be told how many features are supposed to be in there,
how many dollars it is supposed to cost, and how reliable it is supposed to
be. But then the manager must leave it to the programmer to say how much time it
will take.
Explain what it means to pick any of the other three variables as the one you
wish to maximize.
Don't ever let someone tell you that you can achieve all of it. Quit. Your
manager doesn't know what he's talking about. It can only get worse.
Bibliography
Larman, Applying UML and Patterns. Prentice Hall, 1998.
Felleisen, Findler, Flatt, Krishnamurthi. How to Design Programs.
Beck. Extreme Programming Explained. Addison-Wesley, 2000.