美文网首页
CleanCode学习笔记

CleanCode学习笔记

作者: 左心Chris | 来源:发表于2019-10-15 20:00 被阅读0次

1 Intro

2 命名

确定统一,可读搜索,类名方法,专业语境

  • 确定性 如计量对象和计量单位 daysSincesCreation fileAgeInDays elapsedTimeInDays
  • 避免误导 accountList可能不是list,用accountGroup或则bunchOfAccounts代替;小心使用不同地方较小的名称;1和0和l和O区分
  • 有意义的区分 如source和destination,有些如a the Data Info variable string就是废话
  • 使用读的出来的名称
  • 使用可搜索的名称
  • 避免Encodings ? 如果有
    1 匈牙利标记法 首字母体现类型不需要,因为当代语言有类型检查,而且可能造成误导
    2 成员前缀 m_也不需要
    3 接口和实现 接口ShapeFactory 实现是ShapeFactoryImp或者 CShapeFactory ?
  • 避免思维映射 明确,比如把r自己映射为小写url
  • 类名 名词或者名词短语
  • 方法名 动词或者动词短语;属性访问器,修改器,断言用get, set, is 前缀
    ? 重载构造器时,使用描述了参数的静态工厂的方法名
  • 每个概念对应一个词 如controller, manager, driver或者fetch, receive, get
  • 别用双关语 add,insert,append
  • 使用解决方案领域名称或者源自所涉及的问题的名称
  • 添加有意义的语境,不要没用的语境 需要良好命名的类,函数或者名称空间来添加语境

3 函数

确定单一,输入输出,查改分离,参数异常

  • 短小
  • 只做同一抽象层级的事
  • 每个函数一个抽象层级
  • switch语句 用多态把不同switch语句用同一个接口实现
  • 使用描述性的名称 isTestable 和 inclueSetupAndTeardownPages, includeSetupPages
  • 函数参数 调用的时候参数越少,顺序有可能判断错,如果太多封装为类
    • 一元参数 问跟这个参数的问题,或者转化这个参数,还有事件有输入无输出
    • 标识参数 如果传入标识参数,表明这个函数会做两件事,true做一件,false做一件
    • 二元函数 顺序问题,可以这样:outputStream.writeField(name) 或者把outputStream写为类成员变量,避免writeField(outputStream, name),python还好
    • 三元函数 封装为类
    • 参数列表 可变参数列表在最后,函数可能是一元,二元或三元,超过可能有问题
  • 无副作用 函数只干一件事,不要做函数名没有声明的事
  • 输入输出 避免使用输出作为参数传入 ,如appendFooter(s) 而改为 report.appendFooter()
  • 分割指令和询问 if (attributeExist()) {setAttribute()}
  • 使用异常替换返回错误码
    • try {} catch (Exception e) {logger.log(e.getMessage())}
    • 抽离 try/catch 代码块 ?try {function()} catch (Exception e){ logError(e)} function() throws Exception {}
    • 错误处理就是一件事 try在函数就是函数的第一个单词,catch/finally 后面没有内容
    • 使用异常代替错误码 这样异常继承异常类不像改错误码类一样,更改就得重新构建部署
  • 避免重复,结构化编程(一个入口一个出口,没有break,continue,goto),迭代开发

4 注释

代码是最好的注释
好注释和坏注释

  • 因为代码一直在变化,但是注释不是一直在演进,所以代码是最好的注释
  • 好注释
    • 法律信息
    • 信息的注释,意图的解释,阐释(翻译复杂的参数或者返回值),警示
      3 TODO注释,放大重要性,公共api中的javadoc
  • 坏注释
    • 想好的注释再写
    • 多余的注释(代码跟注释表示一种意思),尽量用函数和变量来表明名字
    • 误导性注释,不明确的注释,过多的注释
    • 循规注释(每个函数都有javadoc)
    • 日志式注释 (已经有版本控制系统不需要了)
    • 位置标记,括号后面的注释,归属与署名
    • 注释掉的代码,HTML注释,应该确保描述了离它最近的代码,非公共代码中javadoc

