The ultimate question is: How are cla开发者_如何学Gosses normally structured in applications?
I am currently writing a test banking application in asp.net For example: I have these two classes. One represents an account, and the other is a utility class (It has stuff to do with accounts, i.e. getting accounts, updating accounts, etc.)
public Account {
int ID;
string Name;
double Balance;
}
public Accounts {
public List<Account> GetAllAccounts();
public Account GetAccountByID(int AccountID);
}
in my presentation layer, whenever I want to get an account I am using:
Account editAccount = new Accounts().GetAccountByID(234);
You can see I am instantiating a new Accounts() class to get an account. What should I actually be doing? Or is this correct? Does a static class fit this need better?
I feel like this is getting very cluttered and if it gets bigger it could be uncontrollable with classes having similar names.
How would you normally structure this? Do you put those two methods in the Accounts class into the Account Class?
Any insight here would be so great.
Thanks
Experience is often the best guide when it comes to such questions, because API design is still more an art than a science. There are opposing forces in play for every class you design:
- On the one side, we want classes to be cohesive encapsulations of related data and behavior.
- On the other side, we want to adhere to the Single Responsibility Principle to avoid God Objects.
In your particular case it may seem like all the behavior relates to Accounts, which would be an argument for encapsulating it all into one class.
However, in my personal experience, I often find it valuable to separate object creation and lifetime from the actual types. This allows Dependency Injection (DI) and DI Containers to take care of the lifetime aspect of instances, while the classes can concentrate on encapsulating data and behavior.
In your specific case, the Accounts class looks a lot like a Repository, which is a type (often abstract) that we use to find instances in databases or other persistent storage. They are often better modeled as separate types than the classes they retrieve.
On a final note, in OOD you should not worry about class explosion. Many small classes with distinct responsibilities are preferrable.
You are looking for the Repository pattern, which abstracts a collection of domain objects. A repository for your domain might look like:
public interface IAccountRepository
{
IList<Account> GetAll();
Account GetById(int accountId);
// Insert and delete, if they apply
// Other account-specific queries and operations
}
A presenter would declare a dependency on an IAccountRepository
:
public class EditAccountPresenter
{
private readonly IEditAccountView _view;
private readonly IAccountRepository _accounts;
public EditAccountPresenter(IEditAccountView view, IAccountRepository accounts)
{
_view = view;
_accounts = accounts;
_view.DataBinding += OnDataBinding;
}
private void OnDataBinding(object sender, EventArgs e)
{
_view.Account = _accounts.GetById(234);
}
}
Next, implement IAccountRepository
however you like and put it all together when you create the presenter:
var dataContext = new AccountDataContext("...connection string...");
this.Presenter = new EditAccountPresenter(this, new AccountRepository(dataContext));
This helps to decouple the definition of the operations from their actual implementation. It also allows you to choose which repository you give the presenter, decoupling it from the implementation as well.
The flexibility of this approach offers more freedom, and stands up better to change, than directly instantiating dependencies. This is called the Dependency Injection pattern.
From the information you have provide I would make GetAllAccounts and GetAccountByID static and leave them in the Accounts class. You can also create a static function on Accounts responsible for creating and retrieving Account objects. Your class should have only one reason to change (Single Responsibility Principle).
Seeing Account
and Accounts
classes bothers me a bit...I think Bank
may be a better name for the latter. That way, you have a Bank that provided access to all accounts, or to a single specific account.
In general the two methods would go in the Account class. There is no compelling reason to have two classes in this case. If you are doing 'Get' methods like your GetAccountByID
these should be set as static
. Doing this allows them to be called without instantiating a new account object.
public static Account GetAccountByID(int AccountID);
then the call:
Account editAccount = Account.GetAccountByID(234);
How are classes normally structured in applications?
Poorly.
What's more important than figuring out exactly what should be static and so on is making sure that all the relationships between the various classes reflect the relationships between the real-world things that they model.
Is "Accounts" really something that is in the model at all? Do you need to have a class for it? Could you just have a list of accounts and then use query operators on it? Instead of a method that gets an account by its ID, you could simply have a list and then use accountList.First(x=>x.Id == 123)
. Perhaps this is a concept you don't need to even model in the first place.
精彩评论