让我们继续有关代码重构的一系列简短帖子!在其中,我们讨论了可以帮助您改善代码和项目的技术和工具。
今天,我们将讨论声明的代码样式以及如何帮助我们减少代码中的意外错误和错误的数量。
命令和声明风格
要了解命令和声明风格之间的区别,让我们来看看一个示例:
// 1.
const evenNumbers = []
for (const x of array) {
if (x % 2 === 0) {
evenNumbers.push(x)
}
}
// 2.
const isEven = x => x % 2 === 0
const evenNumbers = array.filter(isEven)
第一个代码段是必须的,它描述了如何将问题作为一组指令解决:
- 创建一个空的
evenNumbers
数组; - 迭代给定的
array
变量; - 检查每个数字是否均匀;
- 如果是这样,请将其添加到
evenNumbers
。
另一方面,第二个摘要描述了需要完成的工作。它着重于过滤标准,而不是过滤算法的详细信息。
这是命令和声明风格之间的区别。声明代码描述了要做什么,而命令代码描述了 的执行方式。
混乱的问题
在命令式代码中,我们必须考虑到目标和如何实现目标,因此,命令代码通常包含更多的行,并且从统计上则更有可能包含错误。
让我们看看另一个示例。下面的selectOperation
函数选择给定键的数学操作:
function selectOperation(kind) {
let operation = null;
switch (kind) {
case "log":
operation = (x, base) => Math.log(x) / Math.log(base);
case "root":
operation = (x, root) => x ** -root;
default:
operation = (x) => x;
}
return operation;
}
该功能似乎还可以,但是其中的每个情况都会错过break
语句。结果,operation
变量将始终等于(x) => x
。
这样的错误相对容易在一个小功能中发现,但是如果有很多代码,那么错过了很多。
由于在命令代码中,线和字符的数量较小,因此我们更容易看到此类错误。
对于缺少
break
语句,我们始终可以自动搜索此类错误。
但是,以我的经验,这并不总是足够的,因为如果代码中有一种方法使人们犯错了。
因此,最好以这样的方式编写代码。
改进代码
我们可以通过使选择声明来摆脱意外错误的问题:
const log = (x, base) => Math.log(x) / Math.log(base);
const pow = (x, power) => x ** power;
const id = (x) => x;
function selectOperation(kind) {
const operations = { root, pow, id };
return operations[kind] ?? operations.id;
}
在上面的代码中,我们现在将“选择”委托给语言本身。我们不在乎如何做出选择,我们只关心它的结果。
在此代码中,犯一个偶然的错误要困难得多,因为它的代码较小,其结构更强大。
出于美学原因,我也喜欢最后一个片段。从键选择对象看起来像是对此问题的更自然的解决方案,而使用switch
的代码似乎嘈杂而冗长。
有关我书中重构的更多信息
在这篇文章中,我们仅讨论了声明代码样式的可靠性。
我们尚未提及其其他好处,例如更好的可读性和可扩展性,对域的更准确的建模以及拆分代码和配置的能力。
如果您想进一步了解这些方面并一般重构,我鼓励您查看我的在线书:
这本书是免费的,可以在Github上获得。在其中,我更详细地解释了这个主题。
希望您发现它有帮助!享受这本书ð