 | Level: Introductory Allen Holub (allen@holub.com), Chief Technical Officer, NetReliance
01 May 2001 This article continues my series on the OO design process. The first seven parts have covered planning stages from the initial design, through the refinement of the problem statement and the beginning of our work on use cases. This month, I wrap up use cases before turning, next month, to the user interface.
In this month's article I continue from last month by filling out the remainder
of the use-case template for the Depositing Funds use case. As was the
case last month, I've not just filled in the template, but also provided
extensive comments about my thought processes as I was working. This
month's part of the template is in a way the real meat of the use-case
description since it actually describes the flow of work as the use case
progresses. This work flow is what the program will have to do at run time
as a user works through the use case. In my last column, I covered about half of our use-case template. I'll pick up where we left off. Filling out the use-case template for the Depositing Funds use case
-
Dependencies
-
Similar to:
2.0. Kid Withdrawing funds from an account. (equivalent?)
Follows:
4.0. Parent opening an account
Includes:
6.1. Parent authorizing a single deposit
Followed by:
6.0. Parent authorizing prior deposits
This list is tentative. For example, the "Similar to" relationship with
use case 2.0 might actually be an "equivalent" relationship. -
Preconditions
- The account must exist.
-
Inputs
- The kid has earned some money.
Scenarios
- (Happy path)
Philip has completed his chores for the day and has decided to deposit
the resulting $2.25 into the Bank of Allen. (If he did his chores every
day, I'd be broke by now.) He enters the bank, asks the teller for a
deposit slip, fills it out, and returns the deposit slip along with his
passbook to the teller. The teller asks for some identification before
she accepts the deposit slip, then sends the slip to the bank officer
for approval. The bank officer (a parent) authorizes the deposit by
signing the slip, and sends it back to the teller, who updates Philip's
passbook to show the transaction. The teller then returns the Passbook
to Philip so he can gleefully ponder his growing account balance.
Note that I've carefully used the vocabulary of the problem statement
(discussed in previous installments of this series) in this scenario
description (for example, "passbook," "teller," etc.). Had I introduced
new concepts here -- and that does happen -- I'd have to go
back and modify the problem statement to introduce the new vocabulary. A
significant (and difficult) goal of the designer is to keep all design
documents "in phase" with each other. If a change in one document impacts
another, then both documents must be changed immediately. For example, I
have deliberately not said "The teller makes a journal entry reflecting
the deposit transaction," because "journal" is not in the domain
vocabulary while "passbook" is in the domain. Whether you call it a
"journal" or a "passbook" makes no difference to the design.
Also note that I have not used the phrase "the system." The system
doesn't do anything; rather, all work is done by actors who take on
well-defined roles. Some of those actors (the kid) are real people. Other
actors (the teller) are entirely automated. Other actors (the bank
officer) are partially automated and partially real (some of the
responsibilities of the bank officer are executed by a parent rather
than a computer). It's the role that's important; It's immaterial
whether the actor performing that role is or is not automated.
-
In this scenario, the money isn't actually added to the account; rather, the deposit is entered into the passbook as "unapproved." Any parent can approve the transaction at some subsequent time. In other words, the deposit is "on hold" until it "clears." The teller returns the passbook to the kid, and the deposit will show up in the passbook, but the funds cannot be withdrawn from the account until the parent signs the deposit slip. (This scenario differs from the happy path in that no parents are around to authorize the deposit.)
- In this scenario, the parent deposits funds for the kid (as
compared to the kid initiating, and the parent authorizing, the
transaction).
By this juncture, I've gotten rather tired of the word "kid," as compared
to something a bit less flip. I'm deliberately continuing to use the
word kid -- rather than child, customer, or
some other equivalent term -- because it's important that the
nomenclature of the entire set of design documents be internally
consistent. I'm wishing that I had chosen my terms a bit more carefully,
though. The second scenario actually introduces a new use case, which hadn't
occurred to me earlier: "Parent authorizing prior deposits." This is
really a stand-alone use case, even though authorization is also an
operation in the current use case (implying a subcase: Parent authorizes
a single deposit.)
Workflow
This section is the critical one, so I'll deviate a bit from the format I've been using hitherto and show how the workflow evolves. I start out by modeling the happy path as a simple list. The happy path scenario:
- Kid requests a deposit slip from teller and fills it out.
- Kid submits the deposit slip and passbook to the teller.
- Teller verifies the kid's identity as valid.
- Teller sends the deposit slip to bank officer for approval.
- Bank officer returns the deposit slip to teller, marked as approved.
- Teller makes an entry in kid's passbook showing the deposit.
- Teller returns the passbook to the kid.
Though a linear list is sufficient for a simple workflow, it doesn't cut the mustard when the workflow gets complicated. Constantine and Lockwood recommend that you represent nonlinear operations using phrases like "In any order:" followed by a list. You could also use "Simultaneously" followed by a list to represent concurrency. Maybe I'm just a visual kind of guy, but I find these words-only representation of use cases to be confusing. I prefer UML workflow diagrams when the use case is at all complicated. The UML for the simple happy path is shown in Figure 1. Figure 1. The happy path workflow diagram

The notation is more-or-less self explanatory. Each box is an activity,
flow is indicated by arrows. You start at a solid circle and end at a
target. The columns, called swim lanes, identify the class of
objects (or the subsystems) that are responsible for performing the
activity. Looking at the diagram, I notice that there is some scope for
parallelism. That is, some activities (verifying the kid's identity and
approving the deposit) could be done in parallel. (You could also say
that the order in which these activities are executed is unimportant,
provided that they are all executed before moving on to the next step.)
Figure 2 shows the modifications required to Figure 1 to reflect this parallelism. The heavy
horizontal lines that begin (are at the top of) a set of parallel
activities are called forks. The lines at the bottom, which represent the point where the activities must synchronize before further work is possible, are called joins. Figure 2. The happy path, modified to reflect parallelism

Now I go back and look at the other two scenarios, and try to merge them
into the happy path activity diagram. (The modified diagram is in Figure 3.) In general, if it's not possible to
merge the scenarios, or if the diagram that results from the merge is too
ungainly, then the additional scenarios are probably stand-alone use
cases, not scenarios of the current use case. The current batch of
scenarios merge quite nicely, though.
The parent-makes-deposit-for-kid scenario turns out to be a no brainer
once I realize that the workflow is identical to the happy path --
provided that I permit to parent to masquerade as a kid. That is, a
parent's password can be used to log on a kid. I put a comment to this
effect in both the activity diagram (Figure 3)
and the business rules section (below). The second scenario (where the parent isn't present) is slightly more
difficult because I have to introduce a branch (indicated in Figure 3 as a diamond with one incoming and
multiple outgoing arrows). The conditions that control which outgoing path
to follow (called guards) are just text labels on the lines. A
merge (also indicated with a diamond, but this one with multiple
incoming and one outgoing arrow) marks the end of the conditional
behavior. Every branch should have an associated merge.
You could express all the complicated stuff between the fork and the join
as follows: In any order, verify the identity of the kid and also mark
the deposit as approved if a parent is present, or unapproved if the
parent is absent. Update the passbook after both activities (verification
and marking) have completed. Note that the original scenario description specified that the teller
hold unapproved deposits. It became apparent while working with the
diagram that it would be a lot easier for the unapproved deposits to be
held in the passbook, not by the teller, so I did that. I went back and
modified the scenario description to reflect this change. Figure 3. Additional scenarios added to happy path

-
Postconditions
- new account balance = old account balance + deposit amount
Note that the use case encompasses two distinct operations (deposit request and deposit authorization) that don't have to occur at the same time. Nonetheless, this is a single use case with a single outcome. The account balance is always affected, even if some days elapse between the deposit and approval activities.
-
Outputs
- An updated passbook.
This section would be the place where you'd actually show what the output
will look like (in the case of a report, for example). I'll defer that
until I start work on the UI in a subsequent article.
-
Business rules (domain-related)
-
- Deposits must be authorized by a parent before they take effect.
- Interest starts accruing on the day the deposit is made, even if
authorization occurs on some subsequent day.
- Unauthorized deposits can remain in the unauthorized state, waiting
for a parent signature, indefinitely. They do not become "stale."
- A parent's password will authenticate a kid. That is, parents can
log on as kids.
-
Requirements (implementation-related)
-
- Deposits must be "saved" automatically. There is no "File/Save"
menu. An explicit "undo" isn't necessary or desirable. Undo a deposit
with a withdrawal.
- The "held" deposits must be displayed when kids view their
passbooks. Held deposits will be displayed in gray.
Had I said "highlighted in some way" rather than "displayed in gray," I
would be running the risk of writing a worthless specification. By the
time we're done, the specification simply can't be ambiguous. Since all
decisions have to be made eventually, you may as well get them out of the
way now. You can always go back and change things if you make a wrong
decision (until the specification is formally approved, of course.)
It seems better to me to make a wrong decision than to make no decision
at all. I've seen many so-called specifications that were so
mealymouthed that several hundred distinct programs could be generated
from the spec, and all of these programs would be conforming. This sort
of ambiguity is worse than useless, since it encourages you to do
incorrect work.
In the current case, I suppose, the issue is so trivial that a decision
may well be unnecessary. It doesn't matter in the least how the
entry is highlighted, as long as it is highlighted.
Consequently, this decision could be deferred to the formal UI-design
process. If you leave the notion of highlighting indeterminate,
the various programmers who are implementing the design will each implement their own notion of highlighting, with the resulting UI being inconsistent and harder to use as a consequence.
-
Implementation notes
-
- There's currently no notion of logging in. Looking at the scenarios,
Philip is not likely to make several transactions at once. In fact, it's
more likely that he'll make a single transaction, but forget to log off.
(This is an observed behavior from my home testing lab -- Philip often
plays a game in the morning, and I'll find the game still running 12
hours later, after he's gone to bed.) Given this behavior, it seems more
secure to ask for some sort of authentication as part of accepting a
deposit slip. This is essentially the way a real bank works.
- The analog of logging in would be identifying yourself to a guard as you
were admitted to the bank. (Which might be a reasonable approach, it's
just not the one I chose.) Note that there's nothing in this use case to
prohibit the teller from remembering who Philip is. That is, it's within
the scope of the use case for the customer to be somehow labeled as
"trusted" so that subsequent transactions can be performed without
needing to repeat the authentication process. The "trusted" attribute
could be cancelled by a log out, or it could simply time out. (For
example, you would become untrusted if two minutes elapsed without any
activity within the bank.)
- (This note may not be clear to you until we start the actual object
modeling, so don't worry it if it doesn't make sense, yet.) The kid is,
for the most part, an external object. That is, there is no programmatic
object within the system that will represent the kid; rather, the kid is
a physical user of the system. On the other hand, the notion of a kid's
identity will almost certainly be modeled, since some object in the
system must handle authentication.
-
There's a difference between "available funds" and "current
balance." (The latter doesn't reflect unauthorized transactions.) Since
the kid treats a deposit as a deposit, regardless of whether or not it's
authorized, the passbook should display both values. In any event, it
can't hurt to teach kids how a "hold" works.
I'm not sure how best to present holds in the UI. One solution is for the deposit slip to be shown to any kids who look at their passbooks, but
the deposit won't show up in the passbook proper until the deposit slip
is authorized by a parent. Another possibility would be for the deposit
to show up in the passbook like an authorized deposit, but with some
visual indication (gray text?) that the deposit is being held.
The latter makes more sense, but this means that the parent-authorizing-current-deposit use case will probably be significantly different from the parent-authorizing-pending-deposits use case.
Note that, if the teller holds deposit slips for parent authorization, the kid will have to ask the teller to see the passbook so that the teller can display the held deposit slips as well as the passbook.
- Probably the best way to handle parent authorization is on the UI
for the deposit slip itself. Maybe an "Authorized" box, which, when
checked, pops up a small dialog onto which a signature can be entered.
Another possibility is a "authorized signature" line on the deposit slip
itself into which a parent can type a pass phrase. (Note that some
indication that the transaction has been authorized -- a facsimile of a
signature, for example -- should appear on an authorized deposit slip ).
Don't print x's in the authorized-signature line (or at least replace the
x's once the signature is verified); there's no point in giving away the
number of characters in the passphrase.
- There are some access-control issues here. Someone in the role of
kid has permission to specify deposits, but not to authorize deposits.
(An authorization causes the account balance and passbook to be updated.)
Someone in the parent role may both specify deposits and authorize
deposits. The system must be able to distinguish between actors in these
two roles -- password authentication is adequate.
-
Interest accumulates on held funds, even if these funds are not
accessible. Probably the best way to handle interest is to think of the
passbook as a list of transactions, sorted by date. When a deposit slip
is authorized, it's inserted into the transaction list in sorted order.
Interest is then recomputed, starting at the point immediately above the
most recently inserted transaction. This way an unauthorized transaction
effectively doesn't accrue interest.
You want to show interest accrual on a daily basis, however, so it's not
sufficient to list only transactions, as would a real-world passbook or
bank statement. You really want a line item for every day. That's a lot
of line items, though. A reasonable compromise might be to show the
previous 30 days on a per-day basis, with the rest of the passbook
looking like a standard bank statement that shows regular (but not daily)
interest postings, perhaps one posting per week.
So that's an entire use-case presentation. Rather than bore you by
presenting the rest of the use cases in subsequent columns, I'll put the
complete set up on my Web site (see Resources) so that you can inspect them at your leisure. Next month we'll continue the design process by looking at the UI design (which is essential not only because we'll
have to build it, but also because the UI serves both to validate the use
cases and provide a useful communication tool).
Resources
About the author  | |  | Allen Holub is the Chief Technical Officer at NetReliance, a San-Francisco-based company that's building a secure global infrastructure for conducting trusted business transactions over the net. He has worked in the computer industry since 1979, and is widely published in magazines (Dr. Dobb's Journal, Programmers Journal, Byte, MSJ, among others). He writes the "Java Toolbox" column for the online magazine JavaWorld, and also writes the "OO Design Process" column for the IBM developerWorks Components zone now hosted on the IBM developerWorks Web services zone. He also moderates the ITworld Programming Theory & Practice discussion group. Allen has eight books to his credit, the latest of which covers the traps and pitfalls of Java
threading ( Taming Java Threads ). He's been designing and building object-oriented software for longer than he cares to remember (in C++ and Java). He teaches OO design and Java for the University of California, Berkeley, Extension (since 1982). Contact Allen via his Web site http://www.holub.com.
|
Rate this page
|  |