美文网首页js css html
代码整洁之道读书笔记

代码整洁之道读书笔记

作者: lieon | 来源:发表于2022-11-30 13:27 被阅读0次

    命名

    • 名副其实:避免出现命名模糊,应做到见名知其意
    // bad naming
     func getThem() -> [Int] {
            var list: [Int] = []
            for x in 0...99 {
                list.append(x)
            }
            return list
      }
        // good naming
       func getFlaggedCells() {
            var cells: [Int] = []
            let gameBoard = 0...99
            for cell in gameBoard {
                cells.append(cell)
            }
            return cells
        }
    
    • 避免误导: 比如前后拼写不一致
    /// bad
    func testName() {
            var a = 1
            let o = 1
            let o1 = 2
            let I = 2
            if o == 1 {
                a = o1
            } else {
                I = o1s
            }
        }
    
    • 做有意义的区分,读者能够通过命名就能分别出两个方法之间的区别
    • 使用读得出来的名称,不要造词


    • 使用可搜索的名称,比如避免使用magic number


    • 不推荐使用成员前缀
    • 避免思维映射:不应当让读者在闹中把你的名称翻译为他们熟知的名称
    • 类名:类名应该是名词,不应当时动词
    • 方法名:应当是动词或者动词短语,eg: postPayment, delelePage
    • 避免同一个单词用于不同目的
    • 使用用专业术语命名
    • 添加有意义的语境:主要用于拆分大函数

    函数

    • 目标:如何构建让读者一看就明白的函数
    • 短小:函数的第一个规则就是短小
    • 一个函数只做一件事:函数应该值做一件事,做好这件事,只做一件事。判断一个函数是否只做了一件事:就是看是否能够再拆出一个函数。
    • 使用描述性的名称定义函数
    • 函数参数:最理想的是零参数,其次是一个参数,两个参数,。。。如果要函数要对输入参数进行转换操作,转换结果就该体现为返回值
    • 标识参数:标识参数丑陋不堪。reader(Boolean isSuite) 可以写为renderForSuite()和renderForSingleTest()
    • 二元函数(两个参数的函数):可以使用一些机制将其转换为一元函数 writeField(outputStream, name) => outputStream.writeField(name)
    • 三元函数(三个参数):应转换为参数对象
    • 参数对象:函数中有三个及以上的参数,应将他们封装为对象
    • 动词与关键字:函数和参数应当形成一种非常良好的动词/名词对形式
    • 无副作用:一个函数只做一件事,eg:一个做加法的函数,却在函数内部修改了全局变量
    • 分隔指令与询问:指令与询问分隔开来,防止混淆的发生
    // 错误的
    if (set("username", "bob")) ...
    
    // 正确的
    if (attributeExist("username") {
      setAttribute("username", "bob")
    }
    
    • 使用异常替代返回错误码
    • 抽离tryCatch代码块
    • 错误处理就是一件事:错误处理的函数只做错误处理,不做其他事
    • 别重复自己:比如避免类似于这种写法:Setup ,SuiteSetup, TeadDown, SuiteTearDown
    • 结构化编程

    注释

    • 注释不能美化糟糕的代码:带有少量注释的整洁而有表达力的代码,要比带有大量注释的零碎而复杂的代码像样得多,不能因为代码很糟糕而通过写注释来解释
    • 有代码来阐述:很多时候,简单到只需要创建一个描述与注释所言同一事物的函数即可
    • 好注释包含哪些:
      • 法律信息
      • 提供信息的注释
      • 对意图的解释
      • 阐述:注释某些晦涩难明的参数或返回值的意义翻译为某种可读形式
      • 警示:用于警告其他程序员会出现某种后果的注释也是有用的
      • TODO注释:是一种程序员认为应该做的,但是由于某种原因目前还没做的工作
      • 放大:注释可以用来放大某种看来不合理之物的重要性
    • 坏的注释有哪些:
      • 楠楠自语
      • 多余的注释
      • 误导性的注释
      • 循规式注释
      • 日志型注释
      • 废话注释
      • 位置标记
      • 括号后面的注释:会破坏函数结构
      • 归属于署名:最好使用代码版本控制来处理归属
      • 注释掉的代码:直接把代码删掉即可

    格式

    • 格式的目的:关乎团队沟通,增强代码的可读性,可读性会影响到代码的可维护性和扩展性
    • 垂直格式
      • 决定了代码文件的行数
      • 向报纸学习:头条主题 -> 大纲 -> 概述 -> 故事细节。篇幅:短小精悍,有些稍微有点长,
    • 概念间垂直方向上的区隔
    • 垂直方向上的靠近
    • 垂直距离
      • 变量声明,应尽可能靠近其使用位置
    • 实体变量:应该在类的顶部声明
    • 相关函数:调用者函数应该尽可能放在被调用者上面
    • 概念相关:概念相关的代码应该放到一起,相关性越强,彼此之间的距离就应该越短
    • 垂直顺序
    • 决定了代码的宽度
    • 横向格式:代码行长度控制在100到120个字符之间
    • 水平方向的区隔与靠近
    • 水平对齐:推荐不水平对齐,不推荐C++的那种水平对齐方式
    • 缩进:类中的方法相对改类缩进一个层级,方法的细实现相对方法声明缩进一个层级,代码块的事项相对于容器代码块缩进一个层级

    对象和数据结构

    • 数据抽象:不愿保罗数据细节,更愿意以抽象形态表述数据
    • 数据,对象的反对称性
      • 过程式代码便于在不改动既有数据结构的前提下添加新函数,面向对象代码便于在不改动既有函数的前提下添加新类

    错误处理

    • 当错误发生时,程序员就有责任确保代码照常工作
    • 使用异常而非返回码:如果使用返回码:调用者必须在调用之后即刻检查错误,但是这个步骤很容易被遗忘。如果是抛出异常,调用代码就被编译识别出来,不如不处理异常就编译不通过
    • 先写try-catch-finally
    • 使用不可控异常
    • 给出异常发生的环境说明
    • 依调用者需要定义异常类:便于被捕获
    • 别返回null值
    • 别传递null值

    单元测试

    • TDD三定律
      • 定律一:在编写不能通过的单元测试前,不可编写生产代码
      • 定律二:只可编写刚好无法通过的单元测试,不能编译也算不通过
      • 定律三:只可编写刚好足以通过当前失败测试的生产代码
    • 保持测试整洁:测试代码和生成代码一样重要,它需要被思考,被设计和被找了,它应该想生成代码一般保持整洁。测试越脏,代码就会变得越脏。最终,丢了测试,代码开始腐败
    • 整洁的测试
      • 三个要素:可读性,可读性,可读性
      • 测试的三个环节:构造-操作-检验 (BUILD-OPERATION-CHECK)
    • 每个测试一个断言:单个测试中的断言数量应该最小化
    • 每个测试一个概念
    • 最佳规则:应该尽可能减少每个概念的断言数量,每个测试函数只测试一个概念
      • FIRST:
        • 快速Fast:测试应该足够快
        • 独立Independent:测试应该相互独立
        • 可重复性repeatable:测试在任何环境中重复通过
        • 自足验证Self-Validating:测试应该有布尔值输出
        • 及时Timely:测试应及时编写

    • 类应该短小
    • 单一权则原则:类和模块应有且只有一条加以修改的理由
    • 内聚:类应该只有少量实体变量。类中的每个方法都操作一个或多个这种变量,通常而言,方法操作的变量越多,就越粘聚到类上。如果一个类中的每个变量都被每个方法所使用,则该类具有最大的内聚性。
    • 为了修改而组织:在整洁的系统中,我们对类加以组织,以降低修改的风险。在理想系统中,我们通过扩展系统而非修改现有代码来添加新特性
    • 隔离修改:接口代替类

    系统

    • 将系统的构造与使用分开:软件系统应将启动过程和启动过程之后的运行时逻辑分离开,在启动中构建应用对象,也会存在互相缠结的依赖关系
    • 分解main函数:将构造与适使用分开的方法之一是将全部构造过程搬迁到main或称之为main的模块之中。main函数创建系统所需的对象,再传递给应用程序,应用程序只管使用。
    • 工厂:使用抽象工厂模式让应用程雪控制何时创建,但构造的细节却隔离与应用程序之外
    • 依赖注入(DI):分离构造与使用,在依赖管理情景中,对象不应该负责实例化对自身的依赖,应该将这份权责移交给其他”有权力”的机制,从而实现控制的反转
    • 扩容:架构都可以递增式地增长,只要我们持续将关注面恰当地切分
    • 测试驱动系统架构:最佳的系统架构由模块化的关注面领域组成,每个关注面均用纯Java对象实现,不同的领域之间最不具有侵害性的方面或类方面工具整合起来,这种架构能测试驱动,就像代码一样

    迭进

    • 简单设计的四条原则

      • 运行所有测试
      • 不可重复
      • 表达程序员的意图(保证表达力)
      • 尽可能减少类和方法的数量
    • 简单设计规则1:运行所有的测试

      • 全面测试并持续通过所有测试的系统,就是可测试的系统
      • 遵循有关编写测试并持续运行测试的简单,明确的准则,系统就会更贴近低耦合度,高内聚的目标。编写测试引致更好的设计
      • 测试消除了对清理代码就会破坏代码的恐惧
      • 通过实例起到文档作用
    • 简单设计规则2~4:重构

      • 重构过程中,可以应用有关优秀设计的一切知识。提升内聚性,降低耦合度,切分关注面,模块化系统性关注面,缩小函数和类的尺寸,选用更好的名称。
    • 不可重复:重复是拥有良好设计系统的大敌。它代表着额外的工作,额外的风险和额外且不必要的复杂度。

    • 表达力:下一位读代码的人最有可能是自己。选用较好的名称,将大函数切分小函数,时时照拂自己创建的东西。用心是最珍贵的资源

    • 极可能少的类和方法(优先级最低)

    相关文章

      网友评论

        本文标题:代码整洁之道读书笔记

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