使用NDepend衡量代码的SOLID程度
SOLID是面向对象的软件开发中的5条准则,也是开发人员可以提升自己代码质量的准则。那么如何衡量自己的代码是否符合SOLID准则呢?NDepend这款工具也许可以帮得上忙。本文将介绍一些NDepend的规则,这些规则可以帮助你来衡量你的代码的SOLID程度,并且提供一些可以让你的代码变得更好的建议。
原文连接:Use NDepend to Measure How SOLID Your Code Is - NDepend
作者 Carlos Schults。授权翻译,转载请保留原文链接。
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程度的更多相关文章
- 代码整洁 vs 代码肮脏
写出整洁的代码,是每个程序员的追求.<clean code>指出,要想写出好的代码,首先得知道什么是肮脏代码.什么是整洁代码:然后通过大量的刻意练习,才能真正写出整洁的代码. WTF/mi ...
- [代码质量] 代码质量管控 -- 复杂度检测 (JavaScript)
转载自: https://juejin.im/post/59bb8b546fb9a00a4247532e 背景 代码的复杂度是评估一个项目的重要标准之一.较低的复杂度既能减少项目的维护成本,又能避免一 ...
- 高效完成R代码
为什么R有时候运行慢? 参考https://www.cnblogs.com/qiaoyihang/p/7779144.html 一.为什么R程序有时候会很慢? 1.计算性能的三个限制条件 cpu ra ...
- 华为Java编程军规,每季度代码验收标准
引言: 这个标准是衡量代码本身的缺陷,也是衡量一个研发人员本身的价值. 军规一:[避免在程序中使用魔鬼数字,必须用有意义的常量来标识.] 军规二:[明确方法的功能,一个方法仅完成一个功能.] 军规三: ...
- 深入理解javascript---如何编写高质量的代码?
如何书写可维护的代码? 最小全局变量 JavaScript通过函数管理作用域.在函数内部声明的变量只在这个函数内部,函数外面不可用.另一方面,全局变量就是在任何函数外面声明的或是未声明直接简单使用的( ...
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点 2011-12-28 23:00 by 汤姆大叔, 139489 阅读, 119 评论, 收藏, 编辑 才华横溢的 ...
- 高质量JavaScript代码书写基本要点
翻译-高质量JavaScript代码书写基本要点 by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/ ...
- 【转】华为Java编程军规,每季度代码验收标准
引言: 这个标准是衡量代码本身的缺陷,也是衡量一个研发人员本身的价值. 军规一:[避免在程序中使用魔鬼数字,必须用有意义的常量来标识.] 军规二:[明确方法的功能,一个方法仅完成一个功能.] 军规三: ...
- 阅读Google的C++代码规范有感
李开复曾在微博上说过,Google的C++代码规范是全球最好的一份C++代码规范,没有之一.最近花了点时间看了下这份代码规范,收获确实很大,在编程过程中一些乱七八糟的坏习惯也该改一改了.最新的英文版见 ...
随机推荐
- 【java--反射】注解(反射解析注解+注解应用)
创建实体类 package cn.com.codingce.iocannotation; /** * @Author: Jiangjun * @Date: 2019/10/7 9:54 */ publ ...
- $ git push -u origin master 报错
输入$ git push -u origin master报permission denied(publickey) 如下: 原因是没有与gitee上的账号成功建立密钥对,所以需要配对密钥 解决方法( ...
- Java中实现SAX解析xml文件到MySQL数据库
大致步骤: 1.Java bean 2.DBHelper.java 3.重写DefaultHandler中的方法:MyHander.java 4.循环写数据库:SAXParserDemo.java ① ...
- 1Spring注入小结
Spring注入小结 (在Application.xml中) Spring学习笔记 周芋杉2021/5/14 1.基本注入类型注入 注入前的准备 <bean id="#配置文件的唯一标 ...
- 把el-element的日期格式改为CRON
在日常的开发当中,经常会遇到格式的不匹配造成的困扰. 在日期管理上,el-element也是贴心的准备了相关的日期选择器,但是在取值的时候发现,el-element所给出的值格式可能并不是我们常用的. ...
- [Python] tkinter 之 Listbox & Combobox
示例: 1 #用户界面 2 import os 3 os.chdir('F:\\spyder_workspace\\ColCal') 4 import Main 5 from tkinter impo ...
- Docker Swarm(六)Label 节点标签与服务约束
前言 多节点 Swarm 集群下,可能节点的配置不同(比如 CPU.内存等),部署着不同类型的服务(比如 Web服务.Job服务等),当这些服务以 Service 或者 Stack 的形式部署到集群, ...
- Redis 主从架构搭建
引言 准备搭建的是主从架构( Master/Slave )中的一主两从模式:其中 Master 为 Redis 的主服务器,主要负责写操作,两个 Slave 为 Redis 的从服务器,主要负责读操作 ...
- Apache Flink 1.12.0 正式发布,DataSet API 将被弃用,真正的流批一体
Apache Flink 1.12.0 正式发布 Apache Flink 社区很荣幸地宣布 Flink 1.12.0 版本正式发布!近 300 位贡献者参与了 Flink 1.12.0 的开发,提交 ...
- SpringBoot + WebSocket 实现答题对战匹配机制
概要设计 类似竞技问答游戏:用户随机匹配一名对手,双方同时开始答题,直到双方都完成答题,对局结束.基本的逻辑就是这样,如果有其他需求,可以在其基础上进行扩展 明确了这一点,下面介绍开发思路.为每个用户 ...