【问题标题】:Are there any static analysis tools that will report how closely the SOLID principles are followed?是否有任何静态分析工具可以报告 SOLID 原则的遵循程度?
【发布时间】:2009-10-26 20:04:17
【问题描述】:

我知道盲目地遵循任何“最佳做法”仍然会导致一堆严格遵守最佳做法的臭屁。 SOLID 原则就是这样,原则。它们并不适用于所有情况,但它们仍然是很好的启发式方法,可用于发现代码中可能的改进。

它们的缺点是有时需要对您的源代码进行深入分析才能应用它们。我和大多数程序员一样,一直在寻找更有效的做事方式。所以,我很好奇是否有人听说过一种分析工具,它试图测试 SOLID 原则的应用(或缺乏)。

SRP 单一职责 原理

一个班级应该只有一个理由 改变。

OCP 开闭 原理

软件实体(类、模块、 功能等)应该是开放的 扩展,但关闭 修改。

LSP Liskov 替代原则

子类型必须可以替代 他们的基本类型。

ISP 接口 隔离原则

不应强迫客户依赖 根据他们不使用的方法。 接口属于客户端,不属于 层次结构。

DIP 依赖倒置原则

抽象不应该依赖于 细节。细节应该取决于 抽象。

-来自 Robert C. Martin 的敏捷原则、模式和实践

【问题讨论】:

  • 它们的缺点是有时需要对源代码进行深入分析才能应用它们。如果对代码的分析(无论多深)就足够了,例如工具是可能的,但是查看代码是不够的。
  • @Wolf 在那个特定句子的上下文中,我指的是基于理解、洞察力和直觉的人类分析。
  • 您是指从人工代码分析中检索到的模式,这些模式随后会以自动方式进行检查?
  • 没有。我只是想问是否有任何工具可以接近由熟练的软件开发人员手动分析代码所获得的结果。我认为最佳答案总结得很好。此类工具不存在,因为 SOLID 原则对于自动分析来说过于非正式。

标签: static-analysis solid-principles


【解决方案1】:

我不认为自动静态分析可以确定这些原则是否得到尊重。要编写这样的工具,您需要正式定义每个概念的含义,并有办法根据任何代码检查它。你如何将责任的概念正式化?我个人不知道。

也就是说,您可以使用一些工具来帮助您检测违规的可能性。 例如,您可以使用代码指标(例如每个类的方法数、每个类的成员数)来确定一个类是否太大,从而可能违反 SRP。

一个例外可能是 Liskov 替换原则。 如果您在所有方法(前置条件、后置条件、不变量)上定义了契约,那么您可以检查重新定义超类方法的方法不会加强前置条件、不会削弱后置条件和尊重超类方法的不变量。我认为工具ESC/Java 会执行这些检查。 阅读wikipedia page about LSP 需要执行更多检查。

【讨论】:

    【解决方案2】:

    我的回答涉及特定于 .NET 的产品,提前道歉,也许有人可以建议它的非 .NET 类似产品。

    我会尝试NDepend,看看它是否会导致我使用以下指标违反 SRP 和 ISP:

    • 每种类型的方法数
    • 方法数量异常多
    • 在程序集和类型级别的传入/传出耦合
    • 其他指标,full list of metrics here

    DIP 和 LSP 违规可能更难追踪,因为它们涉及程序员的意图。分析工具可以识别类型之间的关系,但它如何判断一个类真正从 Square 不恰当地派生自 Rectangle 的情况下扩展了另一个类?或者,在一个设计合理的程序中,A 应该依赖于 B 而不是相反?

    OCP 提出了不同的挑战,因为类应该打开/关闭的扩展/修改可能不一定已经发生。

    但是,如果我们相信遵循 SOLID 会导致产品更易于维护(从科学上证明这一说法不是这个问题的主题),那么 NDepend 的抽象性-不稳定性图表应该提供一个很好的聚合度量每个软件模块遵循原则的程度。如果是,该模块应该避开图表的左下角,称为“疼痛区”。在那个区域,模块是稳定的(不是很好——太多其他人依赖它,所以很难改变),但不够抽象。

    【讨论】:

    • 理论上,如果程序员对每个对象进行了一套完美的测试,是否有可能自动检测出 Liskov 违规?以 square 为矩形的情况,其中 square 的 setWidth() 和 setHeight() 方法的副作用是不仅设置了声明的变量,还设置了另一个。例如。 setWidth 不仅更新宽度,还更新高度。 setHeight 更新宽度和高度(下一条评论继续)
    • 这是一种行为 Liskov 违规行为,如果不进行测试就无法检测到。但是,如果 Rectangle 类有一个测试强制 setWidth() 更新宽度并且不改变高度,则通过 Rectangle 的单元测试运行 Square 将产生失败。在像 Java 这样的语言中,您可以编写一个程序来获取父类的所有子实例并在它们上运行父类的测试。这将捕获副作用违规和可能引发的其他错误。
    • 在上面的“完美测试”中对“完美”的澄清:我并不是说它需要所有可能的输入和输出,而是“足够”(这是一个非常模糊的词)。也许这意味着 setWidth() 的 1 个示例为 100,表示所有正整数。
    猜你喜欢
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    相关资源
    最近更新 更多