关于Web应用程序架构,域类和业务类之间有什么区别?

时间:2016-02-29 12:55:53

标签: c# asp.net entity-framework design-patterns

我想构建我的setMinimumBackgroundFetchInterval:应用程序,如下所示:

application:
didFinishLaunchingWithOptions:

现在我的原始解决方案如下:

只有两个类库:

    我的asp.net web form所在的
  • 1-DB 2-Data Access Layer(Using ORM[EF]) 3-Repository/Unit Of Work (Pattern) 4-Business Layer 5-Service Layer 6-UI
  • DAL (Data Access Layer)(自动生成)及其等效的部分类。

enter image description here

我对此设计的疑问:

  1. 我应该将EF放在新图层中,还是只放在域类图层中,其中每个商家都属于相关的域类或放置我的业务我的网页背后的代码中的逻辑?
  2. 有人可以澄清其中的区别 设计视角中的术语(Domain Classesbusiness logicPOCO)?

1 个答案:

答案 0 :(得分:3)

  

我应该将业务逻辑放在新层中,还是只放在每个业务属于相关域类的域类层中?或者将我的业务逻辑放在我的网页后面的代码中?

  • 您的业务逻辑应该只在您的域/业务类中,而不是其他地方;否则你冒着拥有贫血领域模型的风险,从长远来看这通常是一个坏主意。 (有趣的观看here
  • 您的服务层应仅用作业务对象之间的业务流程点,即它实现流程流,而业务对象则实现流程的各个步骤。

实施例

因此,您可能拥有一个OrderService类,该类位于服务层中,该类具有方法PlaceOrder,并驱动进程检查{{}的状态1}} class(业务对象),将Customer(业务类)保存到数据存储(可能通过存储库层),并为客户排队电子邮件确认。 (可能通过另一个服务(请注意,这是一个非常简单的示例,并不一定声称是您特定方案的最佳流程)

  

有人可以澄清设计视角(POCO,Domain Class,BusinessClass)中这些术语之间的区别吗?

  • 对于大多数意图和目的,"域"之间几乎没有区别。和"商业"对象。
  • 两者都存在为业务领域的解决方案建模 - 唯一的区别往往是,如果您遵循强大的域驱动设计方法,您将倾向于将这些类称为"域对象&#34 ;.
  • 但除此之外,你可以认为它们是相同的东西 - 它们封装了解决业务问题所需的行为和数据。

POCO不是DTO

POCO 表示"普通旧CLR对象"它基本上是指一个类的实例,它不依赖于属性形式的任何外部框架或来自所述框架的继承。

  • 因此,例如,如果您不使用EF Code First,那么您的EF模型类通常会使用EF本身在运行时使用的属性进行修饰,以了解哪些属性是主键,依此类推。
  • 通过使用EF Code First,您可以避免这种情况,并在代码中使用纯POCO。

  • POCO DTO 经常混为一谈;它们完全不一样!

  • DTO是一个类,其唯一目的是在边界(层,进程等)之间传输数据,因此通常只是一堆读/写公共字段或没有业务行为的属性。它几乎不值得"对象"分类
  • 另一方面,POCO可以同时拥有数据和行为,就像正确的对象一样,并且是Domain(或Business,如果你愿意)类的理想原型。

一些想法

我还想指出与您提出的设计相关的其他一些事情。

  • 首先,如果您使用的是EF,那么您实际上并不需要单独的工作单元,因为Order已经为您封装了一个工作单元模式。
  • 考虑一下你是否真的需要"层"一点都没例如,除非你的应用程序是一个非常简单的CRUD应用程序,否则你可能会从使用 Command / Query 模式中受益更多,而不是将你的体系结构设计为一系列浅层的,可能会导致结构不灵活,相反,使用面向特征的细垂直代码片,这意味着它们可以像它们需要的那样浅或深,从而导致更具凝聚力的设计更容易适应。有趣的观看here
  • 如果您使用实体框架,我的诚实建议是使用Code First;它比传统的DbContext模式方式更灵活。
  • 此外,可以接受EF并让它一直渗透到服务层......然后DTO开始将这些对象转换为Web控制器可以发出的传输桶。 (例如使用Automapper)。关于EF和Business Objects的一些有趣观点here **
  • 我知道这可能是因为很多典型的“坚持无知”#34;建议,但根据我的经验,它很少成为一个问题(除非你发现自己每隔一周就会转换数据库提供商!)。

使用EF Code First和拥抱DbContext将获得的好处包括 -True POCO域/业务对象(您可以在单独的程序集中声明您的BO,以便他们享受持久性无知,但也可以在另一个程序集(例如您的数据访问层)中单独映射EF - 在图层之间不做无​​意义映射的简化代码库

**我刚刚意识到我的所有参考文献都是针对同一个人的作品。我发誓,他没有付钱让我这样做。)

更新

根据OP对循环依赖感知问题的评论,这里是一个特定场景的示例代码(用例有点不起作用,只是说明性的)

.edmx

现在,上述观点是public class EmployeeNameService { readonly IEmployeeRepository _repo; public EmployeeNameService(IEmployeeRepsitory repo) { _repo=repo; } public string GetEmployeeName(int empID) { var emp = _repo.GetByID(empID); var name = emp.GetEmployeeName();//does some crazy logic based on the Employee state or whatever. return name; } } 驻留在服务"层"它具有对存储库层和域对象"层"的依赖性(引用)。 (它实际上不是一个图层,只是一个包含Domain / Business类的单独项目)。所以不用担心循环依赖。 当然,Repository会引用Domain Objects,这很好,因为它是单向依赖。

更新2

我以前没有提到的一件事是不遵循上述建议;如果您有一个非常简单的CRUD模型,您可以通过该模型获取用户输入并将其传递给数据存储,而无需任何"业务逻辑"介于两者之间,然后坚持原计划的简单层。但是,只要存在任何业务逻辑 ,就考虑使用上述概念。