美文网首页
代码整洁之道-要点记录

代码整洁之道-要点记录

作者: kaiker | 来源:发表于2023-06-22 16:56 被阅读0次

    第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() 除非里面有数据结构类,否则不应该传递。

    名称

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

    测试

    • 全面测试相近的缺陷
    • 测试失败的模式有启发性

    相关文章

      网友评论

          本文标题:代码整洁之道-要点记录

          本文链接:https://www.haomeiwen.com/subject/owptydtx.html