views:

59

answers:

1

i see this pattern over and over again and wanted to get opinions:


Option 1: On the wire object and Business object composition:

On the wire object - the data that is serialized and sent back and forth across machines (client / server, etc). This is a POCO object.

For example:

public class Order
{
    public int Price;
    public int Amount;
}

Business Objects - another class that usually has some or all of the properties as the on the wire object but also some calculated fields. This usually uses composition on top of the "on the wire" object.

public class OrderBusinessObject  
{  
     private Order _order;

     public OrderBusinessObject(Order o)
     {
          _order = o;
     }

     public int Price {return _order.Price;}  
     public int Amount{return _order.Amount;}  
     public int Total{return _order.Price * _order.Amount;}            
}


Option 2: On the wire object and Business object by converstion:

This would be the same on the wire object as example 1 but the business object, instead of using composition, would use translations:

public class OrderTranslator
{
    public OrderBusinessObject Translate(Order o)
    {
         OrderBusinessObject bo = new OrderBusinessObject();
         bo.Amount = o.Amount;
         bo.Price = o.Price;
         return bo;
    }
}

public class OrderBusinessObject  
{    
     private int _price;
     private int _amount;

     public int Price {return _price;}  
     public int Amount{return _amount;}  
     public int Total{return _price * _amount;}            
}


Option 3: Dont have the business object at all and have all your calculations done in a seperate calculator class. NOTE: consumers get the on the wire object and a calculator

public class Consumer
{
     public void ShowTotal(Order o)
     {
         Calculator calc = new Calculator();
         double total = calc.ShowTotal(o);
      }
}

I wanted to get people's opinions on if there is a best practice or pattern here or this is just a matter of user preference

+1  A: 

In enterprise level systems, my preference is to go with option 2. This method is conducive to contract-first development in a SOA environment and allows your domain objects to remain independent of wire representations. It facilitates contract changes over time and allows the domain and data contacts to change indepently of each other. The translation code can be a bit of pain, but you can use a tool like Automapper to speed that up.

That said, you might not require this level of flexibility in every app.

To me Option 3 would tend to go against object-oriented and domain-driven principles because it externalizes behavior, leading towards an anemic domain model. Option 1 also goes a bit against domain driven design because your domain models would be dependent on data contracts, when really that should be the other way around. In a domain centric model, those domain objects should be independent.

Greg Favinger