读书,收获,分享
建议后面的五角星仅代表笔者个人需要注意的程度。
Talk is cheap.Show me the code
建议144:提倡良好的代码风格★★☆☆☆
优秀团队的编码风格应该具有哪些特征:
-
整洁
代码首先是给人看的,然后才是给机器执行的,对于机器来说,只要代码符合规范,不在乎其格式是否整洁、是否有缩进、是否有回车,只要代码正确就能正常运行,而人就不同了,没有缩进没有回车的代码基本上是不可阅读的。
-
统一
从一个团队中诞生的代码应该具有一致的风格,不要带有个人色彩的风格标识。尽量让我们的代码看起来很职业。
-
流行
一种潮流风行世界的时候必然有其诞生的原因(感冒也包括在内),一种编码格式的流行也必然有它存在的理由,我们完全可以借鉴流行的编码格式,没有必要对这种风格进行重塑,而且使用流行风格可以让新成员尽快融入项目,避免出现进入一个新环境而出现茫茫无助的状态。
-
便捷
制定出来的编码规范必须有通用开发工具支撑,不能制定出只能由个别开发工具支持的规范。
建议145:不要完全依靠单元测试来发现问题★★☆☆☆
原因有以下四点:
-
单元测试不可能测试所有的场景(路径)
单元测试必须测试的三种数据场景是:正常场景、边界场景、异常场景。如果这三种测试场景都能出现预期的结果,则认为代码正确。
-
代码整合错误是不可避免的
单元测试只是保证了分割的独立单元的正确性,它不能保证一个功能的完整性。
部分代码无法(或很难)测试
单元测试验证的是编码人员的假设
敏捷开发中提倡的TDD(Test-Driven Development
)测试驱动开发:单元测试先行,而后才会编写生产代码,这可以大幅度地提升代码质量,加快项目开发的进度。
建议146:让注释正确、清晰、简洁★★☆☆☆
一些不好的注解习惯:
废话式注释
-
故事式注释
一句话说清即可,不需要讲故事
-
不必要的注释(想笑)
//默认值为0 private int num;
-
过时的注释
注释与代码的版本不一致,注释是1.0版本,而代码早已窜到了5.0版本
-
大块注释代码
废弃(在生产版本上肯定不用该代码),则应该完全删除掉。
流水账式的注释
-
专为
JavaDoc
编写的注释建议在注释中只保留
<p>
、<code>
等几个常用的标签,不要增加<font>
、<table>
、<div>
等标签。
那好的注释应该是这样子的:首先要求正确,注释与代码意图吻合;其次要求清晰,格式统一,文字准确;最后要求简洁,说明该说明的,惜字如金,拒绝不必要的注释。
如下类型的注释就是好的注释:
-
法律版权信息
这是我们在阅读源代码时经常看到的,一般都是指向同一个法律版权声明的。
-
解释意图的注释
说明为什么要这样做,而不是怎么做的
警示性注释
-
TODO
注释对于一些未完成的任务,则增加上
TODO
提示,并标明是什么事情没有做完,以方便下次看到这个TODO
标记时还能记忆起要做什么事情
注意:注释不是美化剂,而是催化剂,或为优秀加分,或为拙劣减分。
建议147:让接口的职责保持单一★★☆☆☆
职责是一个接口(或类)要承担的业务含义,或是接口(或类)表现出的意图。
单一职责有以下三个优点:
-
类的复杂性降低
职责单一,在实现什么职责时都有清晰明确的定义,那么接口(或类)的代码量就会减少,复杂度也就会减少。当然,接口(或类)的数量会增加上去,相互间的关系也会更复杂,这就需要适当把握了。
-
可读性和可维护性提高
职责单一,会让类中的代码量减少,我们可以一眼看穿该类的实现方式,有助于提供代码的可读性,这也间接提升了代码的可维护性。
-
降低变更风险
变更是必不可少的,如果接口(或类)的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,那就会对系统的扩展性、维护性都有非常大的帮助。
注意:接口职责一定要单一,实现类职责尽量单一。
建议148:增强类的可替换性★★☆☆☆
里氏替换原则是说“所有引用基类的地方必须能透明地使用其子类的对象”,通俗点讲,只要父类型能出现的地方子类型就可以出现,而且将父类型替换为子类型还不会产生任何错误或异常,使用者可能根本就不需要知道是父类型还是子类型。但是,反过来就不行了,有子类型出现的地方,父类型未必就能适应。
为了增强类的可替换性,就要求我们在设计类的时候考虑以下三点:
子类型必须完全实现父类型的方法
-
前置条件可以被放大
class Base { public void doStuff(HashMap hashMap) { } } class Sub extends Base { public void doStuff(Map map) { } }
- 后置条件可以被缩小
增强类的可替换性,则增强了程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。
建议149:依赖抽象而不是实现★★☆☆☆
在面向过程开发中,我们考虑的是如何实现,依赖的是每个具体实现,而在OOP
中,则需要依赖每个接口,而不能依赖具体的实现,比如我们要到北京出差,应该依赖交通工具,而不是依赖的具体飞机或火车,也就是说我们依赖的是交通工具的运输能力,而不是具体的一架飞机或某一列火车。这样的依赖可以让我们实现解耦,保持代码间的松耦合,提高代码的复用率,这也是依赖倒置原则(Dependence Inversion Principle,简称DIP)提出的要求:
- 高层模块不应该依赖低层模块,两者都应该依赖其抽象。
- 抽象不应该依赖细节。
- 细节应该依赖抽象。
依赖倒置原则在Java语言中的表现就是:
- 模块间的依赖是通过抽象发生的,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。
- 接口或抽象类不依赖于实现类。
- 实现类依赖接口或抽象类。
我们怎么在项目中使用这个规则呢?只要遵循以下的几个规则就可以:
- 尽量抽象
- 表面类型必须是抽象的
- 任何类都不应该从具体类派生
- 尽量不要覆写基类的方法
- 抽象不关注细节
建议150:抛弃7条不良的编码习惯★★☆☆☆
自由格式的代码
不使用抽象的代码
-
彰显个性的代码
“最小惊诧原则”(Principle Of Least Surprise简称POLS,或者Principle Of LeastAstonishment简称POLA),其意是说要使用最常见的,而不是最新颖的功能。
-
死代码,冗余代码
忘记删除的代码或者废弃的代码等
-
拒绝变化的代码
一个在
JDK 1.1
中就过时的方法还还能在使用JDK 1.6
项目中存在,谓之曰“没有坏,就不要去修它”—该重构它了,它没坏,但它赖以生存的环境已经变了! -
自以为是的代码
相信自己编写的工具类,而不是开源工具,宁愿自己写序列化工具,也不选择
kryo
或protostuff
;宁愿自己写日期处理工具,也不选择Joda
或date4j
;宁愿自己写批处理框架,也不选择Spring Batch
,这样是不行的!—相信天外有天吧,更多更好的工具等待着你去发掘。
建议151:以技术员自律而不是工人★★★★★
下20条建议可以逐步把我们向技术人员方向培养:
-
熟悉工具
军人手中有枪,农民手中有锄头,而我们手里只有Java,这也是我们能够引以为豪的工具,我们应该了解它的使用范围,了解的它的生态系统,了解它的发展趋势—它也可能就是陪伴我们一生的那个工具,也祝愿它是。
-
使用
IDE
在技术领域,不要相信“无刀胜有刀”之类的鬼话—“高手都用记事本或VI开发”
-
坚持编码
不要考虑自己的职位、岗位,只要是Java圈子的生物都应该坚持编码,没有编码,就等于是无源之水,无本之木,何来灵感和灵性?
-
编码前思考
在坐下来开始编码之前,必须已经完成设计,最低要求是对开发中遇到的问题有清晰的认识,不要在编码中解决问题。
-
坚持重构
不要相信一次就能写出优秀的代码,这是不现实的,任何优秀的代码、算法都是经过多次重构磨练的,坚信自己的下一个版本或代码更优秀。
写注释、写说明、写报告都是对代码或项目的回顾和总结,不仅仅是为了后续的参与人员,同时也是为了整理自己头脑中混乱的思维。
-
保持程序版本的简单性
一个项目不要保持多个版本,即使有分支也必须定义出项目合并的条件,或者时间约束,或者目标约束,不可任由版本扩散。
-
做好备份
世界上没有万无一失的事情,不做备份,一旦灾难发生就无挽救的余地了
-
做单元测试
单元测试不仅能增强你的信心,也能给你带来好名声—后续者一看,“哇哦,单元测试写得这么完整,肯定是一个认真、负责的人”。
-
不要重复发明轮子
在项目中使用已经成熟的工具或框架,而不是自己编写。但是如果想共享一个新的
MVC
框架,那就尽管去重复发明轮子吧,它不是以交付为目的的,而是以技术研究为目标的。 当按下
Ctrl+C
的时候,问问自己“我在做什么?拷贝是否是唯一能做的?为什么不能重构一下呢”,不要让大段的代码散落在各处,不要做搬运工,不要做拷贝工,要做技术工。-
让代码充满灵性
为变量、类、方法起个好听的名字是一个不错的主意,为代码增加必要的注释也是很好的办法,“One Line”能解决一个上百行代码的问题,也是一个优秀的实现。
-
测试自动化
不管是性能测试、单元测试,还是功能测试,想尽办法让它自动化,不要在测试之前手动配置或触发条件,这不够人性化,也同时让代码“汗颜”—本是用来自动执行的,但却被手动设置了条件。
-
做压力测试
不要相信业务人员“最多200个用户使用”之类的话,把业务人员制定的指标扩大3倍,然后再做压力测试。不要迷信自己的代码很健壮,在高并发时只有上帝知道发生了何事,你又怎么能知道?
-
“剽窃”不可耻
多看开源代码,学习一下人家是如何编码的,然后经常“剽窃”一下,这也是提高技能的最佳途径,我们不是孔乙己,“剽窃”不可耻。
-
坚持向敏捷学习
不管“敏捷”与“非敏捷”之间的争论有多激烈,敏捷中的一些思想是非常优秀的,例如
TDD
测试驱动开发、交流的重要性、循序渐渐开发等。 重里更重面
UI(User Interface)
是“面”,Java程序是“里”,客户首先感受到的是“面”,然后才是“里”,要想获得良好的第一印象,那就需要有一个简洁、清晰、便捷的UI,即使“金玉其外败絮其中”,我们也可以继续重构。
-
分享
“独乐乐”不如“众乐乐”,把自己的代码分享出去收获的不仅仅是赞许,还有自己能力的提升—暴露出自己的Bug,在众目睽睽之下修正之,知耻而后勇也。
-
刨根问底
有问题不可怕,可怕的是掩盖,或者虚假掩盖,“哦,这个问题呀,加上这个参数就可以解决了”—这不是解决问题的办法,在答案之后加上“是因为……",这才是解决了问题。
-
横向扩展
Java要运行在
JVM
、操作系统上,同时还要与硬件、网络、存储交互,另外要遵循诸如FTP
、SMTP
、HTTP
等协议,还要实现Web Service
、RMI
、XML-RPC
等接口,所以我们必须熟悉相关的知识—扩展知识面,这些都是必须去学习的。