全文共8912个字,预计学习时间为14分钟
作者,来源need.pix
糟糕的代码也许能起到作用,但迟早会让我们付出代价。你是否遇到过这样的问题:几周后,你无法理解自己编写的代码,不得不花费数小时甚至数天的时间才能弄清楚到底发生了什么。
解决这一常见问题的方法是让代码尽可能清晰。如果做得好,即使是非技术人员也应该能够理解你的代码。
是时候停止找借口并提高我们的代码质量了!
编写清晰的代码并不复杂。本教程将向您展示改进代码的五种简单技巧,并提供一些实际示例:
1. 没有声明
我们经常使用语句来代替冗长的 if-else-if 语句。但是,语句非常冗长,难以维护,甚至更难调试。它们使我们的代码杂乱无章,而且这些语句的语法很奇怪且不舒服。添加更多案例时,我们必须手动添加每个案例和语句,这很容易出错。
我们来看一个示例语句:
(类型) {
让 ;
(类型) {
案件 '':
='';
;
案例‘火灾’:
='';
;
案件 '':
='';
;
案件 '':
='';
;
:
=‘喵喵’;
;
.log(('火灾')); // :
声明
如果需要在语句中添加更多case,需要编写的代码量相当大,我们可能最终只能复制粘贴代码,但是我们都知道这种行为的后果是什么。
那么,我们如何避免使用语句呢?我们可以使用对象字面量。对象字面量简单、易写、易读、易维护。我们都习惯与对象打交道,对象字面量的语法比语句更新鲜。下面是一个例子:
= {
:'',
火: '',
:'',
:''
};
(类型) {
[类型] || ‘喵’;
.log(('火灾')); // :
// 如果类型不在 中,则为 'Mew'
.log(('')); // : 喵
使用对象字面量代替
如您所见,您可以使用运算符 || 添加默认值。如果在对象中找不到类型,则该函数将返回 mew 作为默认值。
提示:你可能注意到了,我们在函数外部而不是内部声明对象。这样做是为了避免每次执行函数时都重新创建它。
使用映射可以实现相同的效果。映射就像对象一样是键值对的集合。不同之处在于映射允许任何类型的键,而对象只允许字符串作为键。此外,映射有许多有趣的属性和方法。
映射的使用方法如下:
=新地图([
['', ''],
['火', ''],
['', ''],
['', '']
]);
(类型) {
.获取(类型)||'喵';
.log(('火灾')); // :
.log(('')); // : 喵
使用映射代替语句
如您所见,当用对象文字或映射替换语句时,代码看起来更加清晰、更直接。
2. 使你的条件更具描述性
编写代码时,条件语句是绝对必要的。然而,它们很快就会失控,最终超出我们的控制范围。这导致我们要么必须写注释来解释语句的作用,要么必须花费宝贵的时间逐行检查代码以了解发生了什么。这很糟糕。
看一下下面的声明:
(){
如果 (
=== 0 ||
(=== 1 && === 1)||
=== 0
){
();
复杂条件语句
如果只看上一个函数中 if 语句中的代码,很难理解到底发生了什么。代码不清晰,不清晰的代码只会导致技术错误,让人很头疼。
我们如何改进条件语句?我们可以将其写成函数。操作方法如下:
(){
(
=== 0 ||
(=== 1 && === 1)||
=== 0
(英文):
// 我们现在要做的就是:
(){
如果 (()) {
();
将条件写成函数
通过将条件提取到具有描述性名称 () 的函数中,该函数现在更容易理解。为什么?因为代码更明确。它告诉我们发生了什么,这正是我们应该始终努力实现的。
3. 使用 语句 ( ) 代替嵌套的 if 语句
嵌套 if 语句是代码中最令人讨厌的东西之一。如果你想完全理解代码中发生的事情,它们可能会让你精疲力尽。以下是嵌套 if 语句的示例(深度为三层):
(){
=();
如果 (()) {
如果 () {
如果 (()) {
();
} 别的 {
新的('不要你的');
} 别的 {
new ("你的是,不能吗");
} 别的 {
new ('您需要登录');
嵌套 if 语句
您可能需要花几分钟从上到下阅读才能理解函数的流程。嵌套的 if 语句难以阅读和理解。那么,如何摆脱烦人的嵌套 if 语句呢?您可以反向思考并使用 语句来替换这些语句。
“在计算机编程中, 语句是一个布尔表达式,如果程序要继续在相关分支中执行,则该语句必须计算为真。” - 维基百科
通过反转函数的逻辑并将导致提前退出的条件放在函数的开头,它们将成为保护,并且只有在满足所有条件时才允许函数继续执行。这避免了 else 语句。以下是重构上一个函数以使用保护的方法:
(){
=();
如果 (!()) {
new ('您需要登录');
如果 (!) {
new ("你的是,不能吗");
如果 (!()) {
新的('不要你的');
();
使用 语句重构函数
如您所见,代码更加简洁易懂。我们可以顺着函数的自然流程,简单地向下阅读以了解函数的作用,而不必像以前那样向上向下阅读。
4. 不要重复代码
编写重复代码总是会导致失败。这会导致以下情况:“我在这里修复了这个错误,但忘记在那里修复它”或“我需要在五个不同的地方更改/添加新功能”。
正如 DRY(不要重复自己)原则所说:
每个知识或逻辑在系统中都必须具有单一、明确的表示。
因此,代码越少越好:它节省时间和精力,更容易维护,并减少错误的出现。
那么如何避免代码重复呢?这有点难,但将逻辑提取到函数/变量通常效果很好。让我们看看下面的代码,这是我在重构应用程序时看到的:
(){
=();
新闻=[];
对于(让 i = . - 1; i >= 0; i--){
如果([i].类型===“”){
新闻.推送([i]);
消息;
(){
=();
新闻=[];

对于(让 i = . - 1; i >= 0; i--){
如果([i].type ===“rust”){
新闻.推送([i]);
消息;
(){
新闻=[];
=();
对于(让 i = . - 1; i >= 0; i--){
如果([i].类型===''){
新闻.推送([i]);
消息;
重复代码示例
您可能已经注意到,这两个函数中的 for 循环完全相同,除了一个小细节:我们想要的新闻类型,即 或 news。为了避免这种重复,您可以将 for 循环提取到一个函数中,并从 、 和 函数中调用该函数。操作方法如下:
(){
=();
(,'');
(){
=();
(,'生锈');
(){
=();
(,'');
(, 类型) {
新闻=[];
对于(让 i = . - 1; i >= 0; i--){
如果([i].类型===类型){
新闻.推送([i].);
消息;
将for循环提取为函数后,、和函数就变成了简单、清晰的程序。
进一步重构
但是您是否意识到,除了传递给它们的类型字符串之外,这两个函数完全相同?这就是重构代码时经常发生的情况。通常,更改一个会导致更改另一个,依此类推,直到重构后的代码最终只有原始代码的一半大小。代码会告诉您它需要什么:
(类型) {
=();
(, 类型);
(, 类型) {
新闻=[];
对于(让 i = . - 1; i >= 0; i--){
如果([i].类型===类型){
新闻.推送([i].);
消息;
、和函数去哪儿了?用接收新闻类型作为参数的函数替换它们。这样,无论我们添加多少种新闻类型,我们总是使用相同的函数。这称为抽象,允许我们重用函数,因此非常有用。抽象是我编写代码时最常用的技术之一。
补充:使用 es6 特性让 for 循环更具可读性
for 循环不太可读。通过引入 es6 数组函数,你可以避免 95% 的时间使用它们。在这种情况下,你可以使用 . 和 .map 组合来替换原始循环:
(类型) {
=();
(, 类型);
(, 类型) {
.(=> .类型===类型)
.地图(=> .);
使用 . 和 .map 代替循环
• 使用 . 仅返回类型与作为参数传递的类型相同的元素。
• 使用.map仅返回项目对象的属性,而不是整个项目。
恭喜你!经过三次简单的重构,原来的三个函数精简为两个,更加容易理解和维护。此外,抽象使得函数具有可重用性。
5. 一个函数应该只做一件事
函数应该只做一件事。做多件事的函数是万恶之源,也是代码中最糟糕的东西之一(还有嵌套的 if 语句)。它们令人困惑,使代码难以理解。以下是来自实际应用程序的复杂函数示例:
(){
如果 (!。) {
。(“ 不是 ”);
} 别的 {
让 = .打开(“”, 1);
。 =()=> {};
。 = () => {
.(“”,.);
};
。 = () => {
让 db = .;
};
.('stat-op').('', () => {});
.('')。('',()=> {});
.('')。('',()=> {});
.('')。('',()=> {});
.('')。('',()=> {});
.('')。('',()=> {});
(“.json”)
.then(res => res.json())
.然后(=> {
.(“”). = .(
(, ) => .名称 + "
“,
“”
(英文):
});
.(“”). =`,${}`;
太多复杂且难以理解的功能
提示:由于此示例不需要事件侦听器处理程序,因此将其删除。
如您所见,它很混乱,很难理解发生了什么。如果发生错误,很难找到并修复它们。我们如何改进这个函数?我们可以将通用逻辑提取到一个函数中。方法如下:
(){
如果 (!。) {
新的(“ 't ”);
();
();
();
(){
让 = .打开('',1);
。 = () => {
.('', .);
};
。 = () => {
让 db = .;
};
(){
.('stat-op').('', () => {});
.('')。('',()=> {});
.('')。('',()=> {});
.('')。('',()=> {});
.('')。('',()=> {});
.('')。('',()=> {});
(){
=();
('')。 =();
(){
.(
(, ) => + .名称 + '
',
“”
(英文):
(){
然后(res => res.json());
将逻辑提取到函数中
仔细看看函数中的变化:
首先,将 if-else 语句替换为 语句。然后,将启动数据库所需的逻辑提取到一个函数中,并在该函数中添加事件监听器。
打印员工列表的逻辑稍微复杂一些,因此创建了三个函数:、和。
负责对.json 发出 GET 请求并以 json 格式返回响应。
然后,它被一个函数调用,该函数获取员工列表并将其传递给格式化并返回该列表的函数。然后输出该列表。
如您所见,每个函数只负责做一件事。
我们仍然可以对该函数进行一些更改,事实上,应用程序确实需要将视图与控制器分开,但总体而言,该函数现在非常不言自明,您绝对不会难以理解它的作用。如果您几个月后必须重新查看此代码,那也没什么大不了的。
概括
程序员是唯一负责编写高质量代码的人。我们都应该养成从第一行开始编写优质代码的习惯。编写清晰易懂的代码并不难,这样做将使你和你的同事受益。