简体   繁体   English

3层架构 - 在层之间传递数据

[英]3-layer architecture - passing data between layers

Trying to implement 3-layer (not: tier, I just want to separate my project logically, on one machine) architecture I've found so many different approaches that I'm confused, what's the best way (if there's any) to make that in WinForms app. 试图实现3层(不是:层,我只是想在逻辑上将我的项目分开,在一台机器上)架构我发现了很多不同的方法,我很困惑,最好的方法是什么(如果有的话)在WinForms应用程序中。

Now I have no doubts only about 3 layers that should be present in the project: 现在我毫不怀疑项目中应该存在的3个层次:

  • UI (Presentation Layer) UI(表示层)
  • BLL (Business Logic Layer) BLL(业务逻辑层)
  • DAL (Data Acces Layer) DAL(数据访问层)

In UI I put all the WinForms. UI中我放了所有的WinForms。 There must be also some logic to fill the object with data from controls and pass it to BLL layer. 必须还有一些逻辑用控件中的数据填充对象并将其传递给BLL层。

In DAL I want to put classes and methods for data manipulations using ADO.NET, like: 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.
}

The problem is with BLL and the question - should I use Data Transfer Objects to pass data between layers, or should I pass the whole Class? 问题在于BLL和问题 - 我应该使用数据传输对象在层之间传递数据,还是应该通过整个类?

If I choose to use DTO , then I've to create additional common class, Order , that reference to UI, BLL and DAL: 如果我选择使用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 ()
    {
    }
}

and put the logic separated into BLL: 并把分离成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.
}

This approach, under different names, is used among others: here or here . 这种方法在不同名称下使用: 此处此处
On the other hand, some "wise guys" and their followers (like here ) call it Anemic Domain Model and complain it's a bad design and anti-pattern that should not be used. 另一方面,一些“聪明人”和他们的追随者(像这里 )称之为贫血领域模型并抱怨它是一个不应该使用的糟糕的设计和反模式。

The pros: 专业人士:

  • DTO can easily by design to represent Database table, DTO可以很容易地通过设计来表示数据库表,
  • it's light and clear, contains only fields needed for database, 它清晰明了,只包含数据库所需的字段,
  • DAL doesn't have to reference BLL, DAL不必参考BLL,

The cons: 缺点:

  • anti-pattern (sounds scary ;P), 反模式(听起来可怕; P),
  • violation of OOP (separated properties from methods), 违反OOP(方法的分离属性),
  • 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: 所以,相反的方法是在层之间传递整个对象,就像这里 :没有DTO,只是BLL看起来像那样:

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 ;)). 它是一个很好的封装对象,遵循OOP规则(我想;))。
  • 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?). 要使用该对象,DAL必须引用BLL(这不是3层图层应该如何做的,不是吗?)。
  • 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. class可能包含一些未在Database中使用的字段,以及来自Database的某些字段(如Id)不代表“真实生活”对象。

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? 也许还有其他方法我还没找到?

I don't like DTOs, because they mean creating a dual hierarchy with little or no value. 我不喜欢DTO,因为它们意味着创建一个很少或没有价值的双层次结构。

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. 不要做DTO。 Break out a separate persistence layer. 打破一个单独的持久层。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM