SOLID是面向对象的软件开发中的5条准则,也是开发人员可以提升自己代码质量的准则。那么如何衡量自己的代码是否符合SOLID准则呢?NDepend这款工具也许可以帮得上忙。本文将介绍一些NDepend的规则,这些规则可以帮助你来衡量你的代码的SOLID程度,并且提供一些可以让你的代码变得更好的建议。

原文连接:Use NDepend to Measure How SOLID Your Code Is - NDepend
作者 Carlos Schults。授权翻译,转载请保留原文链接。

https://www.ndepend.com/

NDepend和SRP

我们将首先处理SOLID中的“ S”:单一责任原则。这可能是SOLID原则中最容易被误解的东西,公平地说,这似乎是有原因的。关于什么构成责任存在一定程度的主观性。那么NDepend如何帮助解决这个难题呢?

避免类型过大

顾名思义,这条规则建议你保持较小的类型。保证你的类较小并不一定会使它们只承担一种责任,但是肯定会引导事情朝着这个方向发展。

听上去不错,但是“太大”有多大?根据规则的文档,超过200条逻辑代码行的类就属于过大了。

避免太多方法的类型

你可能会认为,鉴于前一个规则,这条规则有些多余,但事实并非如此。 除了大量方法外,类型还可能由于其他原因而过大,例如它可能有很多其他成员,或者可能只有一个巨大的方法。

但是,按照以前的规则,我们不得不问:“太多”是多少? 该规则的文档指出,如果每种类型有20个或更多的方法则被视为拥有太多方法,并补充说,诸如构造函数,属性和事件访问器之类的方法不被视为计数的一部分。

避免太多字段的类型

作为“避免太多...”系列的规则,这条规则涉及到了字段。该规则的文档说,它针对具有15个以上字段的类型,并且不考虑常量和只读静态字段以及枚举类型。

避免过大和过于复杂的方法

在这里,我们继续遵循鼓励简化设计的规则,但是现在我们关注的是方法级别。那么,方法的情况如何呢?我们是否只是要重复使用刚刚看到的相同规则,但是将“类型”替换为“方法”?

不,不是那么容易。在处理方法时,事情会变得有些复杂。首先让我们看看“避免方法过大和过于复杂”规则的文档说了些什么:

//<b> This rule matches methods where *ILNestingDepth* > 2
</b>//<b> and (*NbLinesOfCode* > 35
</b>//<b> or *CyclomaticComplexity* > 20
</b>//<b> or *ILCyclomaticComplexity* > 60)
</b>//<b> Such method is typically hard to understand and maintain.</b>

简而言之,该规则担心嵌套深度大于2且也符合其他几种条件之一的方法,例如代码行和循环复杂度。

避免使用参数过多的方法

该规则的名字已经表明了它的内容。我们真正需要做的是量化。多少是太多?

同样,我们必须求助于文档,这次文档中描述了参数过多指的是超过8个参数。调用这样的方法会十分痛苦。同样需要注意的是,一个有很多参数的方法是否也有可能本身的逻辑已经十分冗杂,处理多个事务了呢?有这样方法的类,应该使用单一职责原则来进行重构。

避免使用过多局部变量的方法

终于,最后一条用来帮助你使用单一职责原则检查自己代码的规则。就像之前介绍过的大多数规则一样,这条规则的名字也说明了它的内容。并且,这条规则只需要定义它所谓的“过多”是多少。而这个问题的答案,根据文档,是15个。

通过这一节的介绍,我们大致介绍了NDepend中可以帮助你使用SOLID原则中的单一职责原则的规则。

OCP 开闭原则

很多人认为开闭原则是所有原则中最难理解和应用的。所谓的开闭原则,指的是你的类型应该对拓展开放,但是对修改关闭。换句话说,对子类的增加一定不能导致父类的任何修改。NDEpend中的“基类不应该使用派生”规则通过指示基类永远不要提及其子类来帮助我们防止这种情况。

LSP 里氏替换原则

Robert Martin在一篇文章中对里氏替换原则下过如下定义:

派生类必须可以替代其基类。

当面对这样一条定义时,一些人会认为里氏替换原则多此一举,显得多余。那么这条原则的意义是什么呢?

