Part 6: Selection

 
 
 

6.1   Specification

        Extend the system in two ways:

1.    Guard the system against invalid input. If a value is invalid, then reject it (do not use the value). A much better idea is to ask the user for a better value, but this soluton must wait the next part of the case study, where loops are covered.

2.    Us e the gender code to type out "Mr. " or "Ms. ".
 
 

6.2   Analysis
 
        Three guards are needed on an account:
•       The initial balance must be positive.
•       A deposit must be positive.
•       A withdrawal must be positive, and not less than the balance.
 
        One guard is needed on the customer:
•       the valid input values for a gender are ‘M’, ‘m’, ‘F’, and ‘f’.
One routine is needed to transform the gender code into a title string.
 
 

6.3   Design

        A function enough is defined in class ACCOUNT to test if an account has enough money for a withdrawal. The withdraw routine in CUSTOMER uses enough as a guard on the actions. This function is used by CUSTOMER, because it is the client’s responsibility to call the supplier (withdraw) correctly.

        CUSTOMER must be able to test a precondition on an ACCOUNT routine before it is called, so the pre-conditions never fail. A function positive is therefore added to CUSTOMER.

        A test cannot be used to guard the get_balance routine, because that routine has no arguments to guard. An invalid initial balance must be rejected. The routine is therefore split into two parts named read and set; read reads in a value from the user and tests it, and set uses this value if it is valid. The read routine is placed in CUSTOMER, and the set in ACCOUNT.

        The client chart is unchanged. The class diagram for ACCOUNT is changed to include the new exported feature, enough. The new class diagram for ACCOUNT is shown below.


 
 

6.4   Solution code

        The changed and added code in classes CUSTOMER and ACCOUNT is shown below.
 

class CUSTOMER

creation {BANK}
      make

feature {NONE}
      ...
      get_gender is
                        -- read in a gender code, store it if it is valid
             do
                     read_gender
                     if valid_gender
                     then gender := io.lastchar
                     else
                             io.putstring ("%TValid codes are M, m, F, f.")
                             io.putstring (" Gender set to M%N")
                             gender := ‘M’
                     end
             end -- get_gender

        read_gender is
                        -- read in a gender code
             do
                     io.putstring (" Gender (M/F): ")
                     io.readchar
                     io.next_line
             end -- read_gender

      valid_gender: BOOLEAN is
                        -- has a valid gender code been entered?
             do
                     inspect io.lastchar.upper
                     when 'M', 'F' then Result := true
                     else Result := false
                     end
             end -- valid_gender

      show_gender is
                        -- show a title indicating the gender
             do
                     inspect gender
                     when 'M', 'm' then io.putstring ("%NMr. ")
                     when 'F', 'f' then io.putstring ("%NMs. ")
                     end
             end -- show_gender
      ...
      positive (amount: REAL): BOOLEAN is
                -- is the amount positive?
             do
                     Result := amount > 0
             end -- positive

feature {BANK}
      make is
                        -- create the customer from input data
             do
                     io.putstring ("%NEnter the customer details%N%N")
                     get_name
                     get_gender
                     get_address
                     get_account
             end -- make

      get_account is
                        -- read in an amount for the balance, set the balance if possible
                        -- if amount is invalid, set the balance to one cent
             do
                     io.putstring ("%TEnter the initial account balance: $")
                     io.readreal
                     if positive (io.lastreal)
                     then !!account.make (io.lastreal)
                     else
                             io.putstring ("%TAmount must be positive. Balance set to $0.01.%N")
                             !!account.make (0.01)
                     end
             end -- make

      show is
                        -- show the customer details
             do
                        io.new_line
                        show_gender
                        io.putstring (name)
                        ...
             end -- show
      ...
      deposit is
                        -- read in amount from the user, deposit it if possible
             do
                     io.putstring ("%TEnter the amount to deposit: $")
                     io.readreal
                     if positive (io.lastreal)
                     then account.deposit (io.lastreal)
                     else io.putstring ("%TAmount must be positive. No deposit made.%N")
                     end
             end -- deposit

      withdraw is
                        -- read in amount from the user, withdraw it if possible
             do
                     io.putstring ("Enter the amount to withdraw: ")
                     io.readreal
                     if positive (io.lastreal)
                     then if account.enough (io.lastreal)
                             then account.withdraw (io.lastreal)
                             else io.putstring ("%TAmount exceeds balance. No withdrawal made.%N")
                     else io.putstring ("%TAmount must be positive. No withdrawal made.%N")
                     end
             end -- withdraw
        ...
end -- class CUSTOMER
 

class ACCOUNT
...
feature {NONE}
      set_balance (amount: REAL) is
                        -- set the balance to amount