思想为源——读《编写高质量代码:改善Java程序的151个建议》(十二)

读书,收获,分享
建议后面的五角星仅代表笔者个人需要注意的程度。
Talk is cheap.Show me the code

建议144:提倡良好的代码风格★★☆☆☆

优秀团队的编码风格应该具有哪些特征:

  1. 整洁

    代码首先是给人看的,然后才是给机器执行的,对于机器来说,只要代码符合规范,不在乎其格式是否整洁、是否有缩进、是否有回车,只要代码正确就能正常运行,而人就不同了,没有缩进没有回车的代码基本上是不可阅读的。

  2. 统一

    从一个团队中诞生的代码应该具有一致的风格,不要带有个人色彩的风格标识。尽量让我们的代码看起来很职业。

  3. 流行

    一种潮流风行世界的时候必然有其诞生的原因(感冒也包括在内),一种编码格式的流行也必然有它存在的理由,我们完全可以借鉴流行的编码格式,没有必要对这种风格进行重塑,而且使用流行风格可以让新成员尽快融入项目,避免出现进入一个新环境而出现茫茫无助的状态。

  4. 便捷

    制定出来的编码规范必须有通用开发工具支撑,不能制定出只能由个别开发工具支持的规范。

建议145:不要完全依靠单元测试来发现问题★★☆☆☆

原因有以下四点:

  1. 单元测试不可能测试所有的场景(路径)

    单元测试必须测试的三种数据场景是:正常场景、边界场景、异常场景。如果这三种测试场景都能出现预期的结果,则认为代码正确。

  2. 代码整合错误是不可避免的

    单元测试只是保证了分割的独立单元的正确性,它不能保证一个功能的完整性。

  3. 部分代码无法(或很难)测试

  4. 单元测试验证的是编码人员的假设

敏捷开发中提倡的TDD(Test-Driven Development)测试驱动开发:单元测试先行,而后才会编写生产代码,这可以大幅度地提升代码质量,加快项目开发的进度。

建议146:让注释正确、清晰、简洁★★☆☆☆

一些不好的注解习惯:

  1. 废话式注释

  2. 故事式注释

    一句话说清即可,不需要讲故事

  3. 不必要的注释(想笑)

        //默认值为0
        private int num;
    
  4. 过时的注释

    注释与代码的版本不一致,注释是1.0版本,而代码早已窜到了5.0版本

  5. 大块注释代码

    废弃(在生产版本上肯定不用该代码),则应该完全删除掉。

  6. 流水账式的注释

  7. 专为JavaDoc编写的注释

    建议在注释中只保留<p><code>等几个常用的标签,不要增加<font><table><div>等标签。

那好的注释应该是这样子的:首先要求正确,注释与代码意图吻合;其次要求清晰,格式统一,文字准确;最后要求简洁,说明该说明的,惜字如金,拒绝不必要的注释。

如下类型的注释就是好的注释:

  1. 法律版权信息

    这是我们在阅读源代码时经常看到的,一般都是指向同一个法律版权声明的。

  2. 解释意图的注释

    说明为什么要这样做,而不是怎么做的

  3. 警示性注释

  4. TODO注释

    对于一些未完成的任务,则增加上TODO提示,并标明是什么事情没有做完,以方便下次看到这个TODO标记时还能记忆起要做什么事情

注意:注释不是美化剂,而是催化剂,或为优秀加分,或为拙劣减分。

建议147:让接口的职责保持单一★★☆☆☆

职责是一个接口(或类)要承担的业务含义,或是接口(或类)表现出的意图。

单一职责有以下三个优点:

  1. 类的复杂性降低

    职责单一,在实现什么职责时都有清晰明确的定义,那么接口(或类)的代码量就会减少,复杂度也就会减少。当然,接口(或类)的数量会增加上去,相互间的关系也会更复杂,这就需要适当把握了。

  2. 可读性和可维护性提高

    职责单一,会让类中的代码量减少,我们可以一眼看穿该类的实现方式,有助于提供代码的可读性,这也间接提升了代码的可维护性。

  3. 降低变更风险

    变更是必不可少的,如果接口(或类)的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,那就会对系统的扩展性、维护性都有非常大的帮助。

