OOP Principles in Customer and Account classes of a Bank
https://softwareengineering.stackexchange.com/questions/293585
题
I am designing a Bank Application which deals with Customers having FD Accounts.
There are two approaches to this :
Approach 1
In this the customer has a list of accounts. The bank application will manage the accounts through the customers.
My mentor feels this is the correct approach. :-P
class Customer
{
String name;
Date dob;
.
.
Account[] accounts = new Account[5];
}
class Account
{
int accNo;
float amount;
.
.
}
Approach 2
In this approach each account has its associated customer reference stored. The Bank application will now manage the accounts and customers independently.
I feel this is the correct approach. :-)
class Customer
{
String name;
Date dob;
.
.
}
class Account
{
Customer customer;
int accNo;
float amount;
.
.
}
Now my issues are :
- Ideally the bank application should worry more about the account than the customer. For example, the bank should have methods like addAccount() : which will add account and create a customer implicitly if it is the first account of the customer and deleteAccount() : which will delete the account and delete the customer implicitly if it is the last account.
- There can be a use case in the future where an account can have multiple customers. So that can be accommodated easily in the second approach than the first.
Considering all this, please can you say which is a better Object Oriented Approach here?
Also how is this actually implemented in a real Bank?
解决方案
- Ideally the bank application should worry more about the account than the customer. For example, the bank should have methods like
addAccount()
: which will add account and create a customer implicitly if it is the first account of the customer anddeleteAccount()
: which will delete the account and delete the customer implicitly if it is the last account.
What is your definition of 'worry'? :)
As mentioned in @James Anderson's answer, the activities of customers and accounts are monitored, so it will not be customary if accounts' records are physically wiped out from your persistence storage (e.g. databases, or possibly simply flat files if this is actually just a small academic assignment borrowing a bank's context) the moment deleteAccount()
is performed.
What you can probably do here is to introduce temporal fields that can mark the start and end timestamps of the record, whether the record is logically considered inactive, or both (i.e. four fields). The final option may make sense if you want to track customers/accounts that are temporarily suspended, with the option that they can be activated later. E.g. a simplified example on a timescale:
01/01 ------------ 04/30 -------------- 08/31 -------------- 12/31
* Account created * Account * Account * Account
and active suspended active inactive
- There can be a use case in the future where an account can have multiple customers. So that can be accommodated easily in the second approach than the first.
True... to some extent. I only hope the following line is only meant to signify the intent to use a multi-element data structure, not a hard limit of 5 accounts:
Account[] accounts = new Account[5];
An alternative approach is to simply store references in both domain classes, e.g. in Java:
public class Customer {
// ...
Set<Account> accounts = new HashSet<>();
}
public class Account {
// ...
Set<Customer> customers = new HashSet<>();
}
In this way, you can easily identify all the accounts of a single Customer
, or all the associated Customer
s of an Account
. To refine this even further, maybe these relationships can be stored as Map<Account, AccountType>
and Map<Customer, CustomerType>
associations too.
其他提示
Oh Dear.
Your design is how bank applications were designed in the 1970s. Myself and several thousand professionals have spent decades undoing this design error to get systems looking more like option 1.
Banks deal with customers the account is just a mechanism for dealing with some of the customers money.
More importantly the stack of regulators who weigh down on any financial business are very interested in customers. They want to know about all the assets and liabilities of any individual or business; not the state of an single account. Failing to report all the accounts held by an individual, or, having more than one customer record for the same person, could get you fined or eventually lead to the loss of your banking licence.
As will deleting the customers data when an account is closed! You need to retain everything for several years.
This seems like a classical Has Many
/Belongs To
relationship type. What we usually do is kind of a merge between your 2 options, where:
- A
Customer
has a list of the manyAccount
s he has. - An
Account
has a reference to theCustomer
it belongs to.
That being said, @James Anderson is accurate as he states the importance of customers rather than the account itself.
Object Oriented Modeling, its used to represent the real world in a Software Application.
In other times, a single account, had only, and only one customer, assigned. These days, several customers, can be assigned and removed from an account.
There are many ways to model an application, so there is not really a "100% bad" or "100% good" way.
Your example is a "many-to-many" associations.
And, usually an additional, intermediate class is added.
One way to start, is model each data set, or object, explicitly excluding relations to each other, and add those relations, later.
class CustomerClass
{
int CustNo;
String name;
Date dob;
.
.
} // class CustomerClass
class AccountClass
{
int accNo;
float amount;
.
.
} // class AccountClass
class AccountCustomerClass
{
int acccustNo;
// How to relate both, added later
} // class AccountClass
Later, pick one of the "edge" classes ("Account" or "Customer"), that better suits your needs, and add a "relationship" class collection or array.
In this example, let's take "Customer":
class AccountClass
{
int accNo;
decimal amount;
.
.
} // class AccountClass
class AccountCustomerClass
{
int accustNo;
DateTime RegistrationDate;
.
.
AccountClass Account;
} // class AccountClass
class CustomerClass
{
int CustNo;
String name;
Date dob;
.
.
AccountCustomerClass Accounts[];
} // class CustomerClass
Note, that using "AccountCustomerClass Accounts[]", in "AccountClass", instead of "CustomerClass" is not "bad", is just an alternative way.
Here's a tip that will teach you to fish.
"model the world as it really is in software"
Look yourself in the mirror and say the two design options as a sentence.
Option 1: 'I am a customer and I have many accounts.'
Option 2: 'I am an account and I have a customer.'
Which one sounds silly? which one sounds real? Pick the one that works in the real world. Stick to the ubiquitous language - read Domain Driven Design (Eric Evans).
Rinse & repeat through the rest of your very successful career!