C# - 当一个对象改变状态时,是否应该负责创建一个历史对象?

wdr*_*one 4 c# architecture oop poco chain-of-responsibility

这是一个架构/最佳实践问题,而不是其他任何问题,所以请随意添加你的两美分.我知道我在标题中声明了状态,但这适用于对象的任何基本属性.我认为下面的帐户示例将有助于证明我的问题比状态好一点.

这是一个示例Account对象:

public class Account
{
   private IList<Transaction> _transactions;

   public AddTransaction(trans as Transaction)
   {
      _transaction.add(trans)
   }
}
Run Code Online (Sandbox Code Playgroud)

现在假设我想开始记录每次使用此对象添加事务时的历史记录.

public class AccountHistory
{
   private DateTime _historyDate;
   private String _details;

   public AccountHistory(string details)
   {
      _historyDate = DateTime.Now;
      _details = details;
   }
}
Run Code Online (Sandbox Code Playgroud)

在这个级别,我通常做的是将一组历史事件添加到帐户对象,并添加一行代码以在AddTransaction()方法内创建历史事件,如下所示

public AddTransaction(trans as Transaction)
{
   _transaction.add(trans);
   **_historyEvents.add(new AccountHistory("Transaction Added: " + trans.ToString());**
}
Run Code Online (Sandbox Code Playgroud)

现在下一部分是问题开始出现的地方.假设我想进行批量发布,并且我希望保留一份记录,说明在此批量发布中哪些帐户已更改为报表,或者我是否需要稍后撤消.所以我会创建一个像这样的对象.

public class HistoryGroup()
{
   private IList<AccountHistory> _events;
}
Run Code Online (Sandbox Code Playgroud)

从这里我看到一些不同的选项来处理这个,因为上面的示例代码无法处理它.

1)在Service类型对象中创建一个函数,该对象循环调用AddTransaction()方法的帐户列表,并创建与HistoryGroup关联的历史记录

 public void AddTransactions(IList<Account> accounts, Transaction trans)
    {
       HistoryGroup history = new HistoryGroup(); 
       for (int x=0;x <=accounts.Count - 1; x++)
       {
         accounts(x).AddTransaction(trans);
         history.AddEvent(new AccountHistory("Added Transaction: " + trans.ToString();
       }
    }
Run Code Online (Sandbox Code Playgroud)

2)将一些类型的HistoryManager对象与要添加的事务一起传递到AddTransaction方法中.然后该函数可以使用历史管理器来创建记录.

好的,这篇文章足够长了.如果我不够清楚,请告诉我.谢谢你的输入.

Jus*_*ner 9

你的方法可能工作正常,但让我提出一个替代方案.

为什么不向Account类添加TransactionAdded事件.

然后,您可以从(我在这里猜测)HistoryGroup对象订阅事件,以便每次触发Event时都添加一个新的AccountHistory对象.

UPDATE

正如评论中所提到的,实现目标的另一种方法是让HistoryGroup实现一个接口(ITransactionLogger或类似的东西),然后修改Account以便可以注入ITransactionLogger依赖项.

从复杂性和调试的角度来看,使用这些路由中的任何一个都会使事情变得更容易管理,但是不允许像事件这样的多个Logger.

这将使您的代码更灵活,同时允许对TransactionAdded事件感兴趣的其他消费者进行订阅.

  • 我的两分钱:尽可能避免使用事件.它们很难调试和维护,因为代码中没有关于调用事件时会发生什么的提示.您必须在代码中搜索所有可能的订阅者,以了解可能发生的情况和不发生的情况.您必须管理所有订阅和取消订阅.因此,对于多个订户方案,事件仍然是一个不错的选择,但我通常不会建议仅在单个订户方案中使用它们,因为将来某个时候可能会有多个订户. (2认同)