实施CR方案的详细指南

3,613 阅读6分钟

1. CR 标准定义

首先并不存在”完美代码“,没有是谁能定义完美代码。我们需要的是更好的代码,追求的是代码库的持续改进。保证前端整体代码的健康状况,可以随着时间的推移,不断得到改善。

2. CL 前置条件

在代码风格方面,采用 @yw/eslint-config 统一代码风格,必须严格遵守。

3. CR 两个核心原则

3.1 持续改进原则

遵循一些原则和最佳实践,以确保代码的质量和可维护性。

3.2 同理心原则

审查代码时尽可能地理解和尊重代码作者的意图和思路,而不是仅仅关注代码的表面问题。

尽可能地提供具体的建议和反馈,而不是简单地指出问题,尊重代码作者的选择和决策,避免过度干预和批评。

4. CR 效率问题

Developer 必须提交改动描述来提高 CR 的效率。

  1. 写好这次改动的描述。
  2. 每次提交小的改动。

Google 建议的格式如下:

第一行:用完整的句子说清楚改动了什么,并跟随一个空行

内容:详细描述这次改动的内容,提供必要的理解这些改动的补充信息,比如究竟解决什么问题,为什么这样改,这样改可能有什么问题。如果可以的话,补充其他的一些背景信息,比如相关的设计文档、bug 修复任务连接等。

举一个好的例子:

引入 prettier 来保证代码格式一致。

之前的项目没有好的代码格式约束工具,不同人写的代码格式相差太大,比如有人喜欢一行很长,有人喜欢很短,有人写代码没有空行,有人喜欢随意加空行。通过引入目前前端最受欢迎的代码自动格式化工具 prettier 来统一项目的代码格式规范。

5. CR 的六个维度

开发人员的意图对这段代码的“用户”有好处吗? 这里”用户“是指受变更影响到的终端用户,和将来会使用到这些代码的开发者。

5.1 可访问性

5.1.1 语义化的 HTML 标签

建议在编写 HTML 代码时尽可能使用语义化的 HTML 标签并让页面的结构保持清晰。

以下是一些常用的语义化标签:

<header>
  <nav>
    <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Contact</a></li>
    </ul>
  </nav>
</header>

<main>
  <article>
    <h2>Article Title</h2>
    <p>Article content goes here.</p>
  </article>
</main>

<footer>
  <p>&copy; 2023 My Website</p>
</footer>

在上面的代码中,<header><nav><ul><li><a><main><article><h2><p><footer> 等标签都是语义化标签,它们的作用分别是页面头部、导航、列表、列表项、链接、主要内容、文章、标题、段落和页脚。

5.1.2 CSS 框架

如果使用类似 Tailwind CSS 这样的框架,建议尽可能使用已定义的类,而不是自定义样式。例如 text-4xl 类来设置标题的字体大小,bg-blue-500 类来设置按钮的背景颜色等等。

<div class="container mx-auto">
    <h1 class="text-4xl font-bold text-center my-8">Welcome to My Page</h1>
    <p class="text-lg text-gray-700 mb-4">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc vel bibendum bibendum, velit sapien tincidunt nunc, vel bibendum sapien sapien vel sapien. Sed euismod, nunc vel bibendum bibendum, velit sapien tincidunt nunc, vel bibendum sapien sapien vel sapien.</p>
    <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Learn More</button>
</div>

5.2 并发编程

当需要同时调用多个接口时,通过使用 异步编程Promise.all()async/await 等技术同时发起多个请求并等待所有请求完成后再进行处理,避免因为串行请求的所耗费的等待时间。

async search() {
  const [result1, result2, result3] = await Promise.all([
    this.searchRequest('query1'),
    this.searchRequest('query2'),
    this.searchRequest('query3')
  ]);
  // 处理搜索结果
},
async searchRequest(query) {
  const response = await fetch(`https://example.com/search?q=${query}`);
  return response.json();
}

