读《代码不朽:编写可维护软件的10大要则》C# 版

这本书特别针对没有接受过计算机科学或软件工程专业学习的软件开发人员,这类人员除了熟悉所用语言语法和语义之外,很少接受其他专业培训,对软件工程中的一些概念理解欠缺。软件设计方面考虑较少。如果要成为一个专业的程序员,就需要学习已形成工业化的软件构建方式。

可维护性解释

这本书解释了可维护软件中的“维护”的意思:可维护性是软件质量的一个标准,代表一个系统可被修改的难易程度。所以它是面向程序员的,假设两个软件完成相同的功能,但一个软件的源码,让其他人或者一段时间之后的自己,很难理解,更不用提修改了,就说明这个软件的可维护性比另一个差。软件维护有4种方式:发现并纠正bug(纠正性维护);适应操作系统或运行环境的改变(适应性维护);根据需求增加新的功能(完善性维护);改进代码质量预防bug产生(预防性维护)。

三个基本理论

本书提供了10条可以实现高可维护性的指导原则,这些原则背后有三个理论:

1、坚持简单的原则最有助于提高可维护性

2、可维护性不是项目开发完后才去考虑的,而应该是在项目开发的一开始就加以考虑。每个人的贡献都应当计算在内

3、不同原则的违例会带来不同的影响,有些严重程度甚至于他。一个软件系统越遵守原则,可维护性越高。

 

对10大要则的理解

按照从小到大,从细微到宏观的层次,这本书提取了编写可维护软件中10大编程原则,小到程序开发者应当时刻注意的代码规范,大到系统架构师应该考虑的系统重构、组件和及接口的设计准则。

编写短小的代码单元

代码单元即面向对象编程里的方法或函数。这个原则要求每个函数的长度不应超过15行。

动机

小的函数的好处?作者提出,小的函数容易重用,因为一个巨型的方法会包含很多细节,导致很难有一模一样的场景使用这个方法。作者提出,小的方法更易理解和进行单元测试。若超过15行,则意味着方法可以被拆分了。

如何使用本原则

拆分重构的方式有提取方法将方法替换为方法对象
提取方法很容易理解,即从一个函数中提取一段代码,写成一个新的方法。但如果提取方法时发现,这个方法访问了很多局部变量,如果都作为新方法的参数的话,势必会导致参数列表过长。还有返回值的问题,如果这个方法会产生不止一个结果变量。一个重构技巧是将这个方法替换成一个方法对象,将不同的局部变量和结果变量作为类的成员,然后调用类方法。

编写简单的代码单元

这里的“简单”体现代码单元的分支点,所以这个原则可量化为:限制每个代码单元分支点的数量不超过4个。C# 中常见的分支点代码就是if和switch语句。

动机

让代码单元保持简单基于两个原因,一是简单的代码更容易修改,二是简单的代码更容易测试,分支点过多,意味着要有更多的测试用例。

如何使用本原则

复杂的代码单元可能是因为其中包含很多互不相关的代码块,这种情况可以采用“提取方法”
若是其它复杂的情况,比如碰到链式的条件语句,如下判断国旗的语句:

...
List<Color> result;
switch(nationality) {case CHINA:result= new List<Color>{Color.RED,Color.YELLOW};break;case FRENCH:result= new List<Color>{Color.BLUE,Color.WHITE,Color.RED};break;
...
}

第一种方法是引入Map数据结构,将国家映射到指定的FLAG对象上;
第二种方法是使用“使用多态来代替条件判断”,实现同一个接口,代表广泛的国旗类型,然后为每个国家的国旗实现一个类。
再比如碰到嵌套的条件语句,为了使代码简单,可以使用“使用卫语句来代替嵌套的条件语句”的重构技巧,即标识出各种独立的情况,并插入return语句来代替嵌套式的条件语句。
例如

