这是一本被前辈称赞, 另一个马丁的知名著作, 被赋予学习如何写出漂亮代码的教皇级手册, 最近(再)浏览, 有诸多感受.

总结一下就是如果你是新手, 可能看优秀的open source学习更好; 如果你是老手, 可能他说的东西要么你会觉得太啰嗦, 要么你会觉得例子太细节, 太教条, 无法举一反三.

不过一些General的要点思想我摘录了出来, 有些还包括个人的观点, 记录在此, 以备查阅.

  • 勒布朗(LeBlanc)法则, Later equals never
  • 代码如果烂了就会越来越烂, 所谓破窗原理, 以前老是也提过叫代码腐化
  • 命名
    • 命名应该合理, 成员变量不用加前缀, 靠高亮就很好
    • 接口加前缀I也不太好, 不如实现加Imp
    • 方法命名最好使用动词或动词短语
    • 多使用计算机领域的词汇
    • 有时候命名在语境里才有意义, 有时候变量命名也不需要重复语境
  • 函数
    • 函数短小一些比较易懂, 20行内最佳
    • if/else/while代码块封装函数, 只有一行最好 (有点激进?)
    • 一个函数只干一件事情
    • 复杂的switch试图用多态取代, 然后封装在抽象工厂里
    • 同一类型函数命名风格应该一致, 使用描述性的语句描述比难懂的短词更好
    • 一元函数最普遍, 标识函数(参数为boolean)的不如分成两个函数, 二元函数尽可能转换成一元函数
    • 参数太多可能需要封装类了
    • 好名字的函数一般是动词, 或者动词+关键字
    • 函数一般要么做事, 要么回答事, 不可兼得 (其实也不一定, 比如很多返回boolean状态的函数)
    • 推荐使用异常代替错误代码
    • 最好将try/catch单独抽入一个函数 (如Android代码会对RemoteService调用进行类似封装, 吃掉exception)
    • 使用枚举表示错误码会让改动变得繁琐 (重新导入或者编译部署), 大家都依赖这个枚举, 应该用异常与继承取代
    • 不要重复, 偶尔可以考虑AOP这类的方法解决
  • 注释
    • 注释少要比注释多有用, 注释多说明代码糟糕 (其实分情况吧)
    • 有目的性的注释还是有用的, 比如阐述, 放大, 警告, 定期维护的TODO等
    • 如果代码不用, 不要注释掉, 直接删掉
  • 格式
    • 横向, 竖向对齐, 间隔, 缩进等. 其实目前formater已经很强大了, 养成良好的format习惯, 渐渐的写出来的代码就会像直接format后一样
  • 对象与数据结构
    • 面向过程与面向对象对立, 前者容易加函数, 不容易加对象, 后者容易加对象, 而不容易加函数
    • 理想情况下, Law of Demeter认为, 类不应该操作对象内部的东西, 如不应该操作函数返回对象的方法. 目的只是为了降低复杂度, 认为这样将私有变量公开化, 增加了重构的难度, 如添加新函数, 方法等, 将数据结构与对象逻辑耦合在一起.
    • 针对于上面的问题, 原则应该是对象暴露行为, 隐藏数据, 数据结构暴露数据
  • 错误处理
    • Java特色的受控异常(Checked Exception), 必须得被catch, 对受控异常的修改会引起上层所有调用方法的改动, 尽量不要使用, 其他语言只有RuntimeException
    • 可以包装第三方逻辑, 封装自己的异常类, 简化为只catch一种异常
    • 简化使用也可以将异常处理完全封装进去, 返回特例即可
    • 轻易不要返回null, 传入null
    • 代码的坚固与干净不冲突, 所以添加一些check, throw相应的Exception也合理
  • 边界
    • 所谓边界就是自己可以控制到的程序与第三方的边界, 通常需要通过封装的办法来划清边界, 限制那些无法控制的第三方, 如直接Wrapper或者Adapter模式等
  • 单元测试
    • 测试需要整洁, 需要跟随代码一起更新, 测试的最大用途是保证你后续的修改有信心
    • 测试的整洁主要讲的是可读性, 即分为三个环节, build->operate->check, 可以把繁杂的准备封装起来
    • 测试API是渐渐重构演进过来的, 也不可能是起初就设计出来
    • 有人建议每个测试一个assert, 但是这样会有很多重复的代码, 不过可以利用Template Method来解决. 不过也不一定必须一个, 做到最小化就可以了
    • 整洁还有五条规则, Fast, Independent, Repeatable, Self-Validation, Timely
    • 这里讲到TDD的好处, 主要是帮助你覆盖更多的测试, 如果写完再测, 发现测不了, 就不写了.
    • 类应该短小, 权责应该足够单一, 内聚性应该高
    • 如果期望抽走一部分逻辑, 最好连相关函数参数也抽走
    • 简化类的过程应该小步, 每一步都运行测试一下
    • 类的精简是为了更好的体现开闭原则, 整体结构为修改而设计
    • 类应依赖于接口, 不依赖实现, 可以隔离修改, 符合依赖倒置原则, 类似策略模式
  • 系统
    • 构造与使用分开, 通过依赖注入等
    • 通过AOP, Proxy的方式, 无侵入性的插入逻辑
    • 系统如果充分模块化, 领域之间相互直接松耦合, 最为理想, 就可以通过测试来驱动
    • DSL的使用可以平衡领域与技术
  • 迭代
    • 代码是在不断迭代中进步的, 比如通过抽函数, 运用设计模式等
  • 并发
    • 应该尽可能分离并发代码与其他代码
    • 尽可能让线程之间独立, 不要有共享
    • 线程模型有典型的生产者与消费者, 读者与作者, 宴席哲学家模型, 分别用来说明互斥, 读写, 竞争死锁等特例
    • 锁定代码块应该尽可能小
    • 线程最好可插拔, 遵循单一权责, 分离线程与其他代码, 测试先保证除线程之外的逻辑
    • 最后一张通过实例来介绍并发代码如何重构的比较清晰
  • 逐步改进
    • 这片使用了一个例子, 先采用蛮干进行重构发现越来越难, 后来采用逐步的办法, 还写的很细节, 但是比较Tricky的地方是, 这里提出的每步改动都通过测试来印证, 然后保证测试通过, 或者补充一个测试, 让代码通过, 但是所谓TDD部分只有思想, 老代码既然写的不好, 测试是如何出来的, 如何做到Cover全的. 如果假设在一个有比较好测试覆盖的基础上重构, 我感觉即便蛮力也不会太差...
  • JUnit
    • 比较神奇的一章, 感觉更像是用一个算法类的重构来说明如何把代码改简单, 但是开头先介绍了100%覆盖的Junit测试长什么样子... 感觉作者是想说以前的人做的还不错, 都用JUnit给覆盖全了, 还是可以重构的更漂亮的, 所以感觉标题不太好
  • 重构SerialDate
    • 跟上一个对比, 这个测试覆盖不全, 所以在补测试的过程中进行重构, 还发现了缺陷, 又最终把代码改清晰了. 不过同样由于太过细节, 一些重构理论也很教条, 如果想通过看别人重构的例子来学习如果写简洁的代码, 不如直接看优秀的代码是怎么写的
  • 味道
    • 里面类比了很多Bad Smell, 同样是很细节, 比如太多, 太死, 太复杂, 重复, 不一致, 耦合, 测试不足等, 提供的Tips大多的中心思想就是抽, 封装, 单一职责, 命名清晰
    • 提到使用*来避免过长import, 不过这个与现在流行的lint检测违背, 可以因为以前都是手动, 通配符简单吧.
    • 不要通过继承来使用常量, 还提到不要用静态常量, 用枚举, 这个也与当前的思想有出入, 现在经常将Java的enum太冗余, 不必要时可以用常量

