代码整洁之道
普通人读的懂的代码, 才是好代码 --- 沃滋基梭德概述篇
代码可读性 代码必须是对人类是可读的。不要考虑计算机如何处理它,因为会有许多工具来转换我们的代码(编译器)。因此,最重要的是,代码将是人类可读的,因为你在开发代码时,最长的工作就是阅读代码,而不是写代码。
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"],
}];
使用英语编写代码
团队协作 可以通过配置一个标准的 .editorconfig 文件
用空格还是 Tab 来格式化代码
在函数的名称旁边还是在下一行写大括号
是否在语句的结尾处放一个分号
有一个在业界广泛使用的工具被称为 Prettier,它能够根据 linter 的规则实时改变我们的代码格式(IDE的插件)。
变量篇
变量名要名副其实 变量的名称必须能够描述出该变量的作用和用途。
变量名可以读出来
在选择变量的名称时,另一个错误的行为是删除一个词中某些字母,使用这些缩略语读起来很困难。首先,我们是在用英语编码,而且不是所有的开发者都是讲英语的。因此,我们为什么要把它的名字减少 3 或 4 个字符?这有什么好处呢?代码会被工具(转译器包括其他语言的编译器)操作,最终正确地完成格式化(使用 Prettier)。因此,把不能发音的名字放在一起,只能让我们更费力地去推断变量的用途。
不要在名称中使用变量的类型 在变量名称中使用数据类型作为前缀是一个很古老的做法,现在让我们反思一下这个问题。
变量名称中必须要用类型作为前缀吗? 每个公司和工程都有各自的前缀规范,那如何去学习和书写这种代码呢? 如果我在变量的名称中使用一种编程语言的类型系统,为什么要用它呢? 当变量的数据类型发生变化时,比如把 Array 修改为 Map,这种情况怎么处理? 这个前缀能给我们带来什么?它是可以发音的吗?
对同一类型的变量使用相同的词汇表 对同一类型的数据使用相同的词汇表。如果我们需要检索一个用户或客户的信息,我们不能以不同的方式称呼用户或客户。也就是说,不能有时称其为 user,有时称其为 customer,甚至是 client 这个词。更不可 取的是,在变量名称上额外再加一个后缀。 下面代码就是很好的示例,同一个概念,有三个不同的定义。必须自始至终使用统一的命名,不管是 user、customer 还是 client,只能用同一个。
不要添加不需要的上下文 在变量名称中没有必要添加类或包的相关上下文。 在变量名称中添加上下文是很常见的,这样可以知道这个变量位于哪个工作区。
不要使用魔法数字和字符串 在编写代码时,不应该在源代码中直接使用数字或文本字符串,这些通常也被称为魔法数字.这个数字是什么意思?必须要解释这个数字吗?这让我们不得不思考业务逻辑之外的事情。
这些魔法数字或字符串必须存储在常量中,通过对常量的名称来表达出它们的用途。在业务逻辑层面上,对于那些有意义的数字或文本字符串,如果没有一个确切的名字就会引起噪音。
在业务逻辑层面上,对于那些有意义的数字或文本字符串,如果没有一个确切的名字就会引起噪音。
复杂判断
不要使用标记 (flag) 作为函数参数 这样会破坏函数功能的单一性,我们必须创建两个函数来实现各自对应的逻辑功能,而不是使用一个函数来实现两个逻辑功能,因为他们是不同的功能。
封装判断条件 条件封装在具有明确语义的函数中
用卫语句替换嵌套的条件语句
空对象 不断检查对象是否为null, 并根据该检查判断是否显示默认操作。这种模式称为空对象模式,我们默认封装了空对象行为的对象
使用多态删除条件 通过判断对象的类型去定义对象的方法,但是这里的条件语句被滥用了,在这种场景下,我们可以通过类的继承,为每个特定类型创建一个类,利用多态来避免使用条件判断。
使用策略模式/命令模式移除条件
函数
使用默认参数去代替短路操作或条件赋值
在大多数编程语言中,函数的参数支持设置默认值。这就意味着我们可以在代码中避免使用短路操作和条件赋值。
函数参数(理想情况下不多于 2 个)
当一个函数有很多参数时,可以把这些参数组合在一起构成一个对象。我们需要避免使用多个基础类型 (如字符串、数字、布尔值等) 作为函数的入参,而是要使用抽象级别更高的对象作为入参。这样我们会更接近业务逻辑,并且更加远离底层实现。
第一个例子中,我们实现了一个生产汉堡的函数,它有 4 个参数。这些参数是固定的,并且必须按照这个顺序传参,这会给我们带来很多的限制。这样的函数在使用的时候不是很灵活。
第二个例子中,最大的改进就是使用一个对象来作为参数,只需要传入一个 burger 对象就可以生产出一个 “新汉堡”。通过这种方式,我们将汉堡的基本属性整合到 1 个对象里面。
在第三个例子中,我们对传入的对象进行解构赋值,让对象的属性在函数体中可访问到,但是实际上我们传入的仅仅是一个参数,这使得这个函数有了更大的灵活性。
避免副作用 - 全局变量 副作用是未来麻烦的根源。虽然从定义上来说副作用不一定是有害的,但是如果在项目中没有节制的引起副作用,代码出错的可能性就会大大提高。 不惜一切代价避免副作用,并且确保函数是可以被测试到的。
改进后
避免副作用 - 可变对象 是直接修改对象本身,如果你一直从事计算机相关的工作,你会知道 JavaScript 自诞生以来就是支持对象可变的,目前许多库都在尽量避免使用可变对象。
数组的方法一般被分为两部分: 一部分是会对数组本身进行修改的方法,例如: push、pop、sort,另一部分是不会对数组本身产生修改的方法例如:filter、reduce 、map 等。
函数应该只做一件事
函数应该只是有一个抽象级别 每个函数应仅具有单个抽象级别。
优先考虑函数式编程而不是命令式编程 函数式编程相对于命令式编程相比的另一个特点是代码更具可读性。 函数式编程在这方面就具有很大的优势;但对于那些使用命令式编程学习并开始解决问题的初级程序员来说,他们很难使用这种编程范式,因为它改变了他们的工作习惯。但是在这个行业中,我们必须适应变化,况且目前使用函数式编程的场景越来越多。
函数链式调用
重构篇
重构很重要的原因:
改进软件/应用程序的设计
使软件更容易理解
发现 bug
修复现有的旧数据库
为用户提供更好的一致性
重构不是银弹,但它是一种有价值的武器,可以帮助你控制好代码和项目 (软件/应用)。它是一个科学的过程,对现有的代码进行改造,使代码可读性更高、更好理解和更整洁。而且,使添加新功能、构建大型应用程序以及发现和修复 bug 变得非常便捷。
撒密码是由明文和密文两个字母表构成的,密文字母表是将明文字母表向左或向右移动一个固定位置得到的。例如,这个恺撒密码,使用的偏移量为 6,相当于右移 6 位
重构建议: 无论我们如何重构代码,都要使用自动化测试来帮助我们验证有没有 “破坏” 代码。
魔法数字 通过定义语义化的变量来移除代码中出现的魔法数字
从 if-else 中提取相似代码 下一步是将代码中重复的代码提取到函数中。具体来说,if 控制结构体中的赋值代码在整个代码中是重复的,我们可以提取这些赋值代码。
避免使用 else 下一步是避免使用 else 控制结构。避免使用它是很容易的,我们只需要在循环开始之前将代码从 else 移到变量 character,并作为它的默认值。
合并 IF 逻辑
简化算法逻辑
封装条件
移除 if-else 控制结构
变量命名
最后更新于
这有帮助吗?