Skip to main content
skip to main content

developerWorks  >  SOA and Web services  >

The OO design process: Refining the problem definition

Explicitness is key

developerWorks
Document options

Document options requiring JavaScript are not displayed


Rate this page

Help us improve this content


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.



Back to top


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.



Back to top


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:

InterestA 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 0Principal$100.00
Interest$1.00
Day 1Principal + interest$101.00
Interest$1.01
Day 2Principal + interest$102.01
Interest$1.02
Day 3Principal + interest$103.03
Interest$1.03
Day 4Principal + interest$104.06
Interest$1.04
Day 5Principal + interest$105.10
Interest$1.05
Day 6Principal + interest$106.15
Interest$1.06
Day 7Principal + interest$107.21
Interest$1.07
Day 8Principal + interest$108.28
Interest$1.08
Day 9Principal + interest$109.36
Interest$1.09
Day 10Principal + 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.



Back to top


Resources



Back to top


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.




Back to top


Rate this page


Please take a moment to complete this form to help us better serve you.



YesNoDon't know
 


 


12345
 


Back to top



    About IBMPrivacyContact