代码之家  ›  专栏  ›  技术社区  ›  Matt Briggs

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

  •  15
  • Matt Briggs  · 技术社区  · 16 年前

    刚读完 this post

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

    5 回复  |  直到 16 年前
        1
  •  17
  •   Johnno Nolan    15 年前

    马特,

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

    现在,过程代码在域模型中没有位置。如果您想使用更具程序性的样式,这很好,但可以将其与表模块或活动记录模式等一起使用。我认为在指南中,不是因为缺少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来实现这一点。对于我们来说,在测试中处理行为提供的接缝比处理暴露所有状态的接缝容易得多。原因是我不需要在测试中复制逻辑。客户端代码不存在 照顾

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

    这有助于澄清一些事情吗?

    格雷格

        2
  •  4
  •   Stefan Moser    16 年前

    如果您将它们称为“域模型对象”,那么我将假设您引用的是Fowler的域模型模式。 http://martinfowler.com/eaaCatalog/domainModel.html

    基于这个假设,那么您的问题的答案是“所有业务逻辑”,因为这本质上就是模式的定义。

    不幸的是,“域模型”这一术语最近似乎被淡化了,只表示数据的对象模型,没有任何行为。

    如果您还没有这样做,我会鼓励您阅读PoEAA,并决定您认为域逻辑在您的情况下属于何处。如果您决定使用域模型,那么我鼓励您阅读Evan的DDD书籍,了解实体、价值对象和服务之间的差异。

    希望有帮助!

        3
  •  2
  •   user29439 user29439    16 年前

        4
  •  1
  •   MicSim    16 年前

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

    1. 我不会将Person实体中的函数getFullName()归类为逻辑,它只是连接了一些字符串。
    2. 计算订单项值更有可能符合逻辑。

    第1点和第2点可能会让我进入实体。第3点并非如此。因此,我将逻辑定义为:

    • 涉及任何其他(非直接相关,如主细节)实体的任何操作

    在国际海事组织,任何这些行动都不属于实体。

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

        5
  •  0
  •   Tim Wardle    16 年前

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

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