代码整洁之道

普通人读的懂的代码, 才是好代码 --- 沃滋基梭德

概述篇

  1. 代码可读性 代码必须是对人类是可读的。不要考虑计算机如何处理它,因为会有许多工具来转换我们的代码(编译器)。因此,最重要的是,代码将是人类可读的,因为你在开发代码时,最长的工作就是阅读代码,而不是写代码。

const users = [{ id: 1, name: "Carlos Caballero", memberSince: "1997–04–20", favoriteLanguageProgramming: ["JavaScript", "C", "Java"] }, { id: 2, name: "Antonio Villena", memberSince: "2014–08–15", favoriteLanguageProgramming: ["Go", "Python", "JavaScript"] }, { id: 3, name: "Jesús Segado", memberSice: "2015–03–15", favoriteLanguageProgramming: ["PHP", "JAVA", "JavaScript"] } ];

/***********************/

const users = [
    { id: 1, name: "Carlos Caballero", memberSince: "1997–04–20", favoriteLanguageProgramming: ["JavaScript", "C", "Java"] },
    { id: 2, name: "Antonio Villena", memberSince: "2014–08–15", favoriteLanguageProgramming: ["Go", "Python", "JavaScript"] },
    { id: 3, name: "Jesús Segado", memberSice: "2015–03–15", favoriteLanguageProgramming: ["PHP", "JAVA", "JavaScript"] },
    ];


/***********************/

const users = [{
    id: 1,
    name: "Carlos Caballero",
    memberSince: "1997–04–20",
    favoriteLanguageProgramming: ["JavaScript", "C", "Java"],
},
{
    id: 2,
    name: "Antonio Villena",
    memberSince: "2014–08–15",
    favoriteLanguageProgramming: ["Go", "Python", "JavaScript"],
},
{
    id: 3,
    name: "Jesús Segado",
    memberSince: "2015–03–15",
    favoriteLanguageProgramming: ["PHP", "JAVA", "JavaScript"],
}];


  1. 使用英语编写代码

  1. 团队协作 可以通过配置一个标准的 .editorconfig 文件

  • 用空格还是 Tab 来格式化代码

  • 在函数的名称旁边还是在下一行写大括号

  • 是否在语句的结尾处放一个分号

有一个在业界广泛使用的工具被称为 Prettier,它能够根据 linter 的规则实时改变我们的代码格式(IDE的插件)。

变量篇

  1. 变量名要名副其实 变量的名称必须能够描述出该变量的作用和用途。

  2. 变量名可以读出来

在选择变量的名称时,另一个错误的行为是删除一个词中某些字母,使用这些缩略语读起来很困难。首先,我们是在用英语编码,而且不是所有的开发者都是讲英语的。因此,我们为什么要把它的名字减少 3 或 4 个字符?这有什么好处呢?代码会被工具(转译器包括其他语言的编译器)操作,最终正确地完成格式化(使用 Prettier)。因此,把不能发音的名字放在一起,只能让我们更费力地去推断变量的用途。

  1. 不要在名称中使用变量的类型 在变量名称中使用数据类型作为前缀是一个很古老的做法,现在让我们反思一下这个问题。

变量名称中必须要用类型作为前缀吗? 每个公司和工程都有各自的前缀规范,那如何去学习和书写这种代码呢? 如果我在变量的名称中使用一种编程语言的类型系统,为什么要用它呢? 当变量的数据类型发生变化时,比如把 Array 修改为 Map,这种情况怎么处理? 这个前缀能给我们带来什么?它是可以发音的吗?

  1. 对同一类型的变量使用相同的词汇表 对同一类型的数据使用相同的词汇表。如果我们需要检索一个用户或客户的信息,我们不能以不同的方式称呼用户或客户。也就是说,不能有时称其为 user,有时称其为 customer,甚至是 client 这个词。更不可 取的是,在变量名称上额外再加一个后缀。 下面代码就是很好的示例,同一个概念,有三个不同的定义。必须自始至终使用统一的命名,不管是 user、customer 还是 client,只能用同一个。

  1. 不要添加不需要的上下文 在变量名称中没有必要添加类或包的相关上下文。 在变量名称中添加上下文是很常见的,这样可以知道这个变量位于哪个工作区。

  1. 不要使用魔法数字和字符串 在编写代码时,不应该在源代码中直接使用数字或文本字符串,这些通常也被称为魔法数字.这个数字是什么意思?必须要解释这个数字吗?这让我们不得不思考业务逻辑之外的事情。

这些魔法数字或字符串必须存储在常量中,通过对常量的名称来表达出它们的用途。在业务逻辑层面上,对于那些有意义的数字或文本字符串,如果没有一个确切的名字就会引起噪音。

在业务逻辑层面上,对于那些有意义的数字或文本字符串,如果没有一个确切的名字就会引起噪音。

