Lab 8: Understanding Mutation
Goals: The goals of this lab are to learn how to design methods that change the state of on object or a state of a data structure, as well as how to design tests that verify the effects of such methods.
Submission: Submit your code for the all of the problems below in handins by Tuesday March 14th at 11:59pm. You can submit a zip file in handins to submit all of the Banking files. To get full credit, your code must make a good attempt at all of the problems below and be well-designed.
To understand mutation we need to learn how to:
Design methods that modify the state of an object
Design tests for effectful methods
The Problem
For this lab we will work with bank accounts. For our purposes we have three types of accounts:
Savings accounts: these must maintain a positive balance.
Checking accounts: these require a minimum balance.
Credit lines: these are to borrow a limited amount of money. They record the currently owed balance and the maximum amount that can be borrowed by the customer.
The bank has a list of Accounts where a customer may deposit or withdraw money. A withdrawal from an account cannot reduce the balance below the minimum, and, for credit lines, cause the balance owed to be above the maximum limit. When a customer deposits money to an account, the balance increases, though for a credit line this decreases the amount owed, which cannot drop below zero.
Methods that effect a simple state change.
Start a new project named Banking and import into it the files from the Banking.zip file above.
Make examples of Checking, Savings, and Credit accounts. Two examples have been created for you. Follow the same organization with your examples.
Discuss several scenarios of making deposits and withdrawals with your partner for each type of account. Make sure you understand when the transaction cannot be completed (i.e., is invalid).
Add the method withdraw to the Account class and implement it in each subclass:
// EFFECT: Withdraw the given amount
// Return the new balance
abstract int withdraw(int amount);
Discuss how to test when a transaction goes through successfully. Discuss how to signal a transaction failure (i.e. a transaction cannot be completed) and how to test that this happens in your implementation. Confirm with a TA.
Add the method deposit to the Account class and implement it in all subclasses. Remember, what happens in the Credit case when the balance would become negative (no more debt)?
// EFFECT: Deposit the given funds into this account
// Return the new balance
abstract int deposit(int funds);
Make sure your tests are defined carefully as before.
Methods that change the state of structured data.
The Bank class keeps track of all accounts.
Design the method add to Bank that allows the customer to open a new account in the bank.
// EFFECT: Add a new account to this Bank
void add(Account acct){ ... }
Make sure you design your tests carefully.
Note: Here the method does not produce any value and so inside of the test method we first invoke the reset method to initialize all data to the desired values, then invoke the method we wish to test, and then test the effects of the method - and (possibly) invoke reset again.
Design the method deposit that deposits the given amount to the account with the given account number. Make sure you take exception to any problems, e.g., no such account, or a transaction that cannot be completed.
Make sure you design your tests carefully.
Design the method withdraw that withdraws the given amount from the account with the given account number. Make sure you take exception to any problems, e.g., no such account, or a transaction that cannot be completed.
Make sure you design your tests carefully.
Design the method removeAccount that will remove the account with the given account number from the list of accounts in this Bank.
// EFFECT: Remove the given account from this Bank
void removeAccount(int acctNo){ ... }
Hint: Throw an exception if the account is not found, and follow the Design Recipe!