好吧,这条原则的关键是人们一直在违反它!一种非常常见(也许是最常见)的情况是,让一个类实现一个或多个接口,然后抛出某种方式不适用的方法。

而NDepend恰好有一条规则可以警告你这种情况,这条规则被相当恰当地称为“实现抛出NotImplementedException的方法。”

你会发现,在使用TDD时,此异常最有用。这是一个非常常见的情况,如下所示:

  • 为一段代码编写测试时,你将调用一些不存在的方法。
  • 此时编译器会抱怨,而这是一件好事。
  • 然后你接受了Visual Studio的建议并生成了一个方法存根,因为你现在也不希望立即实现该方法。

如果你以后忘记实现该方法,则测试将失败,而这会提醒你。

这是NotImplementedException的可接受用法。如果你使用此(或其他)异常来避免实现某个接口,那么你将破坏LSP准则。

ISP 接口隔离原则

接口隔离原则指的是:

不应强迫客户端依赖于不使用的接口。

为了遵循此原理,你应该使接口尽可能的小和精细。换句话说,你应该避免接口太大,这是我们现在要讨论的NDepend规则的确切名称。

“太大”有多大?根据NDepend的文档:10。也就是说,该规则将提示具有10种以上方法的接口。

关于此规则的一件好事是,它也可以帮助你遵守之前提到过的里氏替换原则。如果使接口尽可能小,则可以降低客户端必须提供有意义的实现的可能性。一石二鸟!

DIP 依赖反转原则

所谓的依赖反转原则指的是:抽象接口不应该依赖于具体实现。而具体实现则应该依赖于抽象接口。

假设你有一个应用程序紧密耦合使用Microsoft SQL Server作为持久性解决方案。如果之后你需要更改使用另一个RDBMS,将​​会发生什么?这注定是一个痛苦的过渡过程。

反过来,如果你的应用程序的业务逻辑甚至没有意识到数据库的存在(通过采用适当的体系结构是可能的),则无需进行任何更改即可进行过渡。

为了帮助您解决此问题,NDepend制定了一个规则,即“高凝聚,低耦合”。 “高凝聚,低耦合”类似于“关注点分离”,简而言之,你希望你的软件具有很高的内聚性(“做一件事情并做好”),同时彼此之间的耦合性也很低。

这条NDepend规则通过鼓励你将包含抽象的命名空间与包含具体内容的命名空间(即所述抽象的实现)分开来帮助你实现此目的。

准备好编写更多SOLID代码了吗?

我们上面介绍的规则只是NDepend提供的规则中的一部分。它们足以使您的应用程序符合SOLID原则吗?当然不会。没有任何工具或技术可以保证一定改善你的代码。

但是,虽然规则本身并不能自动使你的代码完美无缺,但它们鼓励你编写较小,集中且不太复杂的类型,从而为你提供极大的帮助。

除此之外,通过不断阅读和研究SOLID原理,适当的架构以及通用的最佳实践和模式,你便可以正确地编写出色的应用程序。


阅读更多:

https://docs.microsoft.com/en-au/learn/?WT.mc_id=DT-MVP-5001664