Refresh Clean Code的更多相关文章

  1. Writing Clean Code 读后感

    最近花了一些时间看了这本书,书名是 <Writing Clean Code ── Microsoft Techniques for Developing Bug-free C Programs& ...

  2. 说说怎么写clean code

    前两天参加了公司组织的一个培训,主题是“如何写出好的代码” ,刚看到这个主题,第一反应是又不知道是哪个培训机构来忽悠钱的!老大安排了,就去听听呗. 说实在的,课程内容没有什么新鲜的东西,就是讲讲如何发 ...

  3. 小课堂week13 Clean Code Part2

    Clean Code Part2 对象与数据结构 首先让我们进行一个严肃的思考,对象与数据结构的区别在哪里? 如下两段代码分别用数据结构和对象的方法来描述了一个Point. public class ...

  4. 小课堂Week12 Clean Code Part1

    小课堂Week12 Clean Code Part1 今天的主题是函数,让我们看一个函数,找一找其中的"不整洁". 我们也根据这段代码,讨论下对于整洁代码的两个重要原则. publ ...

  5. “Clean Code” 读书笔记序

    最近开始研读 Robert C.Martin 的 “Clean Code”,为了巩固学习,会把每一章的笔记整理到博客中.而这篇博文作为一个索引和总结,会陆续加入各章的笔记链接,以及全部读完后的心得体会 ...

  6. Clean Code–Chapter 7 Error Handling

    Error handling is important, but if it obscures logic, it's wrong. Use Exceptions Rather Than Return ...

  7. Clean Code – Chapter 4: Comments

    “Don’t comment bad code—rewrite it.”——Brian W.Kernighan and P.J.Plaugher The proper use of comments ...

  8. Clean Code – Chapter 3: Functions

    Small Blocks and Indenting The blocks within if statements, else statements, while statements, and s ...

  9. Writing clean code is what you must do in order to call yourself a professional.

    Clean Code  A Handbook of Agile Software Craftsmanship

  10. 《Clean Code》 代码简洁之道

    作者介绍 原文作者: Robert C. Martin, Object Mentor公司总裁,面向对象设计.模式.UML.敏捷方法学和极限编程领域的资深顾问,是<敏捷软件开发:原则.模式.与实践 ...

