【问题标题】:Fluent Interface and class complexityFluent 接口和类复杂度
【发布时间】:2014-03-14 16:29:22
【问题描述】:

问题:使用多种方法实现流畅的接口会导致类复杂度指标增长得非常快 快。

实现流畅接口的类如何保持低复杂度?

关于特定类的一些信息:

  • 类已经有 25 个方法,而且还会再增加 15 个。
  • 类中的所有方法都以一种或另一种方式转换 $this->wrapped 对象。
  • 几个 (5-7) 方法重用了现有的方法(可以提取到类中并通过继承添加,这里没有问题)。

已经考虑过的选项:

  1. 特性 - 我想支持 PHP 5.3 及更高版本。
  2. 每个方法一个类 - 大量扩展链,不好。
  3. 'Plugins' - 帮助类以某种方式注入“主类”,通过魔术方法调用,并通过 @method 注释添加自动完成支持。

反馈(关于设计、性能、可维护性等)备受期待

检查示例:

  1. Lodash:170 种方法,1 类,8400 行

  2. Doctrine2 QueryBuilder:40+40-ish 方法,2 个类,1400+600 行代码; 通过ExpressionBuilder类分隔

  3. Symfony2 FormBuilder:10 种公开方法,1 类,300 行


可以将问题视为与语言无关 - 从 PHP 实现和设计的角度回答同样受欢迎。

编辑:

目标是为函数式编程(mapreduce 等)提供漂亮(易于使用和易于维护)的工具

【问题讨论】:

  • 如果流畅的界面增加了那么多复杂性,不围绕流畅的界面进行设计怎么样?
  • 你到底在想什么?
  • 抱歉,我不明白fluent interfaces 是如何增加类的复杂性的。具有和不具有流畅接口的类之间的区别在于在方法中返回对同一对象实例($this)的引用,该引用不返回其他值,最多增加 1 个 LOC pro 方法(并且没有额外的圈复杂度)。还是您的意思是流畅界面和/或复杂性的另一种定义? @Im0rtality
  • 理论上你是对的。然而实际上这些方法将有超过 1 个 LOC/方法(它必须在 return $this 之前做一些事情)。复杂性很快就会增加。

标签: php language-agnostic chaining fluent-interface


【解决方案1】:

复杂性是一种软件指标,表明开发人员对必须与之合作的开发人员缺乏理解。因此,软件实体(包/模块、类、方法)的复杂性越高,它的可维护性就越差。或者换句话说,修改和维护一个软件实体需要多少时间和精力。

类的主要复杂性类型有:

  • 循环复杂度:方法中的决策点数,例如“if”、“while”、“for”、“switch”
  • NPath-Complexity:通过该方法的非循环执行路径数
  • 班级长度过长:表明班级做得太多
  • 方法主体过大: 指示方法做得太多
  • 方法参数列表太长:应该按ValueObject分组
  • 提供的公共方法过多:表明可互换性受损
  • 类字段/属性过多:指示缺少嵌套对象
  • 继承的子代数:表示不平衡的类层次结构
  • 继承深度:指示不平衡/错误的类层次结构
  • 对象之间的耦合:指示过多的依赖关系

所有类型都可以通过工具测量,并且有一个角度点,这里的复杂性太高了。在这种情况下,为了通过使用设计模式来降低复杂性,重构是一个很好的选择。复杂性的另一个衡量标准是类的可测试性。 我需要多少存根/模拟,需要多少断言,等等。

实现流畅接口的类如何保持低复杂度?

Fluent Interface 是一种用于链接方法调用的设计模式。最好的链接看起来像真正的短语。它旨在提供更具可读性的代码。因此它降低了复杂性。 只需添加一行新代码即可实现 Fluent Interfaces,这只会影响较大的方法体和较大的类长度。因此,流畅的界面对复杂性的影响非常低。

随着复杂性的增加,最好用真实的短语进行链接可能会很困难,但要标记这一点,proxy classes 可以做到这一点,它将操作委托给没有流畅接口的对象。

一般而言,标记复杂性的最佳方法是将single responsibility principleinterface segregation principleinformation hiding principleloose coupling 作为关键方面。

【讨论】:

  • 完全没有抓住重点。问题不在于流畅接口类的用法,而在于实现了流畅接口本身的类。请参阅问题的第一行“问题:实现流畅的界面...”而不是“问题:使用 ...”
  • 在类本身实现简单的流利的接口不是复杂性的问题。如果您要为真正的短语使用实现流利的界面,这可能是一个问题,因此您可以通过代理访问它以标记复杂性。我试图在答案中说。
【解决方案2】:

一种方法是拥有一个简单、可靠的基类,该基类提供实现流畅接口类的工具方法。然后,流畅的接口类只需调用它所做的所有事情的基类,将复杂性降低到单个流畅的接口类。

您是否已经为您的流利界面设计了一个设计? (我想知道您实际上会使用多少种方法。)

【讨论】:

  • 1) 所以想法是让多个助手与 main 类紧密耦合? 2)类目的是通用函数式编程库,由用户通过链接选择他想要使用的内容。
猜你喜欢
  • 1970-01-01
  • 2011-07-16
  • 1970-01-01
  • 2011-12-27
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多