Search code examples
c#.net-3.5

Separating business logic


I have a customers Class with properties and methods defined. At present it contains methods for any type of task associated with Customers. For example, it contains a method "InsertOrUpdateCustomer". This method either inserts a new customer record to the database or facilitates editing of an existing customer record.

This class also contains some validation methods for customer fields.

I think that it is not a better way. I want to break it somewhat like this:

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

I want to implement this interface to another class, say Customers:

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

    // Constructor
}

I want to know:

  1. Where to add methods to Insert or Update new customer? Should I create another class or add methods to the above class?

  2. Breaking my old single class with the above given way is beneficial or not? What benefit an Interface has in the above code?

  3. I want to remove validation methods and use a Validation Framework instead. Do I need to create a different class "CustomerValidations" where I would do validations or I should use above class itself?


Solution

    1. For insert and update methods, I'd create a repository, with CRUD methods (e.g. ICustomerRepository)
    2. I don't see the immediate benefit of the ICustomer interface
    3. I would use the approach where validation is outside the business entity; e.g. in dedicated validation classes, or in a configuration file like spring.net validation.

    Overall, I think it is a good idea to have a single responsibility per class - e.g. business state Customer, persistent storage NHibernateCustomerRepository : ICustomerRepository and validation CustomerValidator.

    An example for the repository:

    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);
      // ...
    }
    

    As you can see, the first methods of this interface will be similar for most business entities and could be abstracted into:

    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);
    }