合格的程序员不仅仅是让代码跑起来,而是要做到代码整洁,只满足为了能让编译器通过编译,机器能跑就行而写代码的程序会算不上开发者,码农都不算。
好的命名能体现出代码的特征,含义或者是用途,让阅读者可以根据名称的含义快速厘清程序的脉络。
本篇分享如下代码命名套路来提高我们代码命名。
- 勿模糊,准确达意
- 避免误导
- 做有意义的区分
- 结合上下文简化名称
- 使用可搜索、易读的名称
- 包命名规范
- 类名与方法名规范
混乱的代价
我相信每个程序员都被某些人的垃圾代码恶心过,导致开发进度被严重延缓、性能差劲、bug 多。
每次新增和修改代码如履薄冰,我们只有对那堆腐朽的代码了然于胸才敢修改。
随着时间推移,团队生产力下降,所有人都抵触这个项目,对其束手无策。
新手不熟悉原来的场景和设计,不知道如何修改才符合实际意图,导致更容易出现混乱。
最后,开发团队产生了抵触心理并造反了,再也无法忍受在这个垃圾代码基础上做开发,而管理层不愿意投入资源重新设计。
一个优秀的开发者应该时刻保持代码整洁,无关 deadline。
为什么会写出垃圾代码呢?
有的人可能会说,需求变化违背了最初的设计、排期太紧没法干好......
其实,这是一种不专业的托词。
推进进度是产品经理他们该干的,虽然痴迷于进度,但是多数产品经理也会期望有良好的可拓展代码以便应对市场变换莫测的需求。
连海誓山盟的爱情都会变,又如何做到需求不会改变呢?
所以我们比他们更加重视代码质量,才能应对变化的需求。
保护代码持续整洁优雅是每个优秀开发者都应该遵守的原则。
混乱的代码只会拖慢未来的开发进度,唯一加快进度的方法:始终尽可能保持代码优雅整洁。
好比医生在做手术之前要先消毒,你说消毒太耗时间了,直接拿刀子整吧。
作为专业的医生你会照做么?
作为专业的程序员,我们要了解代码变坏的风险并坚持保持代码质量。
什么是整洁代码
代码质量评判需要综合各种因素得到的,我们并不能从单一的维度去评判。
比如代码可读性好,但是空间与时间复杂度高,这并不能算得上是好代码。
好的代码应该具备:易拓展和维护、简洁(只做好一件事)、可复用性强(没有重复代码)、能快速写出单元测试。可读性强、没有副作用(做了名称以外的工作)。
易拓展和维护
在不破坏原来的代码设计下,可以简单快速的修改和添加代码实现功能拓展。
简单地说就是预留了拓展点,将新代码放在设计的可拓展点,不会因为新增一个功能而改动大量原始代码。
对修改关闭,对拓展开放,开闭原则。
对于开发而言,我们维护旧代码的时间超过新项目新代码的时间。
代码的可维护性就变得很重要,也就是说代码分层清晰、模块划分精当,满足高内聚低耦合、抽象出合理的接口,面向接口编程就意味着有较好的可维护性。
同样的代码,熟悉他的资深工程师会觉得很容易维护,而新人因为不熟悉代码,不懂设计模式而无法理解。
所以,易拓展具有主观性,我们需要提高基础技能才有资格说代码是否易拓展和维护。
只做好一件事
单一职责:每个函数、每个类、每个模块只专注于一件事。
不要设计大而全的类或者函数,我们需要将他们拆分成更细粒度功能更加单一的类。
它不会隐藏设计者的意图,干净利落的抽象和直截了当的控制语句。
我们应该让每个函数每行代码简单、逻辑清晰。这样的话,类依赖和被依赖的类也会变少,减少耦合度。
需要注意的是,也不能拆分太细,否则就会破坏内聚性。
高手,就是用最简单的方法去解决复杂问题。
没有重复代码
在开发过程中,我们应该尽可能抽象出「变与不变」,复用已经存在的代码,不要写重复的代码。
比如运用「封装、继承、抽象、多态」特性,代码封装成模块,隐藏变化的细节,暴露不变的接口。
把业务与非业务的代码逻辑分析,抽象成通用的框架、工具类等。
比如应用模板方法设计模式将不变的算法逻辑框架定义出来,把变化的点延迟到子类重写。
能快速写成单元测试
代码的可测试性差,比较难写单元测试,那基本上就能说明代码设计得有问题。
试想下,如果一个类大而全,有一个方法依赖了十几个外部对象才能完成工作,耦合严重。
当你在编写单元测试的时候,需要 mock 十几个依赖对象和数据。
那说明这个代码糟透了,需要合理拆分和设计。
可读性强
软件设计大师 Martin Fowler 说过:「Any fool can write code that a computer can understand. Good programmers write code that humans can understand.」
翻译成中文就是:"任何二货都会编写计算机能跑的代码。优秀的程序员能够编写人能够理解的代码。”
而可读性就会涉及到编码规范、命名、注释、函数职责是否单一、长度是否精简。
有数据显示读代码的时间与写代码的时间比例超过 10:1,并且编写当前代码的难度,取决于读周边代码的难度。
所以我认为可读性强是最重要的一点。
高质量命名套路
开发过程后命名随处可见,我们给变量、方法、参数、类、包命名。
而命名的好坏会影响我们的可读性,我们不妨从命名作为切入口来写好代码。
勿模糊,准确达意
在开发过程中,一旦发现更好的名称,就换掉旧的。
一个变量、方法、或者类的名称应该展示出它该有的功能。根据名字我们能知道它能做什么事情,如何使用。
如果一个名称需要大量注释来补充避免使用者跳坑,那就是糟糕的名字。
- 变量名体现出该字段作用,比如 LocalDate now = LocaDate.now(); now 标识当前时间。
- 防止出现让人模糊无法理解,必须还要依据大量上下文才能理解的代码。
- 不要使用魔术。
反例 1 :使用魔数
// 从数据库获取列表
List buyerList = dao.getList();
buyerList.forEach(x -> {
for (int i = 1; i