代码整洁之道-要点记录

第2章 有意义的命名

  • 名副其实
  • 避免误导
  • 有意义的区分。不要有废话,不要有仅靠数字的标识,名称之间有区分度。
  • 名称长端应与其作用域大小相对应。
  • 给每个抽象概念选一个词,并且一以贯之。
  • 只要短名称足够清楚,就比长名称好。

第3章 函数

  • 短小,更短小。
  • 只做一件事。
  • 语句要在同一抽象层上。
  • 函数参数尽量不超过2个;不要有标识参数。
  • 无副作用。
  • 使用异常替代返回错误码。
  • 最好把try catch代码的主题部分抽离形成另一个函数。错误处理就是一件事。
  • 不要重复。

第4章 注释

  • 用代码来阐述而不是用注释
  • 好注释:提供信息、对意图的解释、警示、TODO
  • 坏注释:多余、误导、不必都包含javadoc、日志式、废话、信息过多、包含的联系并不明显
  • 能用函数或变量表达含义就别用注释
  • 注释掉的代码,不应该存在。

第5章 格式

  • 垂直格式:概念间垂直方向上间隔、变量声明应尽可能靠近其使用位置、函数间调用则最好将函数放在相近位置
  • 横向格式:使用空格将紧密事物连接到一起,也将相关性较弱的事物区隔开。

第6章 对象和数据结构

  • 我们不愿意暴露数据细节而更愿意以抽象形态表述数据
public interface Vehicle {
    double getFuelTankCapacityInGallons();
    double getGallonsOfGasoline();
}

public interface Vehicle {
    double getPercentFuelRemaining();
}
  • 过程式代码便于在不改动既有数据结构的前提下添加新函数;面向对象代码便于在不改动既有函数的前提下添加新类。
  • 模块不应了解它所操作对象的内部情形,不过如果是数据结构,可能会了解。
  • 对象暴露行为,隐藏数据,便于添加新对象类型而无须修改既有行为,同时难以在既有对象中添加新行为;数据结构暴露数据,没有明显行为,便于向既有数据结构添加新行为,同时难以向既有函数添加新数据结构。

第7章 错误处理

  • 某种意义try代码块就像是事务,catch代码块将程序维持在一种持续状态。
  • 已检查的代价就是违反开闭原则,使用未检异常RuntimeException
  • 不返回null值,也不传递null值
  • 在业务逻辑和错误处理代码之间有良好的区隔

第8章 边界

  • 避免从公共API中返回边界接口,或将边界接口作为参数传递给公共API
  • 例如在系统中不受限制地传递Map<String, Sensor>的实体,以为着当Map接口被修改时,有许多地方都要跟着改。
// 这样能稍微好一点
publc class Sensors {
    private Map sensors = new HashMap();
    public Sensor getById(String id) {return (Sensor) sensors.get(id);}
}
  • 编写测试来遍览和理解第三方代码。
  • 边界上的代码需要清晰地分割和定义了期望的测试。应该避免我们的代码过多地了解第三方代码中的特定信息。

第9章 单元测试

  • 测试直达,只用到那些真正需要的数据类型和函数。
  • 每个测试函数中只测试一个概念。
  • FIRST原则,快、独立、可重复、自足验证(有布尔值输出,不应该通过查看日志文件来确认是否通过)、及时

第10章 类

  • 单一权责,类或模块应该有且只有一条加以修改的理由
  • 如果一个类中的每个变量都被每个方法所使用,则该类具有最大的内聚性
  • 保持内聚性就会得到许多短小的类
  • 为了修改而组织,对类加以组织,降低修改的风险。依赖接口而不是依赖实现。

第11章 系统

  • 将系统的构造与使用分开,每个应用程序都应该留意起始过程 (工厂)
  • 扩充,提到了代理、AOP
  • 最佳的系统架构由模块化的关注面领域组成,每个关注面均用纯Java对象实现。不同的领域之间用最不具有侵害性的方面或类方面工具整合起来。
  • 延迟决策至最后一刻也是好手段。

第12章 迭进

  • 通过迭进设计达到整洁目的。
  • 运行所有测试
  • 递增式地重构代码
  • 不可重复
  • 表达了程序员的意图
  • 尽可能减少类和方法的数量。