使用NDepend衡量代码的SOLID程度的更多相关文章

  1. 代码整洁 vs 代码肮脏

    写出整洁的代码,是每个程序员的追求.<clean code>指出,要想写出好的代码,首先得知道什么是肮脏代码.什么是整洁代码:然后通过大量的刻意练习,才能真正写出整洁的代码. WTF/mi ...

  2. [代码质量] 代码质量管控 -- 复杂度检测 (JavaScript)

    转载自: https://juejin.im/post/59bb8b546fb9a00a4247532e 背景 代码的复杂度是评估一个项目的重要标准之一.较低的复杂度既能减少项目的维护成本,又能避免一 ...

  3. 高效完成R代码

    为什么R有时候运行慢? 参考https://www.cnblogs.com/qiaoyihang/p/7779144.html 一.为什么R程序有时候会很慢? 1.计算性能的三个限制条件 cpu ra ...

  4. 华为Java编程军规,每季度代码验收标准

    引言: 这个标准是衡量代码本身的缺陷,也是衡量一个研发人员本身的价值. 军规一:[避免在程序中使用魔鬼数字,必须用有意义的常量来标识.] 军规二:[明确方法的功能,一个方法仅完成一个功能.] 军规三: ...

  5. 深入理解javascript---如何编写高质量的代码?

    如何书写可维护的代码? 最小全局变量 JavaScript通过函数管理作用域.在函数内部声明的变量只在这个函数内部,函数外面不可用.另一方面,全局变量就是在任何函数外面声明的或是未声明直接简单使用的( ...

  6. 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点

    深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点 2011-12-28 23:00 by 汤姆大叔, 139489 阅读, 119 评论, 收藏, 编辑 才华横溢的 ...

  7. 高质量JavaScript代码书写基本要点

    翻译-高质量JavaScript代码书写基本要点 by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/ ...

  8. 【转】华为Java编程军规,每季度代码验收标准

    引言: 这个标准是衡量代码本身的缺陷,也是衡量一个研发人员本身的价值. 军规一:[避免在程序中使用魔鬼数字,必须用有意义的常量来标识.] 军规二:[明确方法的功能,一个方法仅完成一个功能.] 军规三: ...

  9. 阅读Google的C++代码规范有感

    李开复曾在微博上说过,Google的C++代码规范是全球最好的一份C++代码规范,没有之一.最近花了点时间看了下这份代码规范,收获确实很大,在编程过程中一些乱七八糟的坏习惯也该改一改了.最新的英文版见 ...

随机推荐

  1. CTFHub-easy_search

    easy_search 玩了好些天,今天做道题找找状态,明天开始肝了 打开是一个登录框 用amdin/admin尝试了一下,提示登陆失败 这里肯定不会是暴力破解,我猜是sql注入,试了万能密码or 1 ...

  2. ColyseusJS 轻量级多人游戏服务器开发框架 - 中文手册(上)

    快速上手多人游戏服务器开发.后续会基于 Google Agones,更新相关 K8S 运维.大规模快速扩展专用游戏服务器的文章.拥抱️原生 Cloud-Native! 快速开始 在开始之前,让我们确保 ...

  3. Cauchy-Binet 公式的应用

    Binet-Cauchy 公式 我们知道,方阵的行列式不是方阵的线性函数,即对 \(\forall \lambda\in F,A,B\in F^{n\times n}\),有 \(det(A+B)\n ...

  4. Tensorflow Probability Distributions 简介

    摘要:Tensorflow Distributions提供了两类抽象:distributions和bijectors.distributions提供了一系列具备快速.数值稳定的采样.对数概率计算以及其 ...

  5. Jenkins+Git的搭建和自动部署

    前言 Jenkins在工作中都使用过,之前都是运维去搭建部署,弄好了之后给我一个网址去构建项目就可以了,所以也都是一直没了解过安装过程. 今天在自己的服务器上搭建了一遍,中间有遇到很多坑,特在此归纳总 ...

  6. Canal详细入门实战(使用总结)

    Canal介绍 Canal简介 canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费 早期阿里巴巴因为杭州和美国双机房部署,存在 ...

  7. BugkuCTF——wp(旧版)

    title: BugkuCTF--wp(旧版) date: 2020-4-25 tags: CTF,比赛 categories: CTF 比赛 Web篇 0x001-web2 解题思路: 1.直接按F ...

  8. 放弃模拟器,安卓手机WiFi投屏到Ubuntu

    曾经使用过一些安卓的模拟器,但是特别占用资源,而且很多平时使用的非游戏生活类App都有兼容性问题,自然最终无奈而放弃了. 现在将学习环境迁移到了Ubuntu平台,发现各个方面还是不错的,平时使用的各种 ...

  9. 并发王者课 - 青铜4:synchronized用法初体验

    在前面的文章<双刃剑-理解多线程带来的安全问题>中,我们提到了多线程情况下存在的线程安全问题.本文将以这个问题为背景,介绍如何通过使用synchronized关键字解这一问题.当然,在青铜 ...

  10. 关于flume中涉及到时间戳的错误解决,Expected timestamp in the Flume even

    在搭建flume集群收集日志写入hdfs时发生了下面的错误: java.lang.NullPointerException: Expected timestamp in the Flume event ...