6

试图实现 3 层(不是:层,我只是想在一台机器上逻辑地分离我的项目)架构我发现了很多不同的方法,我很困惑,最好的方法是什么(如果有的话)在 WinForms 应用程序中。

现在我对项目中应该存在的 3 层毫无疑问:

  • UI(表示层)
  • BLL(业务逻辑层)
  • DAL(数据访问层)

UI中,我放置了所有的 WinForms。还必须有一些逻辑来用来自控件的数据填充对象并将其传递给 BLL 层。

DAL中,我想使用 ADO.NET 放置用于数据操作的类和方法,例如:

public class OrderDAL
{
    public OrderDAL()
    {
    }

    public int Add(Order order)
    {
        //...add order to database
    }

    public int Update(Order order)
    {
        //...update order in database
    }

    //...etc.
}

问题在于 BLL 和问题 - 我应该使用数据传输对象在层之间传递数据,还是应该传递整个类?

如果我选择使用DTO,那么我必须创建额外的公共类,Order即对 UI、BLL 和 DAL 的引用:

public class Order
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public string Number { get; set; }
    public string CustomerName { get; set; }

    public Order ()
    {
    }
}

并将逻辑分离到 BLL 中:

public class OrderBLL
{
    public OrderBLL()
    {
    }

    public int Add(Order order)
    {
        OrderDAL orderDAL = new OrderDAL();
        return orderDAL.Add(order);
    }

    public int Update(Order order)
    {
        OrderDAL orderDAL = new OrderDAL();
        return orderDAL.Update(order);
    }

    //...etc.
}

这种方法以不同的名称被使用,其中包括:herehere
另一方面,一些“聪明人”和他们的追随者(比如这里)称它为贫血域模型并抱怨它是一个糟糕的设计和不应该使用的反模式。

优点:

  • DTO 可以很容易地通过设计来表示数据库表,
  • it's light and clear, contains only fields needed for database,
  • DAL doesn't have to reference BLL,

The cons:

  • anti-pattern (sounds scary ;P),
  • violation of OOP (separated properties from methods),
  • because logic is in different class, it may be more difficult to maintain when something changes.

So, the opposite approach is to pass the whole object between layers, like here: no DTO, just BLL looking like that:

public class Order
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public string Number { get; set; }
    public string CustomerName { get; set; }

    public Order()
    {
    }

    public int Add()
    {
        OrderDAL orderDAL = new OrderDAL();
        return orderDAL.Add(this);
    }

    public int Update(Order order)
    {
        OrderDAL orderDAL = new OrderDAL();
        return orderDAL.Update(order);
    }
}

The pros:

  • it's a nicely encapsulated object, following OOP rules (I suppose ;)).
  • both logic and properties are in one place, easier to maintain and debug.

The cons:

  • to use the object, DAL has to reference BLL (that's not how the 3-tier layer should do, isn't it?).
  • class may contain some fields that are not used in Database, as well as some fields from Database (like Id) do not represent "real life" object.

So, it looks like whatever I choose, I'll violate some rules. What's better way then, which should I choose? Maybe there is other approach I haven't found?

4

1 回答 1

9

I don't like DTOs, because they mean creating a dual hierarchy with little or no value.

I also don't like the idea of making model objects responsible for their own persistence. I prefer a separate persistence layer. Why? Model objects don't always need to be persisted to be useful. Business logic and functionality are orthogonal to persistence.

If you have two layers it's possible to keep a one way dependency graph: persistence knows about model, but model does not know about persistence. You end up with a cyclic dependency if model objects are responsible for persistence. You can never test or use model objects without persistence.

My advice? Don't do DTOs. Break out a separate persistence layer.

于 2012-06-29T10:01:25.977 回答