Figure 22.16 lists the phrase “authenticates a user” next to class BankDatabase
—the database is the object that contains the account information necessary to determine whether the account number and PIN entered by a user match those of an account held at the bank. Therefore, class BankDatabase
needs an operation that provides an authentication service to the ATM. We place the operation authenticateUser
in the third compartment of class BankDatabase
(Fig. 22.17). However, an object of class Account
, not class BankDatabase
, stores the account number and PIN that must be accessed to authenticate a user, so class Account
must provide a service to validate a PIN obtained through user input against a PIN stored in an Account
object. Therefore, we add a validatePIN
operation to class Account
. We specify return type Boolean
for the authenticateUser
and validatePIN
operations. Each operation returns a value indicating either that the operation was successful in performing its task (i.e., a return value of true
) or that it was not (i.e., a return value of false
).
Figure 22.16 lists several additional verb phrases for class BankDatabase
: “retrieves an account balance,” “credits a deposit amount to an account” and “debits a withdrawal amount from an account.” Like “authenticates a user,” these remaining phrases refer to services that the database must provide to the ATM, because the database holds all the account data used to authenticate a user and perform ATM transactions. However, objects of class Account
actually perform the operations to which these phrases refer. Thus, we assign an operation to both class BankDatabase
and class Account
to correspond to each of these phrases. Recall from Section 22.4 that, because a bank account contains sensitive information, we do not allow the ATM to access accounts directly. The database acts as an intermediary between the ATM and the account data, thus preventing unauthorized access. As we’ll see in Section 22.8, class ATM
invokes the operations of class BankDatabase
, each of which in turn invokes the operation with the same name in class Account
.
The phrase “retrieves an account balance” suggests that classes BankDatabase
and Account
each need a getBalance
operation. However, recall that we created two attributes in class Account
to represent a balance—availableBalance
and totalBalance
. A balance inquiry requires access to both balance attributes so that it can display them to the user, but a withdrawal needs to check only the value of availableBalance
. To allow objects in the system to obtain each balance attribute individually, we add operations getAvailableBalance
and getTotalBalance
to the third compartment of classes BankDatabase
and Account
(Fig. 22.17). We specify a return type of Double
for each of these operations, because the balance attributes which they retrieve are of type Double
.
The phrases “credits a deposit amount to an account” and “debits a withdrawal amount from an account” indicate that classes BankDatabase
and Account
must perform operations to update an account during a deposit and withdrawal, respectively. We therefore assign credit
and debit
operations to classes BankDatabase
and Account
. You may recall that crediting an account (as in a deposit) adds an amount only to the totalBalance
attribute. Debiting an account (as in a withdrawal), on the other hand, subtracts the amount from both balance attributes. We hide these implementation details inside class Account
. This is a good example of encapsulation and information hiding.
If this were a real ATM system, classes BankDatabase
and Account
would also provide a set of operations to allow another banking system to update a user’s account balance after either confirming or rejecting all or part of a deposit. Operation confirmDepositAmount
, for example, would add an amount to the availableBalance
attribute, thus making deposited funds available for withdrawal. Operation rejectDepositAmount
would subtract an amount from the totalBalance
attribute to indicate that a specified amount, which had recently been deposited through the ATM and added to the totalBalance
, was not found in the deposit envelope. The bank would invoke this operation after determining either that the user failed to include the correct amount of cash or that any checks did not clear (i.e, they “bounced”). While adding these operations would make our system more complete, we do not include them in our class diagrams or our implementation because they are beyond the scope of the case study.