5 格式

统一的格式沟通
垂直格式和横向格式

  • 格式关乎沟通
  • 垂直格式
    • 大多数200行,最多500行
    • 跟报纸学习,先头条,后大纲,后细节;自顶向下,垂直顺序
    • 概念垂直方向用空格间隔,在封包声明,导入声明和每个函数之间
    • 垂直方向上的靠近,接近的变量不要用注释或者其他隔开了
    • 垂直距离 相近的靠近有序
      • 变量声明:函数或类顶部或者底部
      • 实体变量:java类的顶部,c++类的底部
      • 相关函数:调用者应该在被调用者的上面
      • 相关概念:相关相近
  • 横向格式
    • 45个字符左右 40%,10个字符以下 30%
    • 水平方向上 用空格隔离或者靠近
    • 水平对齐和缩进方法和空范围

6 对象和数据结构

数据和对象,对应成员和方法
过程式代码和面向对象代码

  • 数据抽象:
    • 对象把数据隐藏在抽象之后,暴露操作数据的函数
    • 数据结构暴露其数据,没有提供有意义的函数
  • 反对称性
    • 过程式代码(只使用数据结构)便于不改动数据结构的情况下,添加新函数
    • 面向对象代码,便于不改动既有函数的情况下,添加新的类
    • 反之亦然
  • Law of Demeter
    • 模块不应了解它所操作对象的内部情况
    • 如果ctxt是数据结构,自然会暴露内部细节,如果是对象,就不应该
    • 不要混杂:既有执行操作的函数,又有公共变量或公共访问器及改值器
  • 数据传送对象
    • 即数据结构和Active Record
    • 不要把这种数据结构当对象使用

7 错误处理

  • 使用异常,并用try catch finally
  • 使用unchecked异常,符合开闭原则
  • 环境说明,异常封装,特例模式,null值处理

8 边界

  • 使用第三方代码,封装起来,构建边界,只暴露需要的功能
  • 学习性测试,和使用尚不存在的代码,先自己根据业务逻辑定义,先写伪对象测试,等代码实现完之后用adapter封装与api的互动
  • 两种方式:封装;adapter模式(接口桥梁)

9 单元测试

  • TDD测试生产重构,整洁测试:构造操作检验
  • 测试可读性,每个测试一个概念(可以用模板模式分离多个断言,共有的变为基类)
  • FIRST

10 类

  • 类单一职责(只有一条修改的理由);内聚(少量变量,每个方法尽可能用到这些变量)
  • 修改最好少修改(或者打开类),多添加;通过依赖于抽象来实现隔离修改

11 系统

  • 全局设置策略,构造与使用分开
  • main通过Builder构造对象,然后application使用这个构造的对象;main传抽象工厂实现类对象给application,application然后用抽象类保存实现多态,将构造细节隔离在应用程序之外
  • Ioc模式,依赖倒置(上层和下层模块都依赖于抽象),控制反转,依赖注入(上层模块使用哪个具体,通过配置文件或者容器传入或者特殊的构造模块)
  • AOP,把相同类型的流程抽出来,用依赖注入(如xml)动态的增添代码;
  • 代理模式,通过代理对象访问实际对象;装饰模式,两个类实现同一接口,一个类包含另一个类,再加上其他方法或者成员进行装饰
  • 最佳的系统架构由模块化的关注面组成,不同领域通过类或者其他整合起来;模块化和关注面切分
  • 合理使用现有标准,领域特定代码DSL能填平领域概念和实现领域概念

12 迭进

  • 运行所有测试,测试消除改代码的恐惧
  • 重构包括:不重复(模板模式,抽象类有一个方法是final,所有的子类都这样做),表达清晰,尽可能少的类和方法

13 并发编程

  • 原则:单一权责
  • java ConcurrentHashMap/ ReentrantLock/ Semaphore/ CountDownLatch
  • 执行模型:生产者消费者,读者作者,宴席哲学家
  • 互斥,线程饥饿,死锁,活锁
    14 逐步改进

相关文章

网友评论

      本文标题:CleanCode学习笔记

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