随机推荐

  1. Redis原理学习:Redis主体流程分析

    转自:七把刀 https://www.jianshu.com/p/427cf97d7951 网上分析Redis源码的文章挺多,如黄健宏的<Redis设计与实现>就很详尽的分析了redis源 ...

  2. sklearn学习笔记之线性回归

    AI时代扑面而来,在大众面对ChatGPT和Sora发出无数惊叹号的时候,我决定不再只当一个AI时代的API调用者,而是去学习机器学习技术本身. 刚好公司也要往人工智能方向发展的计划,于是我开始从基础 ...

  3. Windows系统下的输入法选择

    总共用过5款输入法:搜狗拼音输入法,QQ拼音输入法,谷歌拼音输入法,手心输入法,小狼毫. 搜狗输入法功能最强大,词库也很全,基本上对于盲打的输入纠错很准确,但是因为后台会启动多个服务,会占很多内存资源 ...

  4. pymysql基本语法,sql注入攻击,python操作pymysql,数据库导入导出及恢复数据---day38

    1.pymysql基本语法 # ### python操作mysql import pymysql ''' # ### 1.基本语法 #(1) 创建连接 host user password datab ...

  5. django学习第十三天--自定义中间件

    jquery操作cookie 下载地址 http://plugins.jquery.com/cookie/ 引入 <script type="text/javascript" ...

  6. 【Azure 应用服务】App Service下部署的应用报错 Out of Memory

    问题描述 应用部署到App Service后,遇见了Out of Memory的错误. 报错信息:GetData  Error:, Exception of type 'System.OutOfMem ...

  7. linux基本文件命令复习笔记

    https://www.bilibili.com/video/BV1ex411x7Em/?p=4&spm_id_from=pageDriver&vd_source=92305fa48e ...

  8. Java 多线程------测试 Thread中的常用方法 + 线程的优先级:

    1 package com.bytezero.threadexer; 2 3 import javax.sound.midi.Soundbank; 4 5 /** 6 * 测试 Thread中的常用方 ...

  9. Win10系统winload.efi丢失或损坏怎么办?修复步骤(以联想笔记本为例)

    winload.efi是通过UEFI方式引导必要的引导文件,如果系统中丢失或是损坏将导致系统无法启动,如win10在出现这样的问题时会出现蓝屏恢复界面,那么此时该如何解决呢?此例为 GPT+UEFI ...

  10. spring 注入参数时为list map写法用例

    导包基础:这了让服务器支持json 需要导入下面包 <dependency> <groupId>com.alibaba</groupId> <artifact ...