Code Review

CR 可以让每次提交代码都在使仓库变的更好

  1. 在需求提交前发现 bug
  2. 代码分享和知识交流
  3. 利于团队,每个人都对整个项目熟悉,避免个别需求和个别人的强绑定

checklist

  • 是否已有现成代码可复用后扩展已有代码
  • 是否可以进一步抽象封装
  • 是否移除了调试代码
  • 是否可以进一步拆分 MR
  • commit 描述是否足够清醒
  • 是否添加必要注释
  • 命名是否合理
  • 是否有安全问题
  • 是否有坏味道
  • 是否有必要的自动化测试

在 CR 之前要提前执行自动化审查

  • 代码规范检查
  • 代码复杂度检查
  • 自动化测试

readability key point

  1. 代码组织
    1. 文件命名要有一致性,即合理通用的代码目录组织及命名
    2. 泛化问题:工具函数、常量应该合理的归类拆分、便于理解。避免命名过于宽泛,形成垃圾桶文件,把所有的公用函数都堆积到一个代码文件内管理
    3. 代码组织顺序不符合阅读顺序,核心内容上提,私有类和方法下移
    4. 变量的声明和变量的使用尽量在一起,便于阅读,合理使用换行对函数进行分块
    5. 类成员按照以下顺序排序
      1. static > instance
      2. field > constructor > method
      3. public > protected > private
  2. import & export
    1. 不要importrequire混用,推荐使用 ESM
    2. 同一个文件不要多次import
    3. 未使用的import需要被清理
    4. import不要推荐相对路径、推荐使用 alias,设计要有一致性和可读性,如果引用的是当前目录及子目录文件可以使用相对路径
    5. import顺序:node 内置模块 -> npm 包 -> 本地文件,每个类型之间加空行
    6. import外部依赖命名语义不明确的情况要适当添加注释
    7. 不推荐使用export default导出,因为引用人可以进行重命名、如果使用类名应该和文件名一致
  3. 命名
    1. 不要使用关键字命名变量、避免和知名库方法命名重复
    2. const let var
    3. 命名格式
      1. 文件命名使用kebab-case(烤串命名法),单词全小写,以中横线分隔
      2. Class 和组件使用PascalCase(帕斯卡命名法),单词相连,单词首字母大写
      3. 模块作用域内:
        1. 变量、常量、函数使用camelCase(驼峰命名法),单词相连,第一个单词首字母小写,其他单词首字母大写
        2. export的常量使用UPPER_CASE,单词全大写,使用下划线分隔
    4. 有意义的命名:文件、函数、类命名要有意义、保持一致性、避免无意义的前后缀
      1. 布尔类型变量命名使用:is|should前缀
      2. 避免无意义后缀,例如函数名包含Func后缀
      3. 函数名、参数名和返回结果命名命名要匹配,例如:const user = getUserInfo()user改成userInfo和函数名一致会更有可读性
    5. class 变量要明确声明变量的publicprivateprotected
  4. 语法问题:
    1. 要使用模板字符串实现字符串拼接
    2. 添加判断要使用===,不要使用隐性类型转换
    3. 函数参数变量保护可以直接使用函数默认参数实现,例:args = args || {}
    4. 使用 optional chaining(?.)可选链接操作符替换传统的||
    5. 使用箭头函数替代bind实现外层this绑定
    6. 使用管道(filtermap)替代for,这样不容易产生很大的循环操作,根据应用场景(过滤、查找、轮询)选择适合的方法
    7. typescript 函数要声明返回值类型,如果代码可能存在中断(主动退出,或者抛出错误情况)的情况返回类型要包含never
    8. 优先使用异步函数替换 callback 和 promise
    9. 使用new Promise()要注意resolve()reject()是否正确使用,异常如果直接return就会导致这个 promise 实例一直处于 pending 状态。
    10. 禁止使用位运算符,可读性差,可以使用Set实现
  5. 函数设计
    1. 单一职责,一个函数只做一件事,例:一个函数根据某个 Boolean 参数来执行两段不同路径,可以将这两段逻辑拆分成两个独立函数。这也是处理过大函数的一种方式,也可以提升代码的可测性。
    2. 如果函数内有副作用,需要注意函数命名,能够体现包含的副作用
    3. 参数
      1. 函数参数要使用 object 类型,方便扩展,便于调用方通过参数名理解参数的含义
      2. 参数范围要尽量小(精准),不要将全部参数一次性全部传入,例如 react 中直接传入全部 props 或 states
    4. 异常优先,边界问题优先,优先处理异常逻辑,可以降低代码缩进、缩小代码块长度
    5. 要对过大函数进行拆分
      1. 阶段拆分:每个函数内部只处理同一层面的逻辑,如果有更深一级的代码,则将更深一级代码提取成单独函数并在当前函数调用
      2. 循环拆分:牺牲执行效率,提升代码可读性,将一次循环内要处理的多项任何拆分在多个循环,每个循环只处理一项任务
      3. 卫语句优化 if 嵌套过深问题,和异常优先原则契合
      4. 卫语句会导致函数过长,可以将复杂 if 条件提取成函数,可以通过函数名理解判断逻辑
  6. 代码设计
    1. 不能使用改变全局对象管理数据、可以使用 redux 等状态管理工具进行管理
    2. 业务代码里面不应该包含功能代码,应该首先对功能代码进行封装,例:通过网络请求获取信息,不应该在具体的业务代码中处理网络请求功能,应该对网络请求进行、网络异常、业务状态码异常进行封装
    3. 避免魔术字符串等硬编码行为,应该使用枚举的方式组织、给每一个状态码设置有意义的名字,并且合理的分类规划 namespace
    4. 避免硬编码,例如:邮件地址、可选项等类型信息要提取配置
    5. 尽量避免使用this,需要使用到this的位置可以封装单独函数,直接调用函数将需要的变量传入函数中。
    6. 类似链接初始化等只需要执行一次的函数,不应该在业务函数内部处理,可以采用单利模式封装,或者使用once等装饰器实现
  7. React
    1. React 使用箭头函数替换 bind 绑定
    2. 未使用 this 的函数不适应作为成员函数存在,可以提前单独提取
    3. 使用 react 不用进行 dom 操作
  8. 其它
    1. max-length,避免单行过程导致需要横向滚动查看
    2. 注释:添加合理注释、删除无意义注释代码
    3. 换行:合理使用换行,段落化代码,避免无意义换行
    4. 删除调试代码console
    5. window.xxxStorageJSON.parse等方法的调用需要使用try catch语句进行保护
    6. 不能使用setTimeout进行执行顺序控制
  9. libs
  10. 样式处理,styled component > className > 自己拼接 class

results matching ""

    No results matching ""