Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 域模型对象中应该包含多少逻辑_Design Patterns_N Tier Architecture - Fatal编程技术网

Design patterns 域模型对象中应该包含多少逻辑

Design patterns 域模型对象中应该包含多少逻辑,design-patterns,n-tier-architecture,Design Patterns,N Tier Architecture,刚刚读完Greg Young的文章,他在书中谈到微软推荐使用哑数据传输对象的模式。他暗示,在Java社区中,事情正朝着相反的方向发展 我的问题是实体对象中应该有多少逻辑?我工作的哲学(C#shop)是,如果不能序列化它,就不要将它放入实体中。重点是如何定义逻辑。举几个例子: 我不会将Person实体中的函数getFullName()归类为逻辑,它只是连接了一些字符串 计算订单项值更有可能符合逻辑 做一些预订交易我肯定会说是合乎逻辑的 第1点和第2点可能会让我进入实体。第3点并非如此。因此,我将逻

刚刚读完Greg Young的文章,他在书中谈到微软推荐使用哑数据传输对象的模式。他暗示,在Java社区中,事情正朝着相反的方向发展


我的问题是实体对象中应该有多少逻辑?我工作的哲学(C#shop)是,如果不能序列化它,就不要将它放入实体中。

重点是如何定义逻辑。举几个例子:

  • 我不会将Person实体中的函数getFullName()归类为逻辑,它只是连接了一些字符串
  • 计算订单项值更有可能符合逻辑
  • 做一些预订交易我肯定会说是合乎逻辑的
  • 第1点和第2点可能会让我进入实体。第3点并非如此。因此,我将逻辑定义为:

    • 执行任何与持久性相关的操作(读/写)
    • 涉及任何其他(非直接相关,如主细节)实体的任何操作
    在国际海事组织,任何这些行动都不属于实体


    现在,为什么/什么时候我不把第1点和第2点类型的操作也放到一个实体中?这是一种非常罕见的情况,但我不会这样做,只要实体中存储的数据需要以某种方式进行解释,然后才能被应用程序使用(例如,如果根据当前用户,字段X的内容具有不同的含义),这意味着实体的数据本身会产生一些逻辑。

    据我所知,与实体相关的所有业务逻辑都应该进入该实体。这包括根据系统的业务规则定义实体行为或内部结构的任何逻辑。这不应包括表示逻辑或持久性逻辑(活动记录设计模式的明显例外),但应包括数据验证、实体关系、状态机和其他内容,这些内容定义了实体在其试图建模的真实世界中的行为

    我试图看待它的方式是尝试使我的模型尽可能可恢复。如果要将模型移植到不同的系统,而客户机代码(或使用实体的代码)可能不同,请始终尝试考虑如何使用该模型。如果功能不是实体的一部分,它是否仍会以相同的方式遵循相同的业务规则?如果答案为“否”,则功能应放在实体中。

    Matt

    我想说你们的商店正在编写程序代码。我想澄清的是,许多大型系统(包括我工作过的许多系统)都是使用过程代码编写的,这并没有什么错。这是有时间和地点的

    现在,过程代码在域模型中没有位置。如果您想使用更具程序性的样式,这很好,但可以将其与表模块或活动记录模式等一起使用。我认为在指南中,不是因为缺少OO,而是因为使用了具有过程逻辑的领域模型

    这导致人们花费大量资源构建域层(阻抗失配、构建聚合的思维过程时间、隔离、无处不在的语言等),而没有获得域层(通常是可维护性)将提供的任何好处。换句话说,虽然你可以满足你的功能需求,但你最终花费了大量的预算,几乎没有回报

    现在回到什么是“行为”,我想从面向对象的角度而不是“领域驱动设计”的角度来关注这个问题。对象通常会封装一些状态,并公开一些行为

    快速重复:封装状态,公开行为

    那么一个对象应该有什么行为呢?简单地说,它应该是对它所封装的状态进行操作的行为。在理想的行为OO世界中,状态永远不会从仅对象的行为中暴露出来。如果我们开始看到这样的代码,请在策略上将其放入代码中:

    Customer c = GetCustomerFromRepository();
    c.Status = CustomerStatuses.Deleted;
    c.LastUpdated = DateTime.Now;
    c.UpdatedBy = GetCurrentUser();
    CustomerRepository.Save(c);
    
    我们违反了SRP。。。这段代码应该是customer对象的行为,因为customer对象的“责任”是

    封装有关客户的状态并公开行为

    因此,我们可以看到,最好使用Customer.Delete()方法。(是的,我知道这是一个坏例子…)

    现在我们也可以通过使用TDD来实现这一点。对于我们来说,在测试中处理行为提供的接缝比处理暴露所有状态的接缝容易得多。原因是我不需要在测试中复制逻辑。客户端代码不关心删除如何工作。。。它只关心客户暴露行为。因此,在我们的测试中,我们不会断言c.State==CustomerStates.Deleted和c.UpdatedBy==GetCurrentUser()等,而是简单地断言delete方法是通过使用模拟在customer seam上调用的

    现在回到标题上来。业务对象中应该包含的逻辑量是由其负责封装其状态的逻辑量。有时这是很多,有时不是。有些地方您也希望使用服务。。。一个很好的例子是为给定的行为协调多个域对象之间的交互,但即使在这里,服务也应该调用域对象上的行为

    这有助于澄清一些事情吗


    Greg

    最近,我一直在考虑创建具有结构的领域模型,并且只创建对该模型通用的行为(即,可以跨多个有界上下文使用的行为),以及针对特定于有界上下文的行为的扩展方法。这将使域模型接近DTO(对于那些类似的DTO),并限制