The bank has two customers. A customer has a name, gender, and address.
For each customer in the bank, create an account, deposit, withdraw, and
show the balance at that point, and finally add interest and show the balance.
A bank has two customers. A customer has a name, gender, address, and one account. An account has a balance and an interest rate. The actions that were all in the class ACCOUNT have to be placed in the three classes BANK, CUSTOMER, and ACCOUNT, and code has to be added to read in and set the customer attributes.
The behaviour of ACCOUNT is changed, because the customer decides how much money to deposit and withdraw. The amounts to use are read by code in class CUSTOMER, and passed as arguments to the deposit and withdraw procedures in ACCOUNT.
A CUSTOMER has four attributes, the name, gender, and address of the customer, and an account. The code to set and use these attributes is placed with the data, in class CUSTOMER..
Class BANK has two attributes, both of type CUSTOMER. Each customer is created and used. The feature use could be placed in the bank (called by use (customer)) or in the customer (called by customer.use). When there is a choice, it is better to place code in a supplier than a client, so the use routine is placed in class CUSTOMER.
The system now has a new root class, BANK.
The creation routine in class ACCOUNT sets the initial balance.
The creation routine for a customer reads in and sets the customer details, and then creates an account for the customer. The class CUSTOMER has routines to deposit and withdraw, that read in an amount to use and send this amount to the deposit and withdraw routines in class ACCOUNT as an argument. The class CUSTOMER also has a show routine.
The Ace file now lists a new root class BANK with the code; this is the root class for the rest of the case study.
root
BANK: "make"
The client chart for this system of three classes is shown below. A client
chart shows the client - supplier relation between classes, so the number
of objects is not shown on the chart.
class BANK
creation
make
feature
me, you: CUSTOMER
make is
-- create and use two customers
do
!!me.make
me.show
me.use
!!you.make
you.show
you.use
io.new_line
end -- make
end -- class BANK
class CUSTOMER
creation
make
feature
name: STRING
get_name is
-- read in and set the name
do
io.putstring (" %TName: ")
io.readline
name := clone (io.laststring)
end -- get_name
gender: CHARACTER
get_gender is
-- read in and set the gender
do
io.putstring ("%TGender (M/F): ")
io.readchar
gender := io.lastchar
io.next_line
end -- get_gender
address: STRING
get_address is
-- read in and set the address
do
io.putstring ("%TAddress: ")
io.readline
address := clone (io.laststring)
end -- get_address
account: ACCOUNT
make is
-- create the customer from data input by the user
do
io.putstring ("%NEnter the customer details%N")
get_name
get_gender
get_address
!!account.make
end -- make
use is
-- deposit, withdraw, and show the balance
-- add interest and show the balance
do
io.new_line
deposit
withdraw
account.add_interest
account.show_balance
io.new_line
end -- use
show is
-- show the customer details
do
io.new_line
io.putstring (name)
io.putstring (" of sex ")
io.putchar (sex)
io.putstring (" lives at ")
io.putstring (address)
account.show
end -- show
deposit is
-- read an amount from user, deposit it
local amount: REAL
do
io.putstring ("%TAmount to deposit: $")
io.readreal
amount := io.lastreal
account.deposit (amount)
end -- deposit
withdraw is
-- read an amount from user, withdraw it
local amount: REAL
do
io.putstring ("%TAmount to withdraw: $")
io.readreal
amount := io.lastreal
account.withdraw (amount)
end -- withdraw
end -- class CUSTOMER
class ACCOUNT
creation
make
feature
balance: REAL
get_balance is
-- read in a balance from the user and store it
do
io.putstring (" Initial account balance: $")
io.readreal
balance := io.lastreal
end -- get_balance
show_balance is
-- show the balance
do
io.putstring ("%NThe balance is $")
io.putreal (balance)
end -- show_balance
rate: REAL is 4.5
interest: REAL is
-- the interest for today
do
Result := balance * day_rate
end -- interest
day_rate: REAL is
-- daily interest rate
do
Result := (rate / 100.0) / 365.25
end -- day_rate
show_rate is
-- show the interest rate
do
io.putstring ("%NThe interest rate is: ")
io.putreal (rate)
end -- show_rate
make is
-- set the initial balance
do
get_balance
end -- make
show is
-- show the balance and interest_rate
do
show_balance
show_rate
end -- show
deposit (amount: REAL)
is
-- add this amount to the balance
do
balance := balance + amount
end -- deposit
withdraw (amount: REAL)
is
-- subtract this amount from the balance
do
balance := balance - amount
end -- deposit
add_interest is
-- add the daily interest to the balance
do
balance := balance + interest
end -- add_interest
end -- class ACCOUNT
The single most common design error is to leave the code where the designer first thought of it, in the form the designer first coded it. This design error is seen in three ways, discussed in more detail below. First, no classes are used and the designer writes straight procedural code, producing an enormous make routine in the root class. Second, code is added to the class the designer is coding, with little thought about whether that is its correct class, producing large classes. Third, routines are coded without thought of cutting them into smaller, reusable routines, producing large routines.
1. Omit the classes entirely. All of the code could
be written in one routine in one (root) class. This results in very short
code, but ignores completely the fact that that aim is to develop a resuable
OO system.
2. Leave the code where it was invented. OO design follows a three step process: |
a) Define the code. |
b) Place the code in a routine. |
c) Place the routine in a class. |
Code is placed in the same class that contains the data changed or used by the code. For data that is changed, there is no choice: Eiffel enforces this rule. For data that is used, the decision is harder and is left to the designer. All programmers can write the code and place it in some routine, and many novices simply stop there without thinking about reuse.
3. Write large routines. In class CUSTOMER, for example, each attribute has its own routine to read and set the attribute value, so each routine is simple and does a single thing. The creation routine controls these supplier routines. It is easier to simply place all this code as a single large chunk in the creation routine, but then the code is not reusable.