GRASP模板中的贫血和丰富模型

在最近一期的DotNet&More播客中,我们与Maxim Arshinov讨论了他即将在莫斯科发表的报告。 在会议上可以很容易地获得Maxim的职位。 而且,此外,我想通过曾经流行的GRASP模板来探讨Anemic VS“ Rich”(“ Rich”)领域模型的激烈辩论的愿景


讨论进行了很长时间,例如:



在开始分析之前,我想澄清争端的话题。 贫血模型与富人模型之间的主要区别在于,它在类的主体中不包含业务逻辑 。 贫血模型的一个众所周知的例子可能是众所周知的DTO模式。


反过来,“丰富”模型可能包含描述业务规则,功能等的逻辑 。 请注意,我们正在考虑反映业务逻辑的方法。 ToString,GetHashCode和其他“技术”类的类未包含在讨论的主题中,因此将被忽略。


格拉斯


如本文开头所述,我们将在GRASP模式的背景下考虑此问题。 克雷格·拉曼(Craig Larman)在书中介绍了这套模式“使用UML和设计模式”,并极大地影响了现代编程,例如,GRASP中宣布了低耦合/高内聚规则。


对于熟悉GoF模式的人来说,这组模式似乎太模糊了。 事实是,GRASP模式的重点不在于解决应用问题,而在于对象之间某些动作和操作的责任分配


  • 创建者负责创建对象。
  • 控制器负责用户的操作
  • 间接负责组织对象之间的弱网格。
    依此类推。

在本文的上下文中,我想重点介绍以下模式:


  • 信息专家
  • 纯加工

信息专家


问题:设施之间分担责任的基本原则是什么?
解决方案:将此职责分配给具有足够信息来执行该职责的班级。


换句话说:


应将责任分配给拥有最大的执行必要信息的人-信息专家。

在C#的上下文中 :应该在类中声明一个方法,该方法的字段和属性都在该方法中使用。
例如,如果用于计算债务金额的所有必要信息都在债务人的本质(贷款额,贷款时间)之内,则应从本质上宣布适当的方法。
当然,这种简化有些过分,但要点很明确。


纯加工


问题:如果Information Expert模板未提供合适的解决方案,则哪个类应提供高内聚和低耦合的实现。
解决方案:将一组高度参与的职责分配给不代表主题领域特定概念的人工班级。


换句话说:


如果无法明确选择可以分配职责的主题模型的适当实体,则必须创建一个在主题区域中不存在的综合类。

在C#的上下文中 :如果该方法的实现提供了几个实体或外部依赖项的统一使用,则应在一个单独的类中声明此方法。 这些类称为服务。
例如,如果要计算债务额,您不仅需要知道债务人的属性,还需要知道银行的参数(利率,允许的延迟期限),那么值得创建一个包含适当方法的单独服务。


这是什么意思?


在前面的上下文中,我们可以区分一个相当简单的算法,该算法有助于做出决策, 将该方法放置在模型或服务中


  • 如果方法仅使用模型属性,则应在模型中声明
  • 如果一种方法在很大程度上使用一个模型的属性,而仅部分使用另一个模型的属性,则可以在模型中声明该方法
  • 如果该方法统一使用多个模型的属性,则值得将其移至单独的服务或现有服务
  • 如果方法使用外部依赖项(例如存储库),则应将其移至单独的服务或现有服务


总结


GRASP模式不能被视为最终真理。 但是,它们可以帮助您轻松地了解将此行为分配给哪个对象。 因此,争端是贫乏的或“富裕的”模型可能没有意义,因为在每种情况下都取决于主题区域的模型和与其相关的行为来做出决定。 在系统设计过程中,将显示有无行为的两个实体。 这是完全正确的。

Source: https://habr.com/ru/post/zh-CN470021/


All Articles