第13章

并发防御原则

  • 分离并发相关代码与其他代码
  • 限制临界区数量
  • 使用数据副本避免共享数据
  • 线程应尽可能地独立。每个线程处理一个客户端请求,从不共享的源头接纳所有请求数据,存储为本地变量。

警惕同步方法之间的依赖

  • 避免使用一个共享对象的多个方法

保持同步区域微小

  • 尽可能减小同步区域

很难编写正确的关闭代码

  • 尽早考虑关闭问题,尽早另其工作正常

测试线程代码

  • 偶发失败都需要注意,最好假设偶发错误根本不应该存在
  • 不要同时追踪非线程缺陷和线程缺陷。
  • 编写可插拔的线程代码,在不同的配置环境下运行
  • 允许线程数量可调整
  • 运行多余处理器或处理器核心数量的线程
  • 装置代码,增加对Object.wait() Object.sleep()等方法调用,改变代码执行顺序测试并发代码中的缺陷。

第14章

  • 毁坏程序的最好方法之一就是以改进之名大动其结构。
  • 每次修改都必须保证系统能像以前一样工作。

第17章 味道与启发

注释

  • 不恰当的信息
  • 废弃的注释
  • 冗余注释
  • 注释代码

环境

  • 需要多步才能实现的构建
  • 需要多步才能做到的测试

函数

  • 过多地参数
  • 输出参数
  • 用作标识的参数
  • 死函数

一般性问题

  • 重复
  • 不正确的边界行为。别依赖直觉,追索每种边界条件,并编写测试。
  • 在错误的抽象层级上的代码。创建分离较高层级一般性概念与较低层级细节概念的抽象模型。
  • 基类依赖派生类
  • 信息过多。限制类或模块中暴露的接口数量。
  • 垂直分隔。 变量和函数应该靠近被使用的地方定义。
  • 前后不一致。命名、约定保持一致。
  • 人为耦合。 不互相依赖的东西不该耦合。
  • 特性依恋。类的方法只应对其所属类中的变量和函数感兴趣,不该垂青其他类中的变量和函数。
  • 晦涩的意图。
  • 位置错误的权责。
  • 不恰当的静态方法。静态方法应当只在当个实体上操作,不在任何特定对象上操作。
  • 理解算法,而不是使用大量的if else
  • 把逻辑依赖改为物理依赖,依赖者模块不应该对被依赖者模块有假定,它应当明确地询问后者全部信息。
public class HourlyReporter {
    private HourlyReportFormatter formatter;
    private List<LineItem> page;
    private final int PAGE_SIZE = 55; // 这是假定知道页面尺寸,是一种逻辑依赖。可以改成getMaxPageSize()的新方法来物理化依赖。
    
    public HourlyRepoter(HourlyReportFormatter formatter) {}
}
  • 用多态替代if else
  • 用命名常量替代魔术数
  • 准确。确认自己足够准确。明确自己为何要这么做。
  • 封装条件。把解释了条件意图的函数抽离出来。
  • 避免否定性条件。
  • 函数值该做一件事。
  • 掩蔽时序耦合。有必要使用时序耦合时,不应该掩蔽它。
  • 封装边界条件。 把处理边界条件的代码集中到一处。
  • 函数应该只在一个抽象层级上。
public String render() throws Exception {
    StringBuffer html = new StringBuffer("<hr");
    if (size > 0) html.append(" size=\").append(size + 1).append("\");
    return html.toString(); 
}

public String render() throws Exception {
   HtmlTag hr = new HtmlTag("hr");
   if(extraDashes > 0) hr.addAttribtue("size", hrSize(extraDashes));
   return hr.html();
}
  • 在较高抽象层级的默认常量或配置值,不要将它埋藏到较低层级的函数中。
  • 避免传递浏览。 a.getB().getC() 除非里面有数据结构类,否则不应该传递。

名称

  • 采用描述性名称
  • 名称应与抽象层级相符
  • 无歧义名称
  • 为较大作用范围选用较长名称
  • 避免编码

测试

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

推荐阅读更多精彩内容