《代码不朽》_编写客维护软件的10大原则
电子工业出版社
主要内容及体会记录如下:
一、编写短小的代码单元
1.原则
- 代码单元的长度应该限制在15行代码以内
- 因此首先不要编写超过15行代码的单元,或者将单元分解成多个更短的单元,直到每个单元都不超过15行代码
- 该原则能提高可维护性的原因在于,短小的代码单元易于理解、测试及重用
2.
代码单元是独立维护和执行的最小代码集合。在Java中,代码单元指的是方法或者构造函数。代码单元总是作为一个整体执行。
代码单元是可以被重用及测试的最小单元。
3.目的
3.1 短小的代码单元易于测试
单一原则,一个代码单元只做一件事情。相比较一个大段的代码单元,更容易测试。
3.2 短小的代码单元易于分析
条例清晰明了。不必添加多余的注释在各行代码上进行说明或备注。
3.3 短小的代码单元易于重用
代码短小,逻辑就足够简单,重复调用的可能性就很高。
4.使用
4.1 添加新的功能时
可以单独建立一个方法单元,将实现写在单元内,而将方法调用的位置放到指定的位置;
而不是直接在调用的方法内写功能。
好处:
如果有一天被告知此功能暂时不需要上线,避免注释掉大段的代码;只需要把调用该方法的位置注释掉即可。
单一原则,不互相干涉。如果几个方法都对同一个对象进行修改,就会出现各种问题;避免同名变量
4.2 代码书写完毕后的重构
4.2.1 提取方法
将几行实现一个功能的代码,抽取出来,作为一个独立的代码单元;
4.2.2 在方法内部使用对象
当方法的参数数量多于4个时,将参数抽象成一个对象
既减少传入参数的数量(避免类型、位置对应不上的问题)也减少方法内部的处理
二、编写简单的代码单元
1.原则
- 限制每个代码单元分支点的数量不超过4个
- 将复杂的代码单元拆分成多个简单的代码单元,避免多个复杂的单元在一起
- 分支点越少,代码单元越容易被修改和测试
2.代码测试
功能覆盖率,代码编写完毕后要进行初步的测试,测试的原则就是要覆盖每个分支
减少分支数量,就是在一定程度上减少测试成本及时间
3.使用
3.1 分支包括
- if else
- switch case default
- a > b ? a : b
- && ||
- for while
- try catch finally
3.2 减少else
使用return ,
比如:判断某集合不空,就进行某种处理。
if(CollectionUtils.isEmpty(list))
return ;
空了就不处理,也就不需要else
能够减少好多代码且条例清晰
3.3 抽象对象
比如:多个分支,多个参数处理、switch 的 各个case 的处理逻辑基本相同且参数很多
将参数抽象成对象,然后对此对象进行处理
三、不写重复代码
1.原则
- 不要复制代码
- 编写可重用的、通用的代码、并且或者调用已有的代码
- 如果复制代码,就需要在多个地方修改Bug
2.
复制代码似乎能够快速完成目标,既然代码都有了,何必要再写一遍?复制会导致代码重复出现,而冲农夫代码就是问题的根本所在。
3.目的
3.1 重复代码更加难以分析
3.2 代码重复更加难以修改
4.使用
提取方法,在代码开发过程中或开发完毕后,尝试将各个功能拆分,找出共同点
四、保持代码单元的接口简单
1.原则
- 限制每个代码单元的参数不能超过4个
- 将多个参数提取成对象
- 较少的参数可以让代码单元更容易理解和重用
2.目的
2.1 短接口更易于理解和重用
2.2 短接口的方法更易于修改
五、分离模块之间的关注点
1.原则
- 避免形成大型模块,以便能达到模块之间的松耦合
- 将不同职责分给不同的模块,并且隐藏接口内部的实现细节
- 该原则能提高可维护性的原因在于,相比起紧耦合的代码库来说,对松耦合代码库的修改更容易监督和执行
2.针对于如何提高系统中单个代码单元的可维护性
3.目的
3.1 小型、松耦合的模块允许开发人员独立进行工作
3.2 小型、松耦合的模块降低了浏览代码库的难度
3.3 小型、松耦合的模块避免了让新人感到手足无措
4.使用
4.1 根据不同关注点拆分类
举例:
一个用户接口
第一次开发:用户信息的增加、删除、修改、查询
第二次开发:用户信息通知接口
第三次开发:用户锁定接口
完全放在一个接口文件中时,代码量过大,且不易维护
建议:按照不同的关注点,拆分成多个接口
4.2 隐藏接口背后的特定实现
举例:
普通相机类:基本功能
高级相机类:如果为了兼容高级相机提供的特定功能,而扩充普通相机方法中的功能,就会显得代码过多
建议:抽象出接口,普通相机与高级相机分别实现接口,高级相机中添加特定的方法
调用接口时,利用多态的原理,保证调用的对象不同
六、架构组件松耦合
1.原则
- 顶层组件之间应该做到松耦合
- 尽可能减少当前模块中需要暴露给(例如,被调用)其他组件中模块的相关代码
- 独立的组件可以单独进行维护
2.举例
层与层之间设计中给的单向依赖
用户接口 --》 服务层 --》 业务逻辑层 --》 数据抽象层 --》 数据库层
如果相互之间调用混乱了,对于后续维护就不方便
如 用户接口直接调用 数据抽象层的接口
3.目的
3.1 低组件以来允许独立的维护
3.2 低组件依赖可以分离维护职责
4.使用
4.1 限制作为组件接口的模块的大小
4.2 在更高的抽象层次上来定义组件接口,这是为了限制跨越组件边界的请求类型,避免请求了解太多的实现细节
4.3 避免使用透传调用,即接收传入调用,又同时代理给其他组件。那么此时接口要同时为两个不同的组件进行服务,违反单一职责原则。
七、保持架构组件之间的平衡
1.原则
- 平衡代码中顶层组件的数量和体积
- 保持源代码中组件的数量接近于9,并且这些组件的体积基本一致
- 该原则能提高可维护性的原因在于,平衡的组件可以帮助定位代码,并且允许独立对组件进行维护
2.目的
2.1 好的组件平衡能让查找和分析代码变得更加容易
2.2 好的组件平衡能隔离维护所带来的影响
2.3 好的组件平衡能够分离维护职责
3.使用
3.1 顶层系统组件个数在理想状态下应为9个,通常来说位于 6 到 12 个 之间
3.2 各个组件的代码量应该大致相同
八、保持小规模代码库
1.原则
- 保持代码库规模尽可能小
- 控制代码库增长,并主动减少代码库的体积
- 拥有小型的代码、项目和团队是成功的一个因素
2.解释
代码库时存储在一个仓库中的所有源代码的集合,可以独力地进行编译和部署,并且由一个团队进行维护。
3.目的
3.1 以大型代码库为目标的项目更容易失败
3.2 大型代码库更加难以维护
3.3 大型系统会出现更密集的缺陷
4.使用
4.1 功能层面的方法
4.1.1 控制需求蔓延
项目开发过程中,需求不断增加,不断的迭代,有些需求看上去高大上,其实,实际应用中的效果不是很好,或者说反而会拖累当前的系统,那这样的需求的上线价值与以后的系统维护成本之间要做好权衡。
4.1.2 功能标准化
将功能实现代码标准化;底层实现的方式基本相同,可重用性的代码会增加
4.2 技术层面的方法
4.2.1 不要复制粘贴代码
复制粘贴,就说明代码可单独抽出一个方法;同时如果出现问题,同样的错误不用修改很多次;
4.2.2 重构已有代码
增加可维护性,减小代码体积
4.2.3 使用第三方库和框架
九、自动化开发部署和测试
1.原则
- 对你的代码进行自动化测试
- 通过使用测试框架来编写自动化测试
- 自动化测试让开发过程可预测并且能够降低风险
2.目的
2.1 自动化测试让测试可以重复
2.2 自动化测试会让开发更有效率
2.3 自动化测试让代码行为可预测
2.4 测试是对被测试代码的一种说明文档
2.5 编写测试能让你编写更好的代码
测试驱动开发,若一个方法内部实现了多个功能,那么测试用例就要考虑多种分支可能,所以为了方便测试,就会考虑如果将方法按照功能点进性拆分
3.使用
3.1 Junit 测试入门
3.2 编写良好单元测试的基本原则
3.2.1 正常情况和特殊情况都要进行测试
3.2.2 像维护非测试代码一样维护测试代码
3.2.3 编写独立的测试,他们的输出应该只反映被测试主体的行为
3.3 测试覆盖率来确定是否有足够的测试用例
覆盖率:指的是单元测试中执行的代码行数占代码库总行数的百分比。
通常80%以上。
十、编写简洁的代码
1.原则
- 编写简洁的代码
- 不应该在完成开发工作后留下代码坏味道
- 简洁的代码是可维护的代码
2.使用
2.1 不要编写单元级别的代码坏味道
忌:过长的代码单元;复杂的代码单元;长接口的代码单元
2.2 不要编写不好的注释
取消代码行内的注释;
代码远离注释;
不要为了注释而去写注释,每行代码上都有一行注释;而是必要的位置才去写注释
2.3 不要注释代码
版本控制上会留有一份旧的代码,所以不要留有注释的代码;
注释的代码对于一个新人来说就是一个具有挑战性的问题:
为什么前面的那个哥们把它注释掉了,是一个坑还是一个雷?我要不要试着修复它,万一出问题了怎么办?要不把它留着,留给后面的接班人?最好还是不动了,免得惹祸上身。
2.4 不要保留费期代码
方法中无法到达的代码
无用的私有方法
注释中的代码:避免在注释中使用代码
2.5 不要使用过长的标识符名称
避免:
使用表示多个职责的:generateConsoleAnnotataionScriptAndStylesheet
包含过多技术术语:GlobalProjectNamingStrategyConfigure
2.6 不要使用魔术常量
代码中不要出现数字,所有的数字均可用常量代替
2.7 不要使用为正确的处理的异常
2.7.1 捕获一切异常。
2.7.2 捕获特定异常。
在特定的调用地方,要对相应的异常进行指定捕获。
2.7.3 在展示给终端用户之前,先将特定的异常系想你转换成通用的信息
十一、后续
将原则变成实践
低层级(代码单元)原则要优于高层级(组件)原则
分享到:
相关推荐
【代码可维护性的重要性】 代码的可维护性是软件开发中的关键因素,它关系到程序的长期生命力和团队协作效率。当代码难以理解和修改时,不仅增加了解决问题的时间,也可能引入新的错误,从而降低软件的整体质量。...
编写高质量的代码是每个程序员追求的目标,这不仅关乎软件的稳定性、可维护性,还直接影响到团队合作效率和项目的长期成功。"写好代码的十个原则"提供了指导开发者提升编程水平的关键点。以下是对这些原则的详细解释...
在面向对象编程(OOP)领域,设计原则是构建可扩展、可维护和高效软件的基础。这些原则指导我们如何组织代码,使其遵循良好的结构和习惯。在这个“设计原则示例代码”压缩包中,我们可以期待找到与单一职责原则(SRP...
【诊断Java代码:设计轻松的代码维护】 在Java编程中,设计易于维护的代码是至关重要的,这不仅可以提高代码的可读性和可理解性,还能降低长期维护的成本。以下是几个关键点,可以帮助开发者创建更易于维护的Java...
本文将基于《修改软件的艺术:构建易维护代码的9条最佳实践》一书,深入探讨这9条关键原则,帮助提升软件的可维护性。 1. 清晰的命名:一个变量、函数或类的命名应当准确反映其功能或意图。好的命名可以减少理解...
代码优化原则与方法优化是软件开发中的核心议题之一,它关系到程序的运行效率、可读性以及可维护性。好的代码不仅能够提高软件性能,还能降低团队成员的学习成本和未来的维护难度。 一、代码阅读的方式 代码阅读...
SAP 物料主数据计量单位维护原则 SAP 物料主数据计量单位维护原则是指在 SAP 系统中对物料主数据进行计量单位维护的原则和方法。本文将详细介绍物料主数据计量单位维护原则,包括水性墨水和溶剂墨水的计量单位维护...
### 如何编写无法维护的代码:深入解析与反思 #### 总体概述 本文通过一种讽刺的方式探讨了如何编写难以维护的代码。虽然标题看似戏谑,但实际上文章旨在揭示那些不利于代码可读性和可维护性的做法。对于软件开发...
代码组织规则是软件开发中非常重要的一个部分,它直接关系到代码的可读性、可维护性和扩展性。一个良好的代码组织可以提高团队协作效率,降低维护成本,让项目更易于理解,也更易于后续的扩展和重构。 首先,代码块...
虽然代码缩进不影响代码的功能,但它极大地提高了代码的可读性和维护性。标准做法是使用制表符或四个空格进行缩进。良好的缩进使代码层次清晰,便于团队成员理解和维护代码。 ### 四、外链CSS样式和JavaScript脚本 ...
这个原则鼓励将不同的功能分离到不同的类中,以减少类的复杂性,提高代码的可维护性。 开放封闭原则(Open-Closed Principle,OCP):软件实体应该对扩展开放,对修改关闭。这意味着当需要添加新功能时,应该通过...
SAP 物料主数据计量单位维护原则 SAP 物料主数据计量单位维护原则是 SAP 系统中一个非常重要的概念,它涉及到物料的计量单位维护、计量单位转换、仓库业务处理等多个方面。下面将详细介绍 SAP 物料主数据计量单位...
在Android开发中,代码优化是提升应用程序性能的关键。以下是一些遵循的代码优化原则: ...在优化代码时,始终要考虑性能与代码可读性、可维护性的平衡,确保优化措施既能提升性能,又不影响代码的长期维护。
- 可维护性降低:当子类不能完全替换基类时,修改基类会影响使用它的所有子类,这可能导致大量的代码重构。 - 测试困难:违反LSP可能导致单元测试变得复杂,因为需要测试更多的边缘情况和异常行为。 - 软件稳定性...
嵌入式系统C语言编程是一种在资源受限的硬件平台上进行软件开发的实践,它要求程序员不仅要掌握C语言的基本...通过遵循这些原则,可以更好地控制资源使用,提高程序的可靠性,并为后续的代码维护和升级打下良好基础。
编写可维护的Go语言代码需要遵循一系列的实践原则和规范,从代码的可读性到包的设计,再到错误处理和并发模型,每一个环节都需要精心打磨。 ### 指导原则 1. **简单性**:代码应该尽量保持简单。简单的代码易于...
Python装饰器是一种强大的编程工具,它能够帮助我们遵循DRY(Don't Repeat Yourself,不重复代码)原则,通过...这种模式在代码维护和功能扩展方面提供了巨大的便利,并且已经成为Python高级编程中不可或缺的一部分。
开闭原则是面向对象设计中的一个核心原则,它在JAVA设计模式中占据着重要的地位。...通过学习这些源码,你将更好地掌握如何在自己的项目中实践开闭原则,以提升代码质量并提高软件的长期可维护性。
本书使用 java 语言(本书中的唯 一一种语言 来阐述和解释我们的原则。但是我们并 不是要教大家如何使用 Javaÿ 我们会假设读者至少可以阅读 Java 代码和 java 标准库的 API, 并且尽可能地保证示例代码足够简单,只...