Bank Project by Dr. Bezaire and Ms. DiBenedetto
The Bank Project is part of the summer work for AP Java 2024 - 2025. Using the UML diagram and project description, write the BankAccount, Bank, and BankClient classes and then turn them in by August 27, 2024.
After writing and testing the classes, submit them to the CS50 autograder and look at the feedback. You can revise and resubmit your code multiple times. Make sure to look at the autograder's feedback each time to ensure that your code is correct and well-styled.
Also spend time thinking about why the classes are designed the way they are. After you have finished the project, look through the list of Questions. You do not need to turn them in, but you will be asked similar questions on a quiz within the first few class sessions.
Academic Honesty
It's important that you write this code yourself to help prepare for AP Java. Here's what's ok and not ok for this assignment:
The Summer Bank Project is an individual assignment |
Read through this site for assistance or refer to the Java online textbook |
Copy individual method headers from this site into your code |
Look at your own code from class last year |
Use standard debugging strategies |
Ask Dr. Bezaire or your classmates for verbal or email conceptual help or specific debugging help |
AI: Ask questions to and copy code snippets from the CS50 Duck Debugger |
Ask questions or look at content on our private Stack Overflow for Teams site |
Search and look at content on Stack Overflow. Do not copy code directly and make sure to cite any code in your program inspired by
what you found on Stack Overflow. A simple comment with the link to the Stack Overflow page is sufficient |
Show the erroneous part of your code to someone who has already successfully completed it for help with debugging.
The person helping should not change your code or give their correction verbatim, but can point out where or what seems wrong in your code. |
Do not look at or copy from someone else's code for this assigment |
AI: Do not use any AI helpers other than the CS50 Duck Debugger built into your CS50 IDE |
You are responsible for fully understanding any code you submit in this class.
Reading Guide
This document contains many sections; refer to the reading guide below for suggestions based on your comfort level with Java, the CS50 IDE, and object oriented programming.
If you are ... |
Less Comfortable |
More Comfortable |
Very Comfortable |
Read ... |
- Reference (as needed)
- UML
- Expectations
- Command Reference
- Demo
- Development Strategy,
expanded ▶
- Checks
- Questions
|
- UML
- Expectations
- Command Reference
- Demo
- Development Strategy
- Checks
- Questions
|
- UML
- Expectations
- Command Reference
- Demo
- Challenges
- Questions
|
UML
This UML diagram was produced using https://yuml.me/.
For a refresher on UML, see this UML reference. Pay attention
to the method headers, including method and parameter names - these are clues to what
the methods should be doing.
Expectations
In addition to having correct, well-styled code, it is also important to follow good
design practices. Your code should:
- Have appropriate and descriptive variable and method names; comment when needed
- Not be repetitive (generalize repetitive chunks and delegate them to a
callable method where possible)
- Make good use of loops and logic to improve efficiency
- Be properly encapsulated
- Be well organized - BankAccount should handle all logic within the domain of
BankAccount and nothing specific to Bank; Bank handles all Bank-related logic; and
BankClient handles the user menu and manages the output from Bank, as well as managing all print statements
to the user and inputs from the user
- Have a header comment that includes your name as the author, the date you started
working on the code, and the purpose of the overall project and each file
Command Reference
You will need to run these commands in the terminal of your CS50 IDE (Integrated Development Environment).
For help understanding how to use the IDE, click here.
- Run this command to get the code template:
wget https://www.andovercs.org/code/bank.zip; unzip bank.zip; cd bank;
- Next, run this command to open a file for editing:
code BankAccount.java
- To compile a file, run:
javac BankAccount.java
- To run a class with a main method, run:
java BankAccount
- After writing code, run this command to check your style score (1.00 is highest):
style50 -o score BankAccount.java
- For a visual of how to improve your style, run:
style50 BankAccount.java
Or, while your file is active in the script editor, look to the right side of the tab strip for the
style50 tab and click it. You will see a side-by-side view of your current file and the proposed
changes to improve style. From here, you can click another tab to Accept changes which will make
the proposed style changes for you.
- When you are ready to test or turn in your code, run this command to submit your code:
submit50 mbezaire/checks/main/java/bank
Demonstration
Your final working program should behave similarly to the following example.
Development Strategy
Download the starter code using the commands above. Work on the BankAccount class first.
Once BankAccount works properly, then work on the logic of the Bank class without BankAccount
objects. Next, incorporate BankAccount objects into the Bank class. Lastly, write BankClient,
adding a menu in its main method. Once you have tested each menu option, put it into a loop
so that your user can perform multiple transactions before quitting the program.
Test your code often and submit it to the autograder whenever you need feedback and again when you are done. Click these triangles to expand more detailed instructions:
Each class file should have a header comment describing its purpose, listing the date the code was written, and including the author name(s).
For code developed from templates, the template author should also be listed. Choose descriptive names for your variables and methods,
use proper indentation, camelCase, and correct capitalization rules. You can check your style with these commands.
Add brief comment to any code that is not self-documenting (meaning the variable and method names sufficiently explain what is happening).
BankAccount
First, add the fields listed in in the UML of Bank Account. Then, develop the methods of BankAccount with a hard-coded pin number (set to 1234) and assume users will only ever call the methods with arguments that make sense
Create a BankAccount class with the following attributes:
- String name
- int pinNumber (4 digits) //unique
- double balance
Add the following methods to the BankAccount class:
- a no-args constructor that sets default values for attributes
- A constructor that accepts name and balance as parameters, randomly sets pinNumber
- A constructor that accepts name as a parameter, sets balance to 0.0 and randomly sets pinNumber
- A method with the header: void deposit(double amt) that accepts a double as a parameter and increases balance by this amount. It should not accept negative amt values.
- A method with the header: double withdraw(double amt) that accepts a double as a parameter and decreases the balance by this amount as long as it does not cause the balance to become negative. It should return the amount that was withdrawn. (If balance is 500. And user tries to withdraw 600, only 500 will be removed from the account and the return value will be 500)
- A getter method with the header double getBalance() that returns balance
- A getter method with the header String getName() that returns the name
- A getter method with the header int getPinNumber() that returns pinNumber
- A method with the header boolean validateAccount(String n, int p) that returns true if n matches name and p matches pinNumber. Returns false otherwise.
- A method with the header String toString() that returns name, pinNumber and balance. The balance does NOT need to be formatted exactly like money with 2 decimal places.
After the methods work with reasonable arguments,
next tackle unreasonable arguments: add logic so that users can't deposit
negative amounts (so they can't sneakily use deposit to withdraw money)
and also add logic to prevent users from withdrawing more than they have
in their account and from withdrawing a negative amount of money. Test your logic to confirm it works.
Test the BankAccount class by creating a BankAccountTester program or
adding a main method to BankAccount. Create several BankAccount objects,
use a Scanner or hard-code inputs so that you can test what happens when you
try to withdraw a negative amount, withdraw more money than is in the account,
deposit an negative amount, etc.
Next, work on the validateAccount method. It's especially helpful to have a hard-coded pin value while testing this method. Test this feature before moving on.
Both the name and the pin will need to be checked against what the user supplies. The name field is a String; recall that Strings must
be checked for equality a different way than numbers (because they are objects). Make use of the equals method.
Lastly, remove the hard-coded pin number and replace it with a call to a random pin generator that will ensure a 4-digit int, and then test your code.
Since the pinNumber field is an integer, the only way to ensure that it has a 4-digit number is to make the numeric value between
1000 and 9999. Within this range, any number should be equally likely to be assigned as the pinNumber.
That is 9000 unique numbers!
You may use Math.random() or the Random class's nextInt() method for this. If you use the Random class, remember:
- Import it using: import java.util.Random
- Create a new Random object
- When calling the nextInt() method of your Random object, recall that it takes one argument; the number
of random states, and can then return any number from 0 to that total number of states (random numbers) - 1.
Validate all of your methods and once you
are confident they work, you can remove the main method from BankAccount if you added
it. If you made a separate file, no need to remove anything as long as all the print
statements and any Scanner calls are removed from BankAccount.java before you submit your work.
Once BankAccount seems to work, submit your code so far using:
submit50 mbezaire/checks/main/java/bank
The checks related to Bank will not pass yet, and that's OK! You're just looking for the
BankAccount checks to pass. Once they pass, you're ready to move onto Bank.
Bank
Create a Bank class that supports up to 3 BankAccounts. Do not use Arrays or any type of Collection or List.
Each BankAccount will be stored in a separate field. Add all the fields and set them to hard-coded values to start.
Write the Bank's constructor, which should accept name as a string and initialize the three BankAccount objects to null. Add a variable numAccounts that keeps track of number of accounts.
The constructor should set numAccounts to 0 to start. A final static variable of MAX_ACCOUNTS should be set to 3 (this can happen where you declare MAX_ACCOUNTS or in the constructor).
Add all the methods, but have them only return a hard-coded value to start.
Any methods that must return an object, hard code them to return null instead. Your first
goal is to have a Bank class that compiles, without adding any real logic.
Include the following methods:
- public int addAccount(String n, double b), which will check to see if there is room in the bank for this account. If there is room, an account will be created using this information. addAccount should return the pinNumber that is created for this account or 0 if no account was created.
- public boolean deposit(String name, int pin, double amt) - method will determine whether an account with name and pin exists. If it exists, it will use the deposit method of the appropriate Bank Account to change amount and return true. If it doesn't exist, it will return false.
- public double withdraw(String name, int pin, double amt) - method will determine whether an account with name and pin exists. If it exists, it will use the withdraw method of the appropriate BankAccount to change amount and return the amount withdrawn. If it doesn't exist it will return 0 or a sentinel value that is used in BankClient to display a message about the incorrect name/pin combination.
- public String showAccount(String name, int pin) - method will determine whether an account with name and pin exists. If it exists, it will call the toString method of the appropriate Bank Account to return account information to the user. Return null if no account is found.
- private BankAccount findAccount(String name, int pin) - method returns a reference to the BankAccount instance variable that matches the name and pin. If no match exists, method returns null. This is a private method and should only be called by the Bank Class to help the deposit, withdraw, and showAccount methods.
After your class compiles, next tackle the logic to keep track of the number of accounts
open at the Bank, still without using the BankAccount fields yet.
You'll want to make use of your MAX_ACCOUNTS and numAccounts variables. The goal is to
have the addAccount method use and change those variables appropriately.
- When addAccount is called, first check that there is space at the bank - numAccounts must
be less than the MAX_ACCOUNTS variable (the capacity of the Bank). If there's no space, the
addAccount method needs to stop running (return). Since it is supposed to return an int for the
pinNumber, we need a value to return instead. This value must still be an int, but a number
that can signal to the calling method that a new account was not created. Let's use 0 to
signify that no new account was created.
-
If a BankAccount will be added, the number of accounts at the Bank will increase, so numAccounts
should be increased by one.
- Next, submit your code again to check that you're on the right track.
All BankAccount and only a couple of Bank checks should pass at this point.
Once they pass, you're ready to incorporate BankAccount objects into your Bank class.
Now implement the fields for three BankAccount objects and work
on the logic of your createAccount method.
Then, make sure your code compiles before moving on.
Now, in addAccount, find the point in the logic where you've determined there's space
for another account. Instantiate (create) an account with the information passed into the addAccount
method. At the end of the method, make sure to return the reference to the account you instantiated.
- Next, work on your viewAccount method. Make sure your code compiles before moving on.
Now, check that your Bank code works regardless of how many BankAccounts have been created.
Look through every place in Bank.java where you refer to a BankAccount object. What would happen if
that reference were null (didn't point to an object yet)? Add logic to your code to check for null
values and deal with them appropriately, so that you don't run into any runtime errors when executing
your code.
Now, make sure your code compiles and then test it.
- Test that you can add 1 account and view it
- Then add 2 more accounts and view any of them
- Try to add a 4th account, confirm that you cannot
Next, work on your deposit and withdraw methods at the Bank level. They must call the corresponding methods
in BankAccount but their return type is different. Then test your code again.
Notice that the deposit method in Bank has a boolean return type. Think about
when it should return true and when it should return false.
There are two main steps that occur in Bank's deposit method. If either of them fail in some way,
it would make sense to return false. If they are both successful, it would make sense to return true.
The two steps are:
- Finding the correct BankAccount, where the name and pin match what's provided
- Calling the corresponding method on that BankAccount object and having it run successfully
Think of how you can find out that these steps were successful and return false if they are not.
For Bank's withdraw method, the return type is double, which should usually be the actual
amount of money that was withdrawn. What value should be returned if step 1 above doesn't
work, meaning the pin or name was incorrect and a matching BankAccount from which to withdraw
is not found?
- Once all your Bank methods seem to work correctly, remove any print statements and main methods from Bank and BankAccount that you were using to test your code and ensure your code still compiles afterward.
Once Bank seems to work, submit your code again:
submit50 mbezaire/checks/main/java/bank
If all of the Bank-related checks pass, you are ready to move onto BankClient.
BankClient
Next, create a BankClient program as a sort of user interface for your Bank.
You'll need to create a Bank object (hard-code the name of the Bank; don't ask the user for it) and then provide a menu of options to the user.
Based on their response, you'll collect any additional information you need, call the
appropriate method(s) in Bank, add logic to evaluate the output of any method calls on Bank
and then print information back to the user as expected.
Make sure to import java.util.Scanner so you can create a Scanner to collect
user input. Print out a menu prompt in the main method.
The menu should have the following options, in the same order:
- Create an Account - If room in Bank, prompt for name and starting balance, create account, generate an output “Welcome” message, output the pin number to the user.
- Make a Deposit - Prompt for name and pin number. If valid allow deposit. Output deposit amount.
- Make a Withdrawal - Prompt for name and pin number. If valid allow withdrawal. Output the amount withdrawn.
- View Account - Prompt for name and pin number. If valid display account information by calling showAccount
- Quit
For each choice in your menu, write a
corresponding method in BankClient that:
- asks for any additional information
- calls the appropriate method in Bank
- manages any output from that method as needed
Add a loop to your main method and move the menu code inside it so that your user can conduct multiple
transactions without having to quit and restart the program.
Hint: when using a Scanner object to get input from the user at the terminal,
you have access to methods such as:
- nextInt()
- nextDouble()
- nextLine() // for Strings
Also recall that, when you make a call to nextInt() or nextDouble(),
the Scanner object leaves a newline character (\n) hanging around,
ready to cause trouble the next time you call nextLine(). To fix this issue,
every time you make a call to nextInt() or nextDouble(), make a call to nextLine()
afterward, like so:
Before | After |
int x = ear.nextInt(); String name = ear.nextLine(); // this is skipped |
int x = ear.nextInt(); ear.nextLine(); // this eats the new line String name = ear.nextLine(); // this one will work |
If you developed a Custom.java file in Java Programming last year (Spring 2023 semester), you may copy it
into your Bank project folder and use the methods you developed to avoid having to make the extra call to nextLine().
Test your code running this program, and then submit your code again.
Once you pass all the checks, look through your code again to ensure you have good design, and then check your style to ensure you have at least 0.85 out of 1.00.
submit50 mbezaire/checks/main/java/bank
Checks
Submit50 will check:
- You are passing in three files: Bank.java, BankAccount.java, BankClient.java
- Each file has a header comment listing author(s), date started, and explaining the purpose.
- When a BankAccount is constructed, any arguments are used to set fields, any remaining fields are set to default values.
Also, pinNumber is randomly set to a number between 1000 and 9999
- Only positive amounts can be deposited and will add to the balance
- Only positive amounts can be withdrawn and will be removed from the balance; balance cannot go below 0 (but withdrawal
amount can be decreased). Withdrawn amount will be returned by the method
- BankAccount has a descriptive, user-friendly toString that includes all the fields
- Bank can be created with a name and 3 accounts
- Accounts are kept track of correctly, without using arrays, and up to 3 can be created
- Accounts can be found and viewed if the correct information is provided (and not otherwise)
- Accounts can be deposited into and withdrawn from
- Bank has a descriptive, user-friendly toString that includes the name, max number of accounts, and current number of accounts
- The instance variables of the Bank class and the BankAccount class are private.
- There are no print statements in either the Bank class or the BankAccount class (it's fine to have them in while you are working and testing, but remove them before you submit the last time).
- The BankAccount objects are completely hidden from the BankClient, meaning only the Bank class has the ability to modify and access the BankAccounts that belong to the Bank.
- Program works with no run time exceptions. For example, all menu options in BankClient should work regardless of how many accounts the Bank has.
Style50 will check:
- All standard Java conventions described in the style guide are adhered to.
Not automatic, you should check:
- Class names, variable names, method names are appropriate including the use of meaningful names, and conventional capitalization.
- Review code looking for examples of redundancy that could be abstracted out into a common method.
Questions
Here are some questions to get you thinking about how we design Object Oriented code in Java.
Please think through and answer each of these questions for yourself. You do not need to turn them in.
Challenges
Challenges are optional. Only work on them if you have completed the required work above,
submitted it, and received full credit from the autograder. You can add any or all of these
features and then submit to a different location when done:
submit50 mbezaire/checks/main/java/bank-challenge
- Add features that a Bank employee could use that are invisible to a customer.
For example, a menu like this may have an option that is not displayed which
allows a Bank employee to log in and view all accounts, delete accounts, etc.
Add this option. For example if user types '5456', the menu should display a
login screen requiring username and password. This will allow the super user privileges.
- Fix the current limitation of this program in which once it powers down, all account
information is lost. You can accomplish this using only logic we have learned in Java Programming.
- Allow an existing Bank customer to log in and then conduct repeated transactions without having to
enter their name and pin each time. Then, give them the option to log out and have the program "forget"
their name and pin without quitting. The menu prompt should appear again and require the next user to
log in before depositing, withdrawing, or viewing an account.
Reference
CS50 IDE
We use the CS50 IDE (Integrated Development Environment) in our class to write our code.
To access this environment, first sign up for Github with a non-school email, and then
visit the website: https://cs50.dev. Click
the green "Log In" button and your IDE should load shortly.
To submit work for class, you will also need to join an online classroom. The
link for joining the classroom is available on Schoology.
Once the CS50 IDE loads, you will see 3 main parts of it:
- Left side: file explorer Here you can see your files and folders
- Top: script editor The script editor where you write your code
- Bottom: terminal The terminal allows you to run Bash (linux) commands
to compile and run your programs, manage your folders and files, check your code style
and submit your work
If you have any trouble accessing or using the IDE, check out this CS50 troubleshooting guide (coming soon!).
UML
UML stands for Unified Modeling Language. It is a way to represent classes and their relationships
in an object-oriented program. Each class has its own rectangle containing areas for the class name,
its fields, and its methods. There may be arrows or other lines between classes representing
relationships between them, like "Dog HAS A Collar" or "Dog IS A Mammal".
Click here for more information about UML diagrams.
Online Textbook
When you need help or additional lesson content, you may wish to consult this online Java textbook:
https://runestone.academy/ns/books/published/csawesome/index.html
Once the school year starts, we will begin working with a different textbook called Java Methods.
Stack Overflow
Programmers invariably end up on Stack Overflow when googling questions about programming. For students, it can be helpful if used with caution.
Try to first look up your own notes or talk with your classmates to answer your questions. You are also welcome to ask the CS50 Duck Debugger
in your CS50 IDE. If you have an account on our private Stack Overflow for Teams site, you can search there or ask a question.
If you have tried the above resources but still want to look at Stack Overflow, make sure you cite (paste the Stack Overflow link as a comment in your code) any questions
that helped you and that you don't copy code from there directly or use coding concepts and keywords that you do not understand.
First, make sure the question that you are viewing has a positive rating to the left side of it (higher is better). Make sure to
read the comments under the question, especially if they have a high positive rating to the left of them. If the question seems to fit
your question, scroll down to the answer section and look for:
- The answer with a green check mark to the left (if any). This is the answer that was accepted by the questioner as best
answering their question. However, the person who asked the question gets to decide which answer to accept, so the
answer with the green check mark may not always be the objectively best answer to the question. Therefore, you also want to look for:
- The answer with the highest rating to the left of it (or any answer that is more highly rated than the accepted answer).
The highest-rated answers are usually the most efficient, most likely to use good programming practices, and most likely
to be acceptable to professional programmers.
After reading through an answer, look through any highly rated comments below it as well. Then paste a link to that web page into your
code as a comment so that you can find it again if you need it and to serve as a citation if you write code based on what you found on
Stack Overflow.
Stack Overflow for Teams
Around June 20, if you have completed Dr. Bezaire's survey and provided your github (non-school email), you'll now receive an invitation to join our private Stack Overflow for Teams site. You can search its content or post a question in it. You will need to respond to the invitation within 7 days or it will expire. If you do not see the invitation or it is more than 7 days old, please email
Dr. Bezaire to request a new one.