 | Level: Introductory Allen Holub, Contributing Editor, JavaWorld
01 Sep 2000 This month I'll continue refining the problem statement that I started last month, which was for a piece of educational software called the Bank of Allen.
The next step that I usually take when starting a problem definition is
to create a glossary. In general, terms that are immediately recognizable
by someone familiar with the domain don't need to be defined, but often
a term has an ambiguous meaning or is used in a limited way in the current
problem, so it will have to be explicitly defined.
One gotcha in a problem statement is inconsistency. It's essential
that one word is not used to mean two different things, and that two different
words are never used to mean the same thing. Your first line of defense is a glossary.
Typically, you would not define problem-domain terms here. For example,
you wouldn't define credit or interest if the problem domain
was accounting. The current problem domain is parenting, however, so terms
like credit need to be defined precisely.
The glossary is also helpful in our main goal, which is to identify
the key problem-level abstractions. Often essential words and concepts that
appear in the glossary don't appear in the main body of the problem
statement. For example, the definition of passbook introduces the term
transaction. (The notion of a transaction turned out to be significant,
although I didn't come to this realization immediately.)
It's also helpful to add an Implementation Details section in the glossary to provide
a place to record these details, even though they're not actually part
of the problem statement per se. The sorts of things that normally
would go in a Functional Requirements Specification often go into the
Implementation Details.
 | |
Glossary
Here's my first-pass glossary and implementation details.
Balance: The amount of money currently in your account.
Bank: A parent.
Credit: A deposit to your account made by the bank
rather than yourself.
Deposit: The act of putting money in the bank; increases
your balance.
Interest: A credit given as a reward for keeping your
money in the bank. Interest is computed daily by crediting to the account
a fixed percentage of the current account's balance (the "principle").
If the interest rate is 10%/month, you'd multiply the balance by (.10/30)
every day of that month.
Passbook: A log of the transactions that occurred
in some account along with summary information. Kids must get their passbooks
from the bank.
Withdrawal: The act of removing money from the bank;
decreases your balance.
Implementation details:
This section is not part of the problem statement per se.
It's just a list of things that occur to me as I'm putting together
the problem statement.
- Parents can set up a password for themselves the first time the program
boots. Thereafter, you'll have to know your password to log on as a parent.
Parents can change the password at any time.
- Changes in interest rate take effect immediately, but do not affect previous
day's balances at all. (Passbooks do not have to (but may) reflect the
new rate for any deposits made on the date the rate changed, even those
made earlier in the day.)
- The kids must ask the bank for their passbook.
- Passbooks are updated every time they're given to a kid.
- Some means for parents to backup or restore the entire bank must be provided.
This could be a simple file copy or something more elaborate.
|
|
Verify and refine the problem statement
Feeling pleased with myself for having prepared a reasonable problem
statement, the next step was to do a design review. I pressed my wife,
DJ, who is a programmer and domain expert -- a parent -- into service.
She found various minor grammatical problems (which I must confess, I have
fixed in the initial statement that you just read), but she found one serious
flaw that I hadn't thought of. "You can't compute interest like that,"
she pointed out. "If you just divide the monthly interest by the days in
the month, but compound it daily, you'll end up with a bigger balance at
the end of the month than if you compute it once at the end of the month.
What you need here is a nominal rate that's lower than 5% per month
that will give you an effective rate of 5%." Oops. Back to the
books.
In the current problem, it turns out there are two domains: parenting,
of course, and to a lesser extent, finance. I had assumed that I knew enough
about the latter, but clearly I was wrong. So, I dropped the design and
hit the books until I understood enough about the second domain to proceed.
This problem might have emerged sooner had I not left out an essential
second step to the design process: after you've become familiar with the
problem domain (step 1) but before you start modeling (step 3), you must
interview your users to discover what they need. I didn't think I needed
to do that since I was already a domain expert -- a parent. I was wrong. Had
I interviewed a second domain expert, someone not as involved as I was
in the actual design (my wife for example), I probably would have gotten
this interest stuff right in the first place.
Don't step over the obvious
There are lots of other issues here, but the most important is what I call
the "the bathroom effect." This name stems from an (unpublished) article
that I wrote for "Dr. Dobb's Journal" a few years ago that began, "Suppose
we built houses the same way we build software." (We'd all be living in
a poorly built version of the
Winchester
Mystery House). Anyway, toward the end of the article, the buyer finally
gets to see the house for the first time (after it's entirely built). Looking
around with a puzzled expression, the buyer asks, "Where are the bathrooms?"
"Bathrooms?" says the contractor, "there weren't any bathrooms in the
spec. It will cost a fortune to add them now; we'll have to jack-hammer
up concrete,and rip open walls. Why don't we just patch on an outhouse
in the back yard?"
"Waddya mean 'it wasn't in the spec'?" stammers the buyer, "Who'd be
dumb enough to build a house without bathrooms?"
And that's often the problem with software. It often doesn't occur to
a user to mention something he needs, precisely because it's so fundamental to the
problem. It's not that the users are "hiding things from me," as many programmers
say. It's that the designer doesn't know enough about the problem
domain to ask the right questions.
Don't just nod -- listen
When conducting these interviews,
listen! Don't interpret. It's
very important not only to capture everything that comes out in the interview
(someone who can take shorthand is a real asset), but also to record the
domain expert's words exactly. I've sat in many meetings where the users
went on for hours without anybody writing anything down. Later on, when
the user wasn't around, nobody could accurately remember what had been
discussed. There's also an unfortunate tendency on the part of programmers
not to pay attention to what the users say. Instead, programmers have been
known to distort the user's description of what a problem is into
a description of what the programmer would like the problem to be.
They'll restate things, shuffle words around, translate statements out
of the problem domain into a more-familiar vocabulary, and otherwise distort
or modify what they hear. More often than not, what gets captured is the
programmer's flawed interpretation of the problem, not the problem that
the domain expert actually described.
Finally, bear in mind that most users have a long history of trying
to deal with arrogant computer geeks who think that they know more about
any problem than the user does. (After getting an incomprehensible set
of directions, the city slicker says to the farmer, "You're not very smart,
are you?" The farmer replies, "That may be so, but I'm not lost.")
The problem is that many users just give up after a while. Why bother to
communicate if the programmer doesn't listen? You'll have to break down
these sorts of barriers.
The main issue with respect to problem statements in general is whether
this level of detail belongs in it at all. Normally, the problem statement
itself wouldn't go so far as to define technical terms in the actual problem
domain. You'd just consult a textbook or dictionary for that purpose. Here,
however, the answer is "yes" because the distinction between nominal and
effective interest is not part of the actual problem domain (which is parenting).
Our domain experts are parents, not bankers or accountants. We are not
developing a system for use by a bank or making any attempt to model the
way that a real bank works. This is a piece of kid's software, not
a turn-key banking system, so we can't assume knowledge of how interest
is computed on the part of our domain experts. Interest computation is
an important part of defining the problem, however, so it indeed belongs
in the problem statement.
It's essential to keep the problem statement focused on the problem
at hand. We don't want to solve the general problem of "banking" in a piece
of kid's software. On the other hand, we don't want to leave out an essential
detail either. If the average reader (who is assumed to be a domain expert)
needs some piece of information to make sense of the problem statement,
then it belongs. If the information is an essential part of the domain,
we wouldn't add it. In the current case, if I really was writing a turn-key
banking system, I certainly wouldn't bother to define "effective interest"
because that's something that I'd expect my domain expert to know. (By
the same token, the designers must know enough about the problem domain
to understand these basic terms as well. You can't design an accounting
application unless you know something about accounting -- at least at the
level of an intelligent layman.)
So, I dug out a finance-for-the-complete-idiot book, looked up
nominal interest, and modified the definition of interest as follows:
| Interest | A credit given as a reward for keeping your money in
the bank. Interest is added to the balance daily.
The Bank of Allen has to work like a real bank, with interest
computed on a monthly basis. Nonetheless, the earned interest has to be
posted to the passbook every day. The problem is that daily compounding
and monthly compounding yield different results.
For example, if you start with $100 in the bank, and have a 10% interest
rate, compounded once every 10 days, you'll end up with $110.00 in the
account at the end of the ten days.
On the other hand, if you divide to create a daily interest of 1%/day
and compound daily, you'll end up with a larger number:
| Day 0 | Principal | $100.00 | | Interest | $1.00 | | Day 1 | Principal + interest | $101.00 | | Interest | $1.01 | | Day 2 | Principal + interest | $102.01 | | Interest | $1.02 | | Day 3 | Principal + interest | $103.03 | | Interest | $1.03 | | Day 4 | Principal + interest | $104.06 | | Interest | $1.04 | | Day 5 | Principal + interest | $105.10 | | Interest | $1.05 | | Day 6 | Principal + interest | $106.15 | | Interest | $1.06 | | Day 7 | Principal + interest | $107.21 | | Interest | $1.07 | | Day 8 | Principal + interest | $108.28 | | Interest | $1.08 | | Day 9 | Principal + interest | $109.36 | | Interest | $1.09 | | Day 10 | Principal + interest | $110.45 |
|
You need to use two interest rates to solve this problem: one that the
kid knows about and another that the bank uses internally.
Effective interest rate
The actual interest rate, including the effect of compounding. Given a
nominal monthly rate of 5%, the effective interest rate when compounded
daily is 5.12%.
Nominal interest rate
The stated interest rate, excluding the effect of compounding.
What's the effective rate, compounded daily, that would achieve a nominal monthly rate of 5%?
N = Nominal rate expressed as a decimal (.05)
P = Number of periods (30 days)
E = Effective rate expressed as a decimal
Formula:
E = (1 + N/P)P -1 = .0512
An interest rate of 5%, compounded daily, yields the same balance
at the end of 30 days as 5.12% compounded monthly.
|
What nominal rate do I use if I'm compounding daily, but want an effective interest rate of 5%/month?
N = Nominal rate expressed as a decimal
P = Number of periods (30 days)
E = Effective rate expressed as a decimal (.05)
Formula:
N = P * (E + 1)1/P -1 = .0488
An interest rate of 4.88%, compounded daily, yields the same balance
at the end of 30 days as 5% compounded monthly.
|
The effective and nominal rates are the same if you compound only once
in a period. That is, if you compute interest once a month, the effective and nominal monthly rates are the
same.
To keep things easy to explain, the bank publishes the effective rate:
"Your monthly interest rate is 10%. This means that if you keep $10 in
the bank for a month, the bank will pay you a dollar."
Since interest is compounded daily, the nominal rate must be used
for daily computation (so the effective rate at the end of the month comes
out right). For example, given a 30-day month, and a published (effective)
monthly rate of 5%, the (nominal) daily rate used in compounding is 4.88%.
If you start out with $10 in the account and apply the following algorithm,
you'll end up with a balance of $10.50:
double balance = 10.00;
int days_in_month = 30;
double effective_rate = ->05;
double nominal_rate = days_in_month *
( Math.pow(effective_rate+1,
1.0/days_in_month)
-1);
for ( int i = 0; i </ days_in_month; ++i )
balance = balance + balance *
(nominal_rate/days_in_month));
|
Now things are starting to look more reasonable, although it turns out
that we're still not done. That's the topic of next month's column.
Resources
About the author  | |  | Allen Holub has been working in the computer industry since 1979. He is widely published in magazines (Dr. Dobb's Journal, Programmers Journal, Byte, MSJ, among others) and is a Contributing Editor to the online magazine JavaWorld. He has eight books to his credit, the latest of which (
Taming Java Threads
) covers the traps and pitfalls of Java threading. He's been designing and building object-oriented software for longer than he cares to remember. After eight years as a C++ programmer, Allen abandoned C++ for Java programming in early 1996. He's been teaching programming (first C, then C++ and MFC, now OO-Design and Java programming) both on his own and for the University of California Berkeley Extension since 1982. Allen offers both public classes and in-house training in Java technology and object-oriented design topics. He also does object-oriented design consulting and contract Java programming. Visit Allen's Web site at
www.holub.com.
The "Bank of Allen" is a trademark of Allen I. Holub. This program, and the design thereof, is (c) 2000, Allen I. Holub. All rights reserved. |
Rate this page
|  |