给出一个结构,比如银行账户..
class Account
{
virtual int Id { get; set; }
virtual int Balance { get; set; }
}
我想跟踪完成的交易,所以说一个简单的类......
class Transaction
{
virtual int Id { get; set; }
virtual Account Account { get; set; }
virtual DateTime Timestamp { get; set; }
virtual int Amount { get; set; }
}
我们假设我想跟踪已完成的交易,这是更智能的方法吗?
interface IAccountRepository
{
void Deposit(int account, int amount)
}
或......
class Account
{
void Deposit(int amount)
{
// this one is easier, but then I have to repeat
// myself because I need to store the Transaction
// in the database too.
}
}
Repository模式似乎是最具包容性的,因为它将具有工作单元/ orm / session(使用nHibernate)的句柄 - 但是使用类级方法似乎更直接,因为它更符合标准的面向对象原则'对此对象执行此操作'。
我的问题是,如果我想记录事务,那么我必须确保它们也被保存为数据库对象。使用类级方法进入第二条路径,我无法在Account
类内部执行此操作,因此我最终不得不重复自己。
我的另一个选择是另一种抽象..
interface ITransactionRepository
{
void CreateTransaction(int account, int amount);
}
哪种工作正常,它将A和B包装在一起,因为我会在TransactionRepository
中找到该帐户然后执行其Deposit
方法,但它并不真的觉得这是一个明智的做法。我不知道为什么,我的直觉告诉我这不是最好的方法。
这当然不仅仅适用于这一组课程 - 这是设计原则。如果你有任何想法,我想看看更多资深程序员在这种情况下会做些什么。
答案 0 :(得分:1)
我建议在帐户上使用CRUD(创建,读取,更新,删除)操作的存储库模式。
interface IAccountRepository
{
Add(Account acc);
Remove(Account acc);
Account GetAccountById(int account);
Update(Account acc);
}
然后将Deposit方法放在Account类中,就像你提到的那样
class Account
{
void Deposit(int amount)
{
}
}
然后,您通过存储库访问该帐户以更新帐户
// Get the account by id
Account acc = rep.GetAccountById(23143);
// Deposit the money
acc.Deposit(21.23);
// Update if needed
rep.UpdateAccount(acc);
转换可以以类似的方式完成,但我可能会存储帐户ID,而不是Transcation中的Account实例。
class Transaction
{
virtual int Id { get; set; }
virtual int AccountId { get; set; }
virtual DateTime Timestamp { get; set; }
virtual int Amount { get; set; }
}
答案 1 :(得分:0)
您的问题是结构DB / OO不匹配引起的问题的一个很好的例子。根据我的经验,人们倾向于支持您描述的第一个选项 - 绕过帐户业务对象并使用存储库将事务存储在数据库中。
我强烈建议不要让您的数据库结构影响业务层设计。业务对象用于实现业务行为。当您从业务角度直接访问存储库以查找属于Account类的操作时,您的业务规则将最终位于奇怪的位置 - 外部 Account类。
要回答你的问题,我在这些情况下总是采用的方法如下:
遵循业务逻辑中的OO原则。根据实际流程构建您的类和交互,因此业务规则最终会达到您期望的水平。
为数据库提供面向存储的视图。我的意思是您的存储库不需要模仿业务对象的结构。例如,实现为帐户和事务执行CRUD的存储库。