分离业务逻辑

时间:2010-11-26 08:29:46

标签: c# .net-3.5 code-design

我有一个客户类,其中定义了属性和方法。目前,它包含与Customers关联的任何类型任务的方法。例如,它包含方法“InsertOrUpdateCustomer”。此方法将新客户记录插入数据库或便于编辑现有客户记录。

此类还包含一些客户字段的验证方法。

我认为这不是一个更好的方法。我想打破它有点像这样:

interface ICustomer
{
    string CustomerName;
    date FinancialYearStartDate;
    date FinancialYearEndDate;
    string TaxNo;
    string Address;
}

我想将这个接口实现到另一个类,比如Customers:

class Customers: ICustomer
{
    // Properties
    CustomerName { get; set; }
    FinancialYearStartDate { get; set; }
    FinancialYearEndDate  { get; set; }
    TaxNo { get; set; }
    Address { get; set; }

    // Constructor
}

我想知道:

  1. 在何处添加插入或更新新客户的方法?我应该创建另一个类还是向上面的类添加方法?

  2. 用上面给出的方式打破我的旧单班是否有益?接口在上面的代码中有什么好处?

  3. 我想删除验证方法并使用验证框架。我是否需要创建一个不同的类“CustomerValidations”来进行验证,或者我应该使用上面的类?

4 个答案:

答案 0 :(得分:4)

  1. 对于插入和更新方法,我使用CRUD方法创建repository(例如ICustomerRepository
  2. 我没有看到ICustomer界面的直接好处
  3. 我会使用验证在业务实体之外的方法;例如在专用验证类中,或在spring.net validation等配置文件中。
  4. 总的来说,我认为每个班级single responsibility是个好主意 - 例如业务状态Customer,持久存储NHibernateCustomerRepository : ICustomerRepository和验证CustomerValidator

    存储库的示例:

    interface ICustomerRepository
    {
      // Get by id
      Customer Get(int id);
      void Delete(Customer customer);
      IList<Customer> GetAll();
      // creates a new instance in datastore
      // returns the persistent identifier
      int Save(Customer customer);
      // updates if customer exists,
      // creates if not
      // returns persistent identifier
      int SaveOrUpdate(Customer customer);
      // updates customer
      void Update(Customer customer);
    
      // specific queries
      IList<Customer> GetAllWithinFiscalYear(DateTime year);
      // ...
    }
    

    正如您所看到的,此接口的第一个方法对于大多数业务实体来说都是类似的,可以抽象为:

    interface IRepository<TId, TEntity>
    {
      // Get by id
      TEntity Get(TId id);
      void Delete(TEntity entity);
      IList<TEntity> GetAll();
      // creates a new instance in datastore
      // returns the persistent identifier
      TId Save(TEntity entity);
      // updates if customer exists,
      // creates if not
      // returns persistent identiefier
      TId SaveOrUpdate(TEntity entity);
      // updates customer
      void Update(TEntity entity);
    }
    
    interface ICustomerRepository : IRepository<int, Customer>
    {
      // specific queries
      IList<Customer> GetAllWithinFiscalYear(DateTime year);
    }
    

答案 1 :(得分:2)

我的回答:

  1. 我将Insert方法放在将包含ICustomers的类中(我想会有一个或多个)。至于更新,它取决于此方法的作用。如果您要更新某些客户的内部字段/属性,则应该使用ICustomers;

  2. 最大的好处之一是恕我直言,因为您可以轻松地模拟/存根,因此单元测试依赖于客户的代码要容易得多。

  3. 我会使用这个类本身。

答案 2 :(得分:1)

诸如“InsertOrUpdateCustomer”之类的操作通常是客户实体服务的一部分(在适配器模型中)(即在另一个类中,如您所建议的那样)

想到它的方法是:'谁负责拯救顾客?'

一种可能性是将ICustomerValidator“注入”Save方法。

答案 3 :(得分:0)

为基本上是数据容器的类引入接口很少有用。相反,您可能希望分别创建两个具有数据库持久性和验证角色的类。有一个接口可以让您有机会使类可以互换以进行测试或不同的存储/验证策略。