复杂判断

  1. 不要使用标记 (flag) 作为函数参数 这样会破坏函数功能的单一性,我们必须创建两个函数来实现各自对应的逻辑功能,而不是使用一个函数来实现两个逻辑功能,因为他们是不同的功能。

  1. 封装判断条件 条件封装在具有明确语义的函数中

  1. 用卫语句替换嵌套的条件语句

  1. 空对象 不断检查对象是否为null, 并根据该检查判断是否显示默认操作。这种模式称为空对象模式,我们默认封装了空对象行为的对象

  1. 使用多态删除条件 通过判断对象的类型去定义对象的方法,但是这里的条件语句被滥用了,在这种场景下,我们可以通过类的继承,为每个特定类型创建一个类,利用多态来避免使用条件判断。

  1. 使用策略模式/命令模式移除条件

函数

  1. 使用默认参数去代替短路操作或条件赋值

    在大多数编程语言中,函数的参数支持设置默认值。这就意味着我们可以在代码中避免使用短路操作和条件赋值。

  1. 函数参数(理想情况下不多于 2 个)

当一个函数有很多参数时,可以把这些参数组合在一起构成一个对象。我们需要避免使用多个基础类型 (如字符串、数字、布尔值等) 作为函数的入参,而是要使用抽象级别更高的对象作为入参。这样我们会更接近业务逻辑,并且更加远离底层实现。

第一个例子中,我们实现了一个生产汉堡的函数,它有 4 个参数。这些参数是固定的,并且必须按照这个顺序传参,这会给我们带来很多的限制。这样的函数在使用的时候不是很灵活。

第二个例子中,最大的改进就是使用一个对象来作为参数,只需要传入一个 burger 对象就可以生产出一个 “新汉堡”。通过这种方式,我们将汉堡的基本属性整合到 1 个对象里面。

在第三个例子中,我们对传入的对象进行解构赋值,让对象的属性在函数体中可访问到,但是实际上我们传入的仅仅是一个参数,这使得这个函数有了更大的灵活性。

  1. 避免副作用 - 全局变量 副作用是未来麻烦的根源。虽然从定义上来说副作用不一定是有害的,但是如果在项目中没有节制的引起副作用,代码出错的可能性就会大大提高。 不惜一切代价避免副作用,并且确保函数是可以被测试到的。

改进后

  1. 避免副作用 - 可变对象 是直接修改对象本身,如果你一直从事计算机相关的工作,你会知道 JavaScript 自诞生以来就是支持对象可变的,目前许多库都在尽量避免使用可变对象。

数组的方法一般被分为两部分: 一部分是会对数组本身进行修改的方法,例如: push、pop、sort,另一部分是不会对数组本身产生修改的方法例如:filter、reduce 、map 等。

  1. 函数应该只做一件事

  1. 函数应该只是有一个抽象级别 每个函数应仅具有单个抽象级别。

  1. 优先考虑函数式编程而不是命令式编程 函数式编程相对于命令式编程相比的另一个特点是代码更具可读性。 函数式编程在这方面就具有很大的优势;但对于那些使用命令式编程学习并开始解决问题的初级程序员来说,他们很难使用这种编程范式,因为它改变了他们的工作习惯。但是在这个行业中,我们必须适应变化,况且目前使用函数式编程的场景越来越多。

  1. 函数链式调用

重构篇

重构很重要的原因:

  1. 改进软件/应用程序的设计

  2. 使软件更容易理解

  3. 发现 bug

  4. 修复现有的旧数据库

  5. 为用户提供更好的一致性

    重构不是银弹,但它是一种有价值的武器,可以帮助你控制好代码和项目 (软件/应用)。它是一个科学的过程,对现有的代码进行改造,使代码可读性更高、更好理解和更整洁。而且,使添加新功能、构建大型应用程序以及发现和修复 bug 变得非常便捷。

撒密码是由明文和密文两个字母表构成的,密文字母表是将明文字母表向左或向右移动一个固定位置得到的。例如,这个恺撒密码,使用的偏移量为 6,相当于右移 6 位

重构建议: 无论我们如何重构代码,都要使用自动化测试来帮助我们验证有没有 “破坏” 代码。

  1. 魔法数字 通过定义语义化的变量来移除代码中出现的魔法数字

  1. 从 if-else 中提取相似代码 下一步是将代码中重复的代码提取到函数中。具体来说,if 控制结构体中的赋值代码在整个代码中是重复的,我们可以提取这些赋值代码。

  2. 避免使用 else 下一步是避免使用 else 控制结构。避免使用它是很容易的,我们只需要在循环开始之前将代码从 else 移到变量 character,并作为它的默认值。

  3. 合并 IF 逻辑

  4. 简化算法逻辑

  5. 封装条件

  6. 移除 if-else 控制结构

  7. 变量命名

最后更新于

这有帮助吗?