0x5、最快速改善代码质量的20条编程规范
① 命名
- 命名长短 → 以能
准确达意
为目标,在能达意的情况下越短越好,默认或大家都熟知的词,推荐用缩写;
- 利用上下文简写命名 → 作用域较小的临时变量、借助类这个上下文成员变量和函数参数,可以简化命名(如User类中的name);
- 命名要可读、可搜索 → 不要用生僻、难发音的单词来命名,统一命名习惯(如都用selectXXX表查询,你就不要用queryXXX);
- 接口和抽象类命名 → 接口前缀加"I" 或后缀加Impl,抽象类加或不加前缀Abstract,选择哪种命名方式都可以,但是要在项目里统一!
② 注释
注释到底该写什么?(做什么、为什么、怎么做),代码示例如下:
/** * (what) Bean factory to create beans. * * (why) The class likes Spring IOC framework, but is more lightweight. * * (how) Create objects from different sources sequentially: * user specified object > SPI > configuration > default object. */ public class BeansFactory { // ... }
尽管做什么、怎么做可以从代码中体现出来,但是还是建议在注释中写明,原因如下:
- 注释比代码承载的信息更多 → 类包含信息较多,简单的命名可能不够详尽,在注释中写明做什么更便于阅读;
- 注释起到总结性、文档的作用 → 让阅读代码的人通过注释就能大概理解代码的实现思路;
- 一些总结性注释能让代码结构更清晰 → 逻辑较复杂、较长又不好提炼拆分的函数,借助总结性注释让代码结构更清晰;
当然,不是注释写得越多就越好,太多意味着代码写得不够刻度,而且会对代码本身的阅读造成干扰,后面维护成本也较高。
一般来说:类和函数一定要写注释,且尽可能全面、详细,而函数内部的注释要相对少一些,一般都是靠好的明明、提炼函数、解释性变量、总结性注释来提高代码的可读性。
③ 代码风格 (团队/项目统一)
类、函数多大才合适?
很难给出一个确切的值,一个间接的判断标准:当一个类代码读起来让你感觉头大、找个函数找半天、用一个小功能就要引入整个类(类中包含很多无关此功能的实现函数)时,就说明类的函数过多了。
一行代码多长最合适?
一行代码最长不能超过IDE显示的宽度,滚动鼠标才能查看一行的完整代码,显然不利于代码的阅读。
善用空行分割单元块
对于较长、又不方便抽取成小函数的函数,除了用总结性注释分隔外,还可以用空行来分割代码块。除此之外,类成员与函数间、静态成员变量和普通成员变量间、各函数间等,都可以通过添加空行的方式让其界限更加明确。
四格缩进还是两格缩进?
都可以,但项目内要统一,建议不要使用Tab缩进,因为不同IDE的Tab缩进显示宽度不同,要用也行,要统一配置好!
大括号是否要另起一行?
都可以,推荐括号与语句同一行,这样可以节省代码行数,另起一行也行,左右括号垂直对齐,可以方便的看到哪些代码属于哪个代码块,各有千秋,还是那句话项目统一。
类中成员的排列顺序
建议:类所属包名 → import引入的依赖类(字母序从小到大排列) → 成员变量 → 函数,变量和函数间都是按照先静态后普通,作用域范围从大到小排列。实际上,还有种排列习惯,就是将有调用关系的函数放到一块。
④ 编程技巧
将代码分割成更小的单元块
当代码逻辑较复杂时,才建议提炼类或函数,如果提炼出的函数只包含两三行代码,阅读代码时还得跳过去看,反而增加了阅读成本。
避免函数参数过多
参数大于等于5个时,会影响到代码的可行,用起来也不方便,先考虑是否职责单一拆解,或者将函数的参数封装成对象传递。
勿用函数参数来控制逻辑
不要在函数中使用boolean类型的标识来控制内部逻辑,ture走这块逻辑,false走另一块,这违背了单一职责和接口隔离原则,建议拆成两个函数。还有一种判断参数是否为null控制逻辑的情况,同样建议拆解。
函数设计要职责单一
函数设置将更要满足单一职责原则,能多单一就多单一。
移除过深的嵌套层次
过深的嵌套本身理解起来比较费劲,嵌套超两层就要思考是否能减少嵌套,几种解决思路:
去掉多余的if或 else语句
、使用编程语言提供的continue、break、return关键字提前退出嵌套
、调整执行顺序
、将部分逻辑封装成函数调用
,多态
等。
学会使用解释性变量
常量取代魔法数字,使用解释性变量来解释复杂表达式,示例如下:
public double CalculateCircularArea(double radius) { return (3.1415) * radius * radius; } // 常量替代魔法数字 public static final Double PI = 3.1415; public double CalculateCircularArea(double radius) { return PI * radius * radius; } if (date.after(SUMMER_START) && date.before(SUMMER_END)) { // ... } else { // ... } // 引入解释性变量后逻辑更加清晰 boolean isSummer = date.after(SUMMER_START) && date.before(SUMMER_END); if (isSummer) { // ... } else { // ... }