注意:接口职责一定要单一,实现类职责尽量单一。

建议148:增强类的可替换性★★☆☆☆

里氏替换原则是说“所有引用基类的地方必须能透明地使用其子类的对象”,通俗点讲,只要父类型能出现的地方子类型就可以出现,而且将父类型替换为子类型还不会产生任何错误或异常,使用者可能根本就不需要知道是父类型还是子类型。但是,反过来就不行了,有子类型出现的地方,父类型未必就能适应。

为了增强类的可替换性,就要求我们在设计类的时候考虑以下三点:

  1. 子类型必须完全实现父类型的方法

  2. 前置条件可以被放大

        class Base {
            public void doStuff(HashMap hashMap) {
            }
        }
    
        class Sub extends Base {
            public void doStuff(Map map) {
            }
        }
    
  1. 后置条件可以被缩小

增强类的可替换性,则增强了程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。

建议149:依赖抽象而不是实现★★☆☆☆

在面向过程开发中,我们考虑的是如何实现,依赖的是每个具体实现,而在OOP中,则需要依赖每个接口,而不能依赖具体的实现,比如我们要到北京出差,应该依赖交通工具,而不是依赖的具体飞机或火车,也就是说我们依赖的是交通工具的运输能力,而不是具体的一架飞机或某一列火车。这样的依赖可以让我们实现解耦,保持代码间的松耦合,提高代码的复用率,这也是依赖倒置原则(Dependence Inversion Principle,简称DIP)提出的要求:

  1. 高层模块不应该依赖低层模块,两者都应该依赖其抽象。
  2. 抽象不应该依赖细节。
  3. 细节应该依赖抽象。

依赖倒置原则在Java语言中的表现就是:

  1. 模块间的依赖是通过抽象发生的,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。
  2. 接口或抽象类不依赖于实现类。
  3. 实现类依赖接口或抽象类。

我们怎么在项目中使用这个规则呢?只要遵循以下的几个规则就可以:

  1. 尽量抽象
  2. 表面类型必须是抽象的
  3. 任何类都不应该从具体类派生
  4. 尽量不要覆写基类的方法
  5. 抽象不关注细节

建议150:抛弃7条不良的编码习惯★★☆☆☆

  1. 自由格式的代码

  2. 不使用抽象的代码

  3. 彰显个性的代码

    “最小惊诧原则”(Principle Of Least Surprise简称POLS,或者Principle Of LeastAstonishment简称POLA),其意是说要使用最常见的,而不是最新颖的功能。

  4. 死代码,冗余代码

    忘记删除的代码或者废弃的代码等

  5. 拒绝变化的代码

    一个在JDK 1.1中就过时的方法还还能在使用JDK 1.6项目中存在,谓之曰“没有坏,就不要去修它”—该重构它了,它没坏,但它赖以生存的环境已经变了!

  6. 自以为是的代码

    相信自己编写的工具类,而不是开源工具,宁愿自己写序列化工具,也不选择kryoprotostuff;宁愿自己写日期处理工具,也不选择Jodadate4j;宁愿自己写批处理框架,也不选择Spring Batch,这样是不行的!—相信天外有天吧,更多更好的工具等待着你去发掘。

建议151:以技术员自律而不是工人★★★★★

