代码精进之路
2021-11-15 20:14:44 45 举报
AI智能生成
代码的要求
作者其他创作
大纲/内容
一行一个声明
标识符的声明应该和它的使用尽可能地靠近,特别是局部变量的标识符声明。
局部变量需要时再声明
为了阅读和记忆,类变量的声明则要集中。因为类变量无论是私密变量,还是公开变量,在类的方法实现中,随时都可以调用。我们需要把这些变量放在一起,以便于修改和查找。
类属性要集中声明
声明时就应该完成初始化。声明时初始化,可以防止初始化的遗漏或者不必要的代码重复。
声明时就初始化
类声明和方法声明后,要使用花括号把实现的代码包括进来。
左括号不要单独成行,要紧随在语句尾部,以一个空格隔开
右括号单独一行。
尾随的花括号
靠紧的小括号
语义相关的词语,常见的搜索模式,要尽量放在用一行。
搜索优化的换行
八大原则
标识符声明
识别子类的方法是不是重写方法
Override
重写方法可以不遵守父类方法的规范
在声明继承关系中,Java注解该如何使用?
第一件事情是,如果接口的设计存在不合理性,或者新方法取代了旧方法,我们应该尽早地废弃该接口。
Deprecated
第二件事情是,如果我们在现有的代码中使用了废弃的接口,要尽快转换、使用替换的方法。
在废弃退役接口的情况下,如何使用注解?
SuppressWarnings
Java 提供了一个不推荐使用的注解,SuppressWarnings。这个注解告诉编译器,忽略特定的警告。警告是非常有价值的信息,忽略警告永远不是一个最好的选项。
忽略警告
1. 重写的方法,总是使用
2. 过时的接口,尽早废弃
3. 废弃的接口,不要使用
总结
Java注解
异常状况的处理会让代码的效率变低。一个流畅的业务,它实现代码的执行路径,理想的状况就是没有任何异常状况发生。
异常的原因
非正常异常(Error)
运行时异常(RuntimeException)
非运行时异常(检查型异常(CheckedException))
可处理异常(Exception)
异常分类
应用程序需要处理异常(CheckedException 和 RuntimeException),就需要我们在方法的规范描述文档中清楚地标记异常。没有标记的异常,应用程序没有办法通过文档了解哪些异常需要处理、什么状况下会抛出异常以及该怎么处理这些异常。
标记清楚抛出异常
异常类名(IllegalArgumentException,FileNotFoundException)
异常描述(“Invalid file path”)
异常堆栈(at sun.security.ssl.InputRecord.read(InputRecord.java:504))
处理好捕获异常
不要使用异常机制处理正常业务逻辑
异常的使用要符合具体的场景
具体的异常要在接口规范中声明和标记清楚
处理异常
1. 版权和许可声明
2. 命名空间(package)
3. 外部依赖(import)
代码文件的头部结构
1. 类的规范
2. 类的声明
3. 类的属性和方法
代码文件对象结构
1. 类的属性
2. 构造方法
3. 工厂方法
4. 其他方法
类的内部代码结构
1.方法的规范
2. 方法的声明
3. 方法的实现
方法的代码结构
1. 方法的简短介绍
2. 方法的详细介绍(可选项)
3. 规范的注意事项 (使用 apiNote 标签,可选项)
4. 实现方法的要求 (使用 implSpec 标签,可选项)
5. 实现的注意事项 (使用 implNote 标签,可选项)
6. 方法参数的描述
7. 返回值的描述
8. 抛出异常的描述:需要注意的是,抛出异常的描述部分,不仅要描述检查型异常,还要描述运行时异常
9. 参考接口索引(可选项)
10. 创始版本(可选项)
方法规范的实现
1. public/private/protected(访问控制限定词,制定访问权限)
2. abstract(抽象类或者抽象方法,具体实现由子类完成)
3. static(静态类、方法或者类属性)
4. final(定义不能被修改的类、方法或者类属性)
5. transient(定义不能被序列化的类属性)
6. volatile(定义使用主内存的变量)
7. default(声明缺省的方法)
8. synchronized(声明同步的方法)
9. native(声明本地的方法,也就是 Java 以外的语言实现的方法)
10. strictfp(声明使用精确浮点运算)
按顺序使用限定词
1. 版权和许可声明代码块
2. 命名空间代码块
3. 外部依赖代码块
4. 类的代码块
5. 类的属性与方法之间
6. 类的方法之间
7. 方法实现的信息块之间
使用空行分割代码块
组织好代码块
提高协作效率的最高技巧不是提高沟通技巧,而是要减少沟通的数量,提高沟通的质量,尤其是要减少数量。
区分外部接口和内部实现
无论对于调用者,还是实现者来说,外部接口的使用都要有章可循,有规可依
合约要成文
合约既然是我们协作的依靠,就一定要清晰可靠、容易遵循,不能有模棱两可的地方。
接口规范主要用来描述接口的设计和功能,包括确认边界条件、指定参数范围以及描述极端状况。
合约要清楚
接口的设计和规范的制定,一定要谨慎再谨慎,小心再小心,反复推敲,反复精简。
合约要稳定
接口规范,我们的原则是,能不变更就不变更;必须的变更,一定要反复思量该怎么做才能把影响降到最低。
变更要谨慎
接口规范是协作合约
JavaDoc 就是一种顾及了多方利益的一种组织形式。它通过文档注释的形式,在接口声明的源代码定义和描述接口规范。这种和源代码结合的方式,可以方便我们维护接口规范,也有利于保持接口规范和接口声明的一致性。
JavaDoc 工具可以把文档注释,转换为便于阅读为 HTML 文档。这样就方便规范的使用者阅读了。
使用Java Doc
1. 起草接口规范,或者起草提议的修订规范
2. 找相关领域的专家,审议草案,并根据评审意见,修改接口规范
3. 如果领域专家审议通过,提交兼容性和规范性审查程序;并根据审查意见,相应地修改接口规范
4. 兼容性和规范性审查通过,修改接口合约
5. 按照议定的接口规范,编写最终的实现的代码
接口制定和修订步骤
接口文档规范
1. 从用户的角度出发来思考用户指南,用户指南要容易上手
2. 用户指南和源代码一样,也有开发周期,也是需要维护的
用户指南
在不损害代码质量的前提下,效率可以节省我们的时间和成本。这种节省不仅仅停留在编码阶段,更体现在整个软件的生命周期里。
1. 提高编码的效率
代码的质量在于它和预期规范的一致性。一致、简单、规范的代码易于测试。相反,复杂的代码会加大测试的难度,难以达到合适的测试覆盖率。
2. 提高编码的质量
代码的维护要求代码必须能够修改,增加新功能,修复已知的问题。如果代码结构的清晰、易于阅读理解,那么问题就容易排查和定位。
3. 降低维护的成本
要想让更多的人参与,就需要一致的编码风格,恰当地使用文档。要方便他们阅读,便于解释。使用编码规范可以让一个程序员减少出错,避免不必要的困扰。
4. 扩大代码的影响
为什么需要编码规范?
自主模式的运行是无意识的、快速的、不怎么耗费脑力;
自主模式(快系统)
控制模式需要集中注意力,耗费脑力,判断缓慢,如果注意力分散,思考就会中断。
控制模式(慢系统)
自主模式和控制模式的分工合作是高效的,损耗最小,效果最好。快速的、习惯性的决断交给勤快省力的自主模式,复杂的、意外的决断由耗时耗力的控制模式接管。
编码规范的心理因素
规范代码检查
好的代码就是坚持使用最直观的编码方式,而不是追求代码简短,真的可以避免很多不必要的错误
第一点是可以减少代码错误
第二点是可以节省我思考的时间
第三点是可以节省代码阅读者的时间
好处
减少错误、节省时间,是我们现在选择编码方式的一个最基本的原则。
1. 容易理解
2. 没有明显的安全问题
3. 能够满足最关键的需求
4. 有充分的注释
5. 使用规范的命名
6. 经过充分的测试
好代码
1. 难以阅读的代码
2. 浪费大量计算机资源的代码
3. 代码风格混乱的代码
4. 复杂的、不直观的代码
5. 没有经过适当测试的代码
坏代码
好代码和坏代码
计划
分析和设计
代码实现
测试
运营
维护
流程
项目经理
设计人员
开发人员
测试人员
客户
服务人员
软件生命周期的参与人员
参与人员
软件生命周期
最适合当前现实环境的代码,才是最优秀的代码
1. 代码写得又快又好,是“经济”的;代码写得快,但是错误多,不是一个“经济”的行为
2. 代码跑得又快又好,是“经济”的;代码跑得快,但是安全问题突出,不是一个“经济”的行为
3. 代码写得精简易懂,是“经济”的;代码写得精简,但是没人看得懂,不是一个“经济”的行为
比如
优秀的代码需要具备三个特征: 经济、规范、安全
程序员间合作交流最重要的语言便是代码,换句话说,这就需要我们规范地编写代码,使用大家都接受的风格。不规范的代码,我们可能节省了眼前的时间,但是测试、运营、维护阶段,就需要更多的时间。而一旦问题出现,这些代码会重新返工,又回到我们手里,需要阅读、修改,再一次浪费我们自己的时间。对于这些代码,每一点时间的付出,都意味着投入,意味着浪费,意味着我们损失了做更有意义事情的机会
什么是好代码
第一个观点是好的程序员不会写坏的代码,要不然,就是他还不足够优秀一个非常优秀的程序员,他主观上非常认真,能力又非常强,但他也会犯非常“低级”、“幼稚”的错误
对于自身,我们对自身的希望,对别人,可以更加宽容。一个好的团队,我们首先要思考如何提供一种比较好的机制,减少此类错误的发生
第二个观点是同一个错误不能犯两次
错误并不可怕,你不必为此深深自责,更不应该责备他人。要不然,一旦陷入自责和指责的漩涡,很多有建设意义的事情,人们可能没有意识去做;或者即使意识到了,也没法做,做不好。
第三个观点是一个人犯了错误并不可怕,怕的是不承认错误
普遍的观点
提高程序员的修养,是一个永不过时的课题。从别人的失败和自己的失败中学习、积累、提高,是一个程序员成长的必修课
优秀的代码源于我们对细节的热情和执着
如果你能够找到哪怕仅仅是一个小问题的一个小小的改进办法,都有可能会给你的代码质量带来巨大的提升和改变
程序猿
编译器的警告,我们一定要非常警觉。能消除掉所有的警告,你就应该消除掉所有的警告。就算实在没有办法消除掉编译警告,那你也一定要搞清楚警告产生的原因,并确认编译警告不会产生任何后续问题
编译器
软件测试会尽可能地覆盖关键逻辑和负面清单,以确保关键功能能够正确执行,关键错误能够有效处理
一个没有良好回归测试的软件,很难保证代码变更的质量;也会使得代码变更充满不确定性,从而大幅地提高代码维护的成本
回归测试
代码评审是一个有效的在软件研发过程中抵御人类缺陷的制度。通过更多的眼睛检查软件代码,被忽视的错误更容易被逮住,更好的设计和实现更容易浮现出来
代码评审
静态代码分析(Static Code Analysis)是通过对源代码的检查来发现潜在问题的一种软件质量保障方式
代码覆盖率(Code Coverage)是一个反映测试覆盖程度的指标。它不仅仅量化测试的指标,也是一个检测代码缺陷的好工具
代码分析
如何避免
如何避免错误
需要能够熟练操控一门编程语言
掌握一门编程语言
程序员的存在不是为了写代码,而是为了解决现实问题,实现现实价值
优秀的程序员还要深入理解问题,懂得问题的最核心价值。只有理解了问题,看到了解决问题的价值,我们才能够真正解决好问题
解决现实的问题
能够发现关键问题,是一个好程序员和优秀程序员的分水岭
可以从一个被动的做事情的程序员,升级为一个主动找事情的程序员
优秀的程序员,能够发现解决方案背后的妥协和风险。所以,他可以预设风险防范措施,设置软件的适用边界
优秀的程序员,能够敏锐地观察到产品的关键问题,或者客户未被满足的需求。所以,他可以推动产品持续地进步和演化
发现关键的问题
优秀的程序员,一定是懂得妥协,懂得选择,一步一步把事情沉静地朝前推动的人
我们写的每一行代码,都可能存在问题。有时候,我发现别人的代码的问题;有时候,别人发现我的代码的问题。我们最后都会明白,要坦诚地面对别人的问题,也要坦然地面对自己的问题
沉默的前行者
优秀的程序员是他人可以依赖的伙伴
优秀的程序员,知道团队合作的重要性,是一个优秀的团队成员。他在团队中能够快速学习、成长,变得越来越优秀,也能够帮助其他团队成员变得越来越优秀。
编程语言、花样工具、逻辑思维、解决问题这些“硬技能”可以决定我们的起点的话,影响力、人际关系这些“软技能”通常影响着我们可以到达的高度。
可以依赖的伙伴
优秀的程序员是高效的时间管理者。
优秀的程序员会更好地管理时间,或者提高效率,或者用好时间。
要坚持做需要做的事情。不需要的、不紧急的、价值不大的,我们可以暂时搁置起来。一个人,能做的事情是有限的,能把最重要的事情最好,就已经很了不起了。
时间管理者
优秀程序员的特征
编码规范指的是针对特定编程语言约定的一系列规则,通常包括文件组织、缩进、注释、声明、语句、空格、命名约定、编程实践、编程原则和最佳实践等。
一旦学会了编码规范,并且严格地遵守它们,可以让我们的工作更简单,更轻松,少犯错误。
代码编程规范
复杂是代码质量的敌人。越复杂的代码,越容易出现问题。
在编码的时候,我们应该尽量使代码风格直观、逻辑简单、表述直接。
规范的代码,可以降低代码出错的几率
在代码制造的每一道关卡,规范执行得越早,问题解决得越早,整个流水线的效率也就越高。
规范的代码,可以提高编码的效率
在一个软件生命周期里,软件维护阶段花费了大约 80% 的成本
很多软件代码,其生命的旅程超越了它的创造者,超越了团队的界限,超越了组织的界限,甚至会进入我们难以预想的领域。
规范的代码,降低软件维护成本
我们要尽早地使用编码规范,尽快地培养对代码风格的敏感度。 良好的习惯越早形成,我们的生活越轻松。
编码规范越使用越高效
代码规范的价值
为标识符提供附加的信息,赋予标识符现实意义。帮助我们理顺编码的逻辑,减少阅读和理解代码的工作量
使代码审核变得更有效率,专注于更重要的问题,而不是争论语法和命名规范这类小细节,提高开发效率
提高代码的清晰度、可读性以及美观程度
避免不同产品之间的命名冲突
一个好的命名规范的好处
驼峰命名法指的是使用大小写混合的格式,单词之间不使用空格隔开或者连接字符连接的命名方式。
驼峰命名法
在蛇形命名法中,单词之间通过下划线“_”连接,比如“out_of_range”。
蛇形命名法(snake_case)
在蛇形命名法中,单词之间通过连字符“-”连接,比如“background-color”。
串式命名法(kebab-case)
命名方法
要有准确的意义(名字要能够准确、完整地表达出它代表的意义,可以见字知意,名副其实。)
Java 倾向于使用驼峰命名法
C 语言倾向于使用蛇形命名法
CSS 使用串式命名法。
严格遵守命名规范
可读性强的名字优先于简短的名字,尽量使用完整的词汇。
不要使用缩写、简写、缩略词,除非这些词语被广泛使用。
不要使用太短的名字,比如一个字母,除非是广泛接受的特例(i/j/k/m/n 表示临时使用的整数,c/d/e 表示临时使用的字符)
避免含糊、混淆或者误导。
不要混合使用英文和汉语拼音。
可读性优先
命名原则
命名规范
代码块内所有的内容都是为了一个目标服务的,不能把无关的内容放在同一个代码块里。同一个代码块里语句的相互联系比与相邻代码块里的语句关系更为紧密;
保持代码块的单一性,一个代码块只能有一个目标
代码块是一个完整的信息块。一个代码块
注意代码块的完整性
代码块过多,会让人觉得路径太长,逻辑复杂,不容易阅读理解。一个基础的代码块最好不要超过 25 行(通常显示屏小半个页面),否则就会有增加阅读理解的困难。
代码块数量要适当。
程序分块
合理利用空白空间,空白空间不仅区分代码块,还可以表示代码块之前的联系
阅读的习惯顺序是从左到右,代码也如此。因此不同行,但同级别的代码要靠左对齐。
同级别代码块靠左对齐
阅读代码总是从上往下读,不同行的同级别的代码块之间,要使用空行分割。
同级别代码块空行分割
区分不同行的不同级别的代码,可以使用缩进。缩进的目的是为了让我们更直观地看到缩进线,从而意识到代码之间的关系。
下一级代码块向右缩进
同一行内的代码块,可以使用空格区分开不同的逻辑单元。
同行内代码块空格区隔
如何利用空白空间
利用空白空间
每行代码字符数的限制。一般情况下,每行代码不要超出 80 个字符
如果一行不足以容纳一个表达式,就需要换行
在逗号后换行。
在操作符前换行。
高级别的换行优先。
新的换行与上一行同级别表达式的开头对齐。
如果上述规则导致代码混乱或者代码太靠右,使用 8 个空格作为缩进(两个缩进单位)。
换行原则
基本的换行原则
整理代码有一个基本的思想,那就是把代码分割成大脑能够有效识别并记忆的信息块,通过合理地使用空行、空格和缩进,把这些信息块清晰地呈现出来。清晰的代码结构,可以帮助我们理顺编码的思路,提高编码的效率,减少编码的错误,提高代码的可读性,降低代码的维护成本。
代码格式
因为注释不需要运行,所以没有常规的办法来测试它
注释难以维护,这是使用注释带来的最大的麻烦。
注释为我们提供了一个借口。使用注释来解释代码,是注释的本意。但是,我们有时候会过度依赖解释,从而放弃了潜在的替代方案。
注释的缺点
第一种类型,是记录源代码版权和授权的
第二种类型,是用来生成用户文档的
第三种类型,是用来解释源代码的
常见的注释类型
针对第一种注释类型,也就是固定的版权和授权信息,使用一般的星号注释符(/-/)
针对第二种注释类型,即生成用户文档的注释,使用 Javadoc 要求的格式,文档注释符(/-*/)。除了首行使用特殊的文档注释符(/)
针对第三种注释类型,也就是代码解释注释,只使用行注释符(//)
注释风格
准确,错误的注释比没有注释更糟糕。
必要,多余的注释浪费阅读者的时间。
清晰,混乱的注释会把代码搞得更乱。
原则
注释
代码精进之路
0 条评论
回复 删除
下一页