if(...) {if(...) {//TODO CASE1} else {//TODO CASE2}
} else {//TODO CASE3
}

可以改写成

if(...) {//TODO CASE1return;
}
if(...) {//TODO CASE2return;
}
if(...) {//TODO CASE3return;
}

可以看到分支点并未减少,然后可以再用“提取方法”减少复杂度。

不写重复代码

对重复代码的定义是,一段至少6行都相同的代码。

动机

如果复制代码,相同的代码出现在不同的地方,不利于源码的定位;如果需要修改的地方正是重复的代码,意味着要做很多重复性的工作,而且容易出错。

如何使用本原则

首先想到的是提取方法;但若是一个方法是另一个类的私有方法怎么办?这时应当将提取的方法放到一个工具类中。
如果重复代码(6行以上完全相同)已不存在,但代码相似,具有相同的逻辑,这时应该考虑提取父类。

保持代码单元的接口简单

限制每个代码单元的参数不能超过4个。

动机

较少的接口参数能够保持简单的上下文,易于重用、理解和修改。

如何使用本原则

将多个参数包装成对象,比如输入坐标参数,x与y,可以包装成一个点对象。
使用“使用方法对象替换方法”的重构技巧,此处和前面有重合。

分离模块之间的关注点

模块对应类的概念。
实际上就是要求类要保持小的体积,不要过大过复杂。

动机

小的体积的类带来了类之间的松耦合,松耦合意味着类能更灵活的适应将来的变化。如果一个类做了很多事情,其耦合度会越来越紧,积攒大量代码,导致代码很难阅读和修改。

如何使用本原则

第一种方法:根据功能将大类拆分为很小的类。一个类一开始可能很小,只是实现单一功能,但都不可避免负责越来越多的职责,当意识到这个类承担了不止一个职责时,就应该将这个类进行拆分。
第二种方法:提取一个接口,实现松耦合。比如一开始为一台相机设计了简单的相机类,只具备拍照,闪光灯打开和关闭3个方法。后来这个类的使用扩展到新的移动设备上,增加了定时功能。这时类变大,而且只有一个类,还需要检查旧设备上的代码有没有受影响。为了降低耦合度,可以使用一个接口,它只定义所有相机都需要实现的功能。
第三种方法:使用第三方库和框架来替代自定义的实现。

架构组件松耦合

组件是比模块(类)更高一层的单元,设计到系统的架构。此原则要求尽可能减少当前模块暴露给(例如,被调用)其它组件中模块的相关代码。

动机

独立的组件可以单独进行维护,方便划分职责,让测试变得容易。

如何使用本原则

使用抽象工厂设计模式,简单的讲就是类的实例不能直接被创建(new一个),而是通过工厂类的方法返回。这种通用的工厂接口背后,隐藏了具体产品的创建过程。在这个环境下,产品通常都不止有一种类型。如果要使用其中的逻辑,需要通过创建通用的工厂对象调用类方法成员。
注:抽象工厂不同于工厂模式,简单理解就是抽象工厂的类型不止一个,所以产品至少有两个。

保持架构组件之间的平衡

保持源代码中的组件数量接近于9。

动机

好的组件平衡让查找和分析代码更容易,提供清晰的功能边界,分离维护职责。

如何使用本原则

软件系统的开发有两种组织模式:
基于功能领域划分的系统:好处是可以从高层功能的角度来分析代码,坏处是技术人员需要了解多个技术栈
基于技术划分的系统:根据技术专长来划分,可能会有前端,后端,接口、日志等组件。
软件架构师需要选择如何组合功能的合适原则。明确系统的领域并坚持下去。

保持小规模代码库

动机

大型系统更加难以维护,易出现更密集的缺陷,以大型代码库为目标的项目更容易失败。

如何使用本原则

功能层面:控制需求蔓延,功能标准化
技术层面:不要复制黏贴代码,重构代码,使用第三方库和框架(这同样是前面提到的准则)

自动化开发部署和测试

测试包含单元测试、集成测试、端对端测试、回归测试、验收测试。不同类型的测试需要不同的自动化框架。

动机

自动化测试可重复,有效率;自动化测试里的断言(assert)可以充当注释;通过编写测试可以反过来推促编写可测试的代码,提高代码质量。

如何使用本原则

使编写单元测试成为每个开发人员的职责,比如使用C#中的单元测试框架Xunit.net。
使用像moq或者mocking这样的技术。stub即测试桩。需要测试桩是因为有些影响测试结果的测试条件是易变、无法统一的。比如拍照,两次拍摄的环境不可能完全相同,结果无法验证,所以需要一个假对象,即测试桩。mocking(模拟)是因为测试中某些函数是沉默的,不包含任何结果,可以在函数中添加计数来验证函数执行过。mock技术有自动化的框架。
建议生产代码和测试代码一比一,提高覆盖率。

编写简洁的代码

给程序开发人员总结了7条“童子军军规”:
1、编写单元级别的良好代码
2、不要编写不好的注释
3、不要注释代码
4、不要保留废弃代码
注:包括3,同时还有其它的形式,比如不可能执行到的代码、无用的私有方法、注释中的代码
5、不要使用过长的标识符名称
6、不要使用魔术常量
注:指表达式中突兀出现的数字,应该先定义。
7、不要使用未正确处理的异常
注:包括以下情况,捕获异常却不处理(catch为空),直接捕获通用异常(比如Exception异常,这些异常不会提供触发失败的状态或事件信息,所以没意义),将异常信息展示给终端用户(避免用户困惑或暴露信息,应该先转换为通用信息)

原文地址:https://www.qcloud.com/community/article/545562


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/325234.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql多表查询的分类

内连接 等值连接 非等值连接 自连接 外连接 inner join 等值连接 非等值连接 自连接 外连接

再有人问你volatile是什么,把这篇文章也发给他(深入分析)

转载自 再有人问你volatile是什么&#xff0c;把这篇文章也发给他 在上一篇文章中&#xff0c;我们围绕volatile关键字做了很多阐述&#xff0c;主要介绍了volatile的用法、原理以及特性。在上一篇文章中&#xff0c;我提到过&#xff1a;volatile只能保证可见性和有序性&…

Cockroach DB 1.0发布

分布式SQL数据库Cockroach DB遵循软件产品以动物命名的模式。近日&#xff0c;该数据库的第一个生产就绪版本1.0发布。 许多人将Cockroach DB视为Google Spanner的开源版本。后者是一个强一致性、横向可扩展的RDBMS&#xff0c;它起初是一个服务于谷歌服务的内部项目&#xff…

分享10道常考Java面试题及答案

转载自 分享10道常考Java面试题及答案 Hi&#xff0c;大家好&#xff0c;今天给大家分享10道常考的Java面试题及答案&#xff0c;涉及到Java中的10个方面。每个领域一道题。希望你能有收获。 <面向对象>什么是面向对象&#xff1f;什么是面向过程&#xff1f;面型对象…

对数据进行插入操作并且获取主键的值

eg. eg:工作中写定时模块&#xff0c;先插入时间段&#xff0c;然后直接获取id

编写高性能 .NET 代码 第二章:垃圾回收 基本操作

基本操作 垃圾回收的算法细节还在不断完善中&#xff0c;性能还会有进一步的提升。下文介绍的内容在不同的.NET版本里会略有不同&#xff0c;但大方向是不会有变动的。 在.net进程里会管理2个类型的内存堆&#xff1a;托管和非托管。本地代码申请的&#xff0c;以及由CLR申请…

如何设计一个高可用的运营系统

转载自 如何设计一个高可用的运营系统 这是一篇来自粉丝的投稿&#xff0c;作者【林湾村龙猫】近一年在做关于运营活动方面的设计。本文是他的关于运营活动的总结&#xff0c;Hollis做了一点点修改。 概述 一个产品业务的发展总是离不开运营二字。随着业务快速的发展以及新…

.Net中的AOP系列之《AOP实现类型》

本系列的实验环境&#xff1a;VS 2017。 读完本章后&#xff0c;可能仍然不能实现自己的AOP工具&#xff0c;但应该对两种主要类型&#xff08;PostSharp和Castle DynamicProxy&#xff09;的AOP工具的运行原理有了基本的理解。PostSharp是一个在编译时编织的后期编译器&#x…

JavaFX官方教程(一)之JavaFX概述

翻译自 JavaFX概述 本章概述了可以使用JavaFX API构建的应用程序类型&#xff0c;下载JavaFX库的位置以及有关正在交付的关键JavaFX功能的高级信息。 JavaFX是一组图形和媒体包&#xff0c;使开发人员能够设计&#xff0c;创建&#xff0c;测试&#xff0c;调试和部署在不同平…

mybatisPlus的分页查询

结论&#xff1a;不是直接limit进行分页的 而是通过rowBounds进行的

详解CockroachDB事务处理系统

本文提到的一些术语&#xff0c;比如Serializability和Linearizability&#xff0c;解释看Linearizability, Serializability and Strict Serializability。 本文中观点大部分都是参考了CockroachDB多篇官方blog,设计文档&#xff0c;代码以及相关资料&#xff0c;相对来说比较…

JavaFX官方教程(二)之JavaFX体系结构

翻译自 JavaFX体系结构 本章提供了JavaFX体系结构和生态系统的高级描述。 图2-1说明了JavaFX平台的架构组件。图中的部分描述了每个组件以及这些部件如何互连。JavaFX公共API下面是运行JavaFX代码的引擎。它由包含JavaFX高性能图形引擎的子组件组成&#xff0c;称为Prism; …

Work Time Manager【开源项目】- 创建自己日志组件 2.0重构

这次我们真是开始来聊聊开源项目里&#xff0c;小而有用的模块或者组件的开发思想。 同时&#xff0c;软件已经更新到1.60的版本了&#xff0c;支持新用户注册&#xff0c;可以不再使用统一的test账户了。 您可以通过以下路径进行下载&#xff1a; 1、在GitHub上fellow一下项目…

JavaFX官方教程(三)之JavaFX示例应用程序入门

翻译自 JavaFX示例应用程序入门 此示例应用程序集旨在帮助您开始使用常见的JavaFX任务&#xff0c;包括使用布局&#xff0c;控件&#xff0c;样式表&#xff0c;FXML和视觉效果。 Hello World&#xff0c;JavaFX Style JavaFX中的表单设计 用CSS设计的花式设计 使用F…

SSH(Spring+Struts2+Hibernate)框架搭建步骤(含配置文件以及运行结果)

1.创建web项目2.导入ssh 所需要的多有jar包&#xff0c;到web-inf下面的lib里面3.将导入过来的jar包都build--path一下4.切换到myeclipse database视图中&#xff0c;添加链接数据库的链接5.新建一个数据库连接&#xff08;如果忘记了数据库链接时你可以去下面的网址中查看&…

Unity 游戏用XLua的HotFix实现热更原理揭秘

本文通过对XLua的HoxFix使用原理的研究揭示出来这样的一套方法。这个方法的第一步&#xff1a;通过对C#的类与函数设置Hotfix标签。来标识需要支持热更的类和函数。第二步&#xff1a;生成函数连接器来连接LUA脚本与C#函数。第三步&#xff1a;在C#脚本编译结束后&#xff0c;使…

JavaFX官方教程(四)之Hello World,JavaFX样式

翻译自 Hello World&#xff0c;JavaFX Style 教你创建和构建JavaFX应用程序的最佳方法是使用“Hello World”应用程序。本教程的另一个好处是&#xff0c;它使您能够测试您的JavaFX技术是否已正确安装。 本教程中使用的工具是NetBeans IDE 7.4。在开始之前&#xff0c;请确…