下20条建议可以逐步把我们向技术人员方向培养:

  1. 熟悉工具

    军人手中有枪,农民手中有锄头,而我们手里只有Java,这也是我们能够引以为豪的工具,我们应该了解它的使用范围,了解的它的生态系统,了解它的发展趋势—它也可能就是陪伴我们一生的那个工具,也祝愿它是。

  2. 使用IDE

    在技术领域,不要相信“无刀胜有刀”之类的鬼话—“高手都用记事本或VI开发”

  3. 坚持编码

    不要考虑自己的职位、岗位,只要是Java圈子的生物都应该坚持编码,没有编码,就等于是无源之水,无本之木,何来灵感和灵性?

  4. 编码前思考

    在坐下来开始编码之前,必须已经完成设计,最低要求是对开发中遇到的问题有清晰的认识,不要在编码中解决问题。

  5. 坚持重构

    不要相信一次就能写出优秀的代码,这是不现实的,任何优秀的代码、算法都是经过多次重构磨练的,坚信自己的下一个版本或代码更优秀。

  6. 写注释、写说明、写报告都是对代码或项目的回顾和总结,不仅仅是为了后续的参与人员,同时也是为了整理自己头脑中混乱的思维。

  7. 保持程序版本的简单性

    一个项目不要保持多个版本,即使有分支也必须定义出项目合并的条件,或者时间约束,或者目标约束,不可任由版本扩散。

  8. 做好备份

    世界上没有万无一失的事情,不做备份,一旦灾难发生就无挽救的余地了

  9. 做单元测试

    单元测试不仅能增强你的信心,也能给你带来好名声—后续者一看,“哇哦,单元测试写得这么完整,肯定是一个认真、负责的人”。

  10. 不要重复发明轮子

    在项目中使用已经成熟的工具或框架,而不是自己编写。但是如果想共享一个新的MVC框架,那就尽管去重复发明轮子吧,它不是以交付为目的的,而是以技术研究为目标的。

  11. 当按下Ctrl+C的时候,问问自己“我在做什么?拷贝是否是唯一能做的?为什么不能重构一下呢”,不要让大段的代码散落在各处,不要做搬运工,不要做拷贝工,要做技术工。

  12. 让代码充满灵性

    为变量、类、方法起个好听的名字是一个不错的主意,为代码增加必要的注释也是很好的办法,“One Line”能解决一个上百行代码的问题,也是一个优秀的实现。

  13. 测试自动化

    不管是性能测试、单元测试,还是功能测试,想尽办法让它自动化,不要在测试之前手动配置或触发条件,这不够人性化,也同时让代码“汗颜”—本是用来自动执行的,但却被手动设置了条件。

  14. 做压力测试

    不要相信业务人员“最多200个用户使用”之类的话,把业务人员制定的指标扩大3倍,然后再做压力测试。不要迷信自己的代码很健壮,在高并发时只有上帝知道发生了何事,你又怎么能知道?

  15. “剽窃”不可耻

    多看开源代码,学习一下人家是如何编码的,然后经常“剽窃”一下,这也是提高技能的最佳途径,我们不是孔乙己,“剽窃”不可耻。

  16. 坚持向敏捷学习

    不管“敏捷”与“非敏捷”之间的争论有多激烈,敏捷中的一些思想是非常优秀的,例如TDD测试驱动开发、交流的重要性、循序渐渐开发等。

  17. 重里更重面

UI(User Interface)是“面”,Java程序是“里”,客户首先感受到的是“面”,然后才是“里”,要想获得良好的第一印象,那就需要有一个简洁、清晰、便捷的UI,即使“金玉其外败絮其中”,我们也可以继续重构。

  1. 分享

    “独乐乐”不如“众乐乐”,把自己的代码分享出去收获的不仅仅是赞许,还有自己能力的提升—暴露出自己的Bug,在众目睽睽之下修正之,知耻而后勇也。

  2. 刨根问底

    有问题不可怕,可怕的是掩盖,或者虚假掩盖,“哦,这个问题呀,加上这个参数就可以解决了”—这不是解决问题的办法,在答案之后加上“是因为……",这才是解决了问题。

  3. 横向扩展

    Java要运行在JVM、操作系统上,同时还要与硬件、网络、存储交互,另外要遵循诸如FTPSMTPHTTP等协议,还要实现Web ServiceRMIXML-RPC等接口,所以我们必须熟悉相关的知识—扩展知识面,这些都是必须去学习的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容