5.3 保持简单

避免过度复杂化代码。

  • 简化代码逻辑
  • 避免过度设计
  • 简化数据模型
  • ...

5.4 避免重复

避免代码中出现重复的逻辑和代码。

  • 函数封装
  • 样式复用
  • 数据模型抽象
  • ...

5.5 优雅命名

命名应该清晰、简洁、易读、易懂、易于理解和记忆。

关于方法、变量和样式类命名的建议和示例:

5.5.1 方法命名

  • 使用动词开头,例如:getsetaddremove等。
  • 使用驼峰命名法,例如:getUserInfosetUserName等。
  • 方法名应该清晰明了,能够准确地描述方法的功能。

示例代码:

function getUserInfo() {
  // 获取用户信息的方法
}

function setUserName(name) {
  // 设置用户名的方法
}

5.5.2 变量命名

  • 使用名词或名词短语命名,例如:userInfouserName等。
  • 使用驼峰命名法,例如:userInfouserName等。
  • 变量名应该清晰明了,能够准确地描述变量的含义。

示例代码:

let userInfo = {
  name: '张三',
  age: 18,
  gender: '男'
};

let userName = '张三';

5.5.3 样式类命名

  • 使用有意义的名称,例如:headerfooternav等。
  • 使用连字符分隔单词,例如:header-navfooter-content等。
  • 样式类名应该清晰明了,能够准确地描述样式类的作用。

示例代码:

.header {
  // 头部样式
}

.footer {
  // 底部样式
}

.header-nav {
  // 头部导航样式
}

.footer-content {
  // 底部内容样式
}

5.6 代码注释

  1. 注释应该清晰明了,不要使用过于简略或者晦涩难懂的语言,以免给其他开发者造成困扰。
  2. 注释应该与代码紧密结合,对代码中的关键部分进行解释,如函数、变量、算法等。
  3. 注释应该遵循一定的格式规范,如使用特定的注释符号、缩进等。
  4. 注释应该及时更新,随着代码的修改和演进,注释也需要相应地进行更新。

5.6.1 单行注释

解释代码的某些细节或者提供一些上下文信息。

示例代码:

// 这是一个简单的函数,用于计算两个数的和
function add(a, b) {
  return a + b;
}

// 这是一个使用了回调函数的异步操作,用于下载文件
function downloadFile(url, callback) {
  // 下载文件的代码
  // ...
  // 下载完成后调用回调函数
  callback();
}

5.6.2 JSDoc 注释

用于 JavaScript 代码文档化的标准格式。

示例代码:

/**
 * 这是一个简单的函数,用于计算两个数的和
 * @param a [参数一]
 * @param b [参数二]
 * @returns [返回值]
 */
function add(a, b) {
  return a + b
}

5.6.3 特殊注释(TODO、FIXME)

TODO

用于标记代码中需要完成的部分,通常用于提醒开发者需要完成的任务。会包含任务的描述、优先级、截止日期等信息。

示例代码:

// TODO: Implement login functionality
function login(username, password) {
}

FIXME

用于标记代码中存在问题的部分,通常用于提醒开发者需要修复的问题。包含问题的描述、原因、解决方案等信息。

示例代码:

// FIXME: This code is not working properly
function calculateSum(arr) {
  let sum = 0;
  for (let i = 0; i < arr.length; i++) {
    sum += arr[i];
  }
  return sum;
}

6. 紧急情况

很多事情都有例外。在遇到紧急情况的时候可能需要做一些变通。我们需要对紧急情况有清晰定义,否则有可能会对不紧急的”紧急的情况“妥协代码的健康度。

什么是紧急情况?

  • 线上出现生产事故(P0、P1等),显著影响了用户的正常使用。
  • 线上发现重大安全隐患,需要紧急修复漏洞。
  • 一个小的修改来避免大版本发布后的回退。
  • 有对合作方承诺了硬性的截止日期。
  • ...