【译】10个技巧,立竿见影的提高初学者的编码能力

原文地址:https://www.sitepoint.com/how-to-write-good-code
作者:Joel Falconer

作为一个初学者,提高自己的代码技巧是首要任务,但是从哪下手呢?在这么多信息里面,很难知道该学哪些,哪些能真正帮助我们提高代码质量

在这篇博客种,我将分享10种对初学者友好的编码技巧,帮助您写出更好的代码,如果您已经做好准备让您的编码技巧更上一层楼,那我们就马上开始吧!

1. 从计划开始

Alt

制定计划是编写更好代码的最好的方法之一。在你开始写代码之前,花费一点时间想一下你想让你的代码干什么,或者是实现什么功能。
不要以为你知道了需求,一上来就直接开始编码,花点时间真正分析一下手里的问题。

  • 输入输出是什么?
  • 预期的结果是什么?
  • 代码逻辑是否正确?
  • 你需要的数据结构是什么?
  • 是否考虑了边界值的情况?

在开始之前思考这些问题,能帮助你更快速的实现功能,同时减少代码出BUG的概率,它可以让你更加熟悉项的需求,了解业务也是很重要的一部分,也可以让你更快速的写出测试用例去检测代码。

当然,这种方式并不是限制你非要这么做,也不必花费大量的时间在这上面,仅仅是你在启动编辑器之前,哪怕是花几分钟在纸上画一画,也会让你事半功倍。

对需要做的事情有了清晰的理解,你就能把你的想法变成一个具体的计划,你会发现通过这种方法设计生成的代码更易于阅读,扩展性更高,也更易于管理。

虽然你的代码会更简洁,但如果你发现了一些未知因素并制定了计划,那么你就可以在问题上节省无数的时间,而这些问题本来是可以避免的,你会从中受益最大。为了解决更高级的问题,培养有利于你和你的职业生涯的技能,你需要花费无数的时间。

制定高水平计划的技巧

  1. 对你手头上的问题有一个清晰的理解
  2. 在写代码之前,花时间考虑一下,为了解决当前的问题,你希望代码做些什么
  3. 在开始编码之前先编写伪代码,伪代码还不是真正的代码,它有助于在不陷入细节的情况下设计出代码的结构
  4. 画一张图表,将问题可视化可以帮助你更好的理解需要做什么,以及不同的部分是如何关联在一起的
  5. 检查你的工作,一旦你有了一个计划,就可以用任何情况的数据去检查它,并确保它是可行的
  6. 使用内联注释来解释你的思维过程,一旦你开始写代码,使用内联注释来解释你在做什么以及为什么这么做。这样,可以让你或者他人在后来看这段代码时会非常友好,如果是一个可能会让其他人感到困惑的复杂问题,注释就显得尤其重要!

2. 编写有意义的变量和函数名

好代码的一个特点就是易于阅读和理解,而使代码易于阅读的一个重要方面就是使用有意义的变量和函数名。

为事物取个还名字是很难的。但这很重要,即使是在Web开发种也是如此,当别人试图理解你的代码时,变量和函数名通常时第一个要看的东西。

考虑下面的例子:

let x, y, z;
function f(){
  // function
}

上面的代码不是很容易阅读,x, y和z分别代表什么?f() 又是做什么的?

现在考虑这个例子

let firstName, lastName;
function printFullName(firstName, secondName){
  // function
}

这段代码就更容易阅读了,变量名提供了信息,函数名让我们很好的了解了它的作用。

如果名称是描述性的,在检查代码时,也更有可能发现错误,例如传递给函数的变量错误,否则,你就必须在工作中一直记住该变量的含义。

当只有一个变量 a 时,我们很容易记住为什么定义它,但当工作中出现很多这种无意义的变量名时就很难记住它们每一个的含义了,这就形成了一个认知的瓶颈,严重限制了你能够管理的复杂性范围。

你应该采用一致的样式来格式化名称,当人们在开发中提到命名约定时,他们通常会谈论使用大写和分隔符的方式来增强可读性。

下面时一些在开发中最常见的命名约定:

  • 驼峰命名(Camel):变量名写在一些列连接在一起的单词中,除了第一个单词以小写字母开头以外,其他每个单词都以大写字母开头,例如:firstNamelastNameprintFullName()。驼峰命名在Javascript中非常常见。
  • 帕斯卡命名(Pascal):帕斯卡命名和驼峰命名很相似,但它的第一个单次的首字母也是大写的,例如:FirstNameLastNamePrintFullName()
  • 蛇形命名(Snake): 蛇形命名使用的都是小写字母,每个单词之间用下划线连接。例如:first_namelast_nameprint_full_name()
  • 烤肉串命名(Kebab): 烤肉串命名和蛇形命名类似,但是单词之间使用的是连字符(中划线)连接在一起的。例如:first-namelast-nameprint-full-name()

一旦你选择一个命名约定,保持一致并坚持它是很重要的。

举个例子,你可能决定对变量名使用驼峰命名(firstName),对函数使用蛇形命名(print_full_name)。在这种情况下,不用的约定使得一致性对于可读性尤为重要。你暗示了每个命名约定都有含义。

如果这种改变时随机的,没有规律的,那么其他阅读你的代码的人就会很困难,甚至会误解你的代码,还会在没有必要的地方浪费更多的精力。

编写清晰变量名的技巧

变量名和函数名应该:

  • 具有描述性
  • 容易记忆和阅读
  • 和其他名称保持一致性

为此,你应该:

  • 使用描述性名称,变量名或者函数名应描述其用途
  • 避免使用单字母名称,除非上下文中的含义非常清楚,例如,在For循环中使用i作为索引通常是可以的,因为这是一种常见的约定。
  • 避免使用数字命名,数字是在代码中使用的数字文字,没有对其含义进行明确的解释
  • 决定命名约定,然后坚持它
  • 经常写代码注释,当起名字还不能满足代码的解释的时候,就需要通过注释来解释,这样当再次查看代码的时候就能更快的理解代码。

当你正在给事物命名的时候,问自己一下几个问题:

  • 这个变量或者函数的作用是什么?
  • 它的名字描述了它的用途了吗?
  • 它是否便于记忆和阅读当其他人看的时候
  • 它是否和代码中的其他名字的命名方式是保持一致的?

如果你不能很容易的回答这些问题,那么选择一个不同的名称可能是一个好主意。

3. 编写小型的,模块化的函数

alt

函数是程序员工具包中最强大的工具之一。它允许我们把一个大问题拆分成更小,更易于管理的部分

较小的函数更容易测试,调式和重用,也可以让你的代码的可读性更高,因为每个函数的意义都是清晰的

看下面的例子:

function multiplySquaredNumbers(x, y){
  let xSquared = x * x
  let ySquared = y * y
  return xSquared * ySquared
}
console.log(multiplySquaredNumbers(5, 6)); // 输出900

可以看到,这个方法需要两个参数。它声明变量来管理输入的参数平方后的结果,以便后续操作,在返回结果的那一行可以看到,返回的结果是变量相乘之后的结果

你可能已经发现了,我们还有别的方法来简化这个函数。这里有一个:

function multiplySquaredNumbers(num1, num2){
  return Math.pow(num1, 2) * Math.pow(num2, 2)
}
console.log(multiplySquaredNumbers(2, 3)) // 输出 36

为了演示模块化代码的实用性,我们把数字平方的功能单独抽出来用一个函数实现

function square(x){
  return x * x
}
function multiplySquaredNumbers(x, y){
  return square(x) * square(y)
}
console.log(multiplySquaredNumbers(5, 6)); // 输出900

乍一看,很难看出这种方法如何帮助我们编写更好的代码,这个示例太简单(并且依赖太多的基本运算符),也没有减少代码的行数。但事实上,我们是把一个函数拆成了两个函数。

简洁的代码总是优先于不必要的冗长代码,如果你不是在秀代码,请尽量用健壮,可读性好的代码来实现你的功能。

重要的是要理解代码模块化并不是对代码极简主义的苦行追求。而是当问题再次出现时,从你花费在解决问题上的时间中获益。

现在,不管我们什么时候想对一个数字进行平方运算,我们都可以使用我们自己的模块函数来完成这项工作,即使我们再也不需要将两个平方数相乘。我们已经知道了计算机是如何做这项工作的,并从中获益。

如果我们采用原始示例中的方法,我们将不得不告诉编译器,在任何时候我们想要为后续操作平方数字时如何继续。

这是一个简单的例子,但是它说明了如何使用函数将一个大问题分解成一个个较小的部分。

在web开发中,需要反复解决的问题通常更加复杂。例如,你需要显示来自API调用的数据列表。这涉及数据获取、数据迭代,以及在页面上动态创建要显示的部分数据的元素。

这个问题一次很好解决,但如果每次进行API调用或更新数据列表时都需要这样做,那么就必须复制大量代码。这将很快变得难以管理,尤其是当需要显示此列表的不同位置的数量增加时。

相反,你可以创建一个函数,该函数接受一些数据,并 返回在页面上显示该数据所需要的元素。然后,无论任何时候需要创建这些元素,都可以使用对应的数据去调用函数。这样将允许我们保持代码整洁,避免重复。

编写模块函数的技巧

在编写模块化函数时,可以遵循的一些最佳做法:

通过控制功能单一来保证函数小型化

当你在编写一个函数的时候,想一下它是要做什么的,并且只让它做这一件事。

只写一此就能完成所有事情,这是很诱人的,但这也意味着你的函数逻辑复杂,包罗万象。这样就会使你的代码更难理解,同时也更容易出错。

通常最好编写几个小函数,每个函数只做一件事。这些更容易测试,并且更容易在代码的不同部分中重用。

以描述性方式命名函数

函数名应该清晰且具有描述性,以便你(和其他开发人员)在阅读代码时能够很容易的理解它们所作的工作。我们已经讨论了命名,但是对于在代码库中反复使用的函数来说,命名尤其重要。

避免副作用

如果函数在其作用域之外修改了某些内容,则称其具有副作用。例如接受数组作为参数并对数组进行排序的函数将被认为具有副作用。

没有副作用的函数称为纯函数。他们通常更受欢迎,因为他们更容易预测。

总是避免副作用时很困难的,但是在编写函数的时候要记住这一点。

明智的使用参数

当你决定在函数中使用某些参数时,请考虑他们是否真的有必要。

参数通常用于使函数更灵活,以便在不同的情况下使用。但是太多的参数会使函数难于理解和使用.

通常,包含少量精心挑选的参数比包含大量不那么重要的参数要好。

4. 适当地使用数据结构

数据结构是组织数据以便有效使用的方法。有许多不同类型的数据结构,但最常见的是数组和对象。

数据是数据的列表。它们可以用于存储任何类型的数据,但数组中的每个项必须具有相同的类型。数组使用方括号声明:

const arr = ['a', 'b', 'c']

对象是使用键-值对进行数据组织的集合。键用于访问值,值可以是任何类型的数据。对象使用大括号声明:

const obj = {
  key1: 'value1',
  key2: 'value2',
  key3: 'value3',
};

应该适当地使用数据结构,是代码更具可读性和效率。例如,如果你有一个需要在页面上显示的数据列表,那么使用数组比使用对象更合适。因为数组更容易迭代,创建显示数据所需的元素也会更容易

另一方面,如果你有一个需要在页面上显示的数据集合,但每个数据片段也有有一些关联的元数据,那么使用对象比使用数组更合适。因为使用键可以更更容易的访问数据和元数据。

5. 尽可能地注释代码

alt

注释是未执行的代码行,开发人员人员可以为自己或他人留下注释。在JavaScript中,单行注释用//表示,多行注释用/* */表示:

// 这是单行注释

/*
  这是
  多行
  注释
*/

注释是提高代码可读性的好方法。使用注释来解释代码正在做什么以及为什么要这么做

注释之所以重要,主要有两个原因:它们可以帮助你记住代码正在做什么,并且它们可以帮组其他人理解你的代码。养成在编写代码时注释代码的习惯是很重要的,这将帮助你跟踪自己的想法,并使他人更容易理解你的代码

一个常见的惯例就是使用TODO注释为自己留下需要做的事情的注释:

 // TODO: Implement login functionality

另一个常见的惯例就是使用FIXME注释为自己留下需要修复的东西:

// FIXME: This code is not working properly

这是一种跟踪需要做什么的有用的方法,也让其他人更容易看到需要做什么。

一般来说,当你不确定应该做什么,或者你任务有可能有更好的方法做某事时,留下注释是一个好主意。注释通常就是用来解释复杂或不明显的代码。

重要的是要记住注释应该是用来提高代码的可读性,而不是让代码更难理解。如果你发现自己写的注释比它的代码还长,这是一个信号,表明你的代码不可读,应该进行重构。

注释代码的技巧

  • 使用注释来解释你的代码在做什么以及为什么要这么做
  • 使用注释为自己留下关于需要做或者修改的事情的笔记
  • 使用注释来解释复杂或者不明显的代码
  • 使用注释来增强代码的可读性,而不是作为一种支撑
  • 在编写代码的时候写注释,不要等到代码写完以后再来
  • 不需要过多注释代码,只需要注释需要解释的部分即可
  • 注释中使用清晰简洁的语言
  • 避免使用缩略语或行话
  • 保持注释和代码的同步,如果你在修改代码,也要及时修改注释
  • 及时删除过时的注释

6. 缩进代码提高可读性

缩进可以使代码更容易阅读,还可以帮助您发现错误。当代码正确缩进时,更容易看到代码的结构以及每个部分的开始和结束位置。这是调试代码和查找错误的有用方法。

在JavaScript中,标准的缩进是两个空格。在Python中,标准缩进是四个空格。在Python这样的语言中,缩进很重要,使用错误的缩进会导致代码中断。

但即使是在JavaScript这样的语言中,缩进纯粹是表示的问题,保持缩进的一致性也很重要。不一致的缩进会使代码更难以阅读和理解。

缩进代码的主要原因是为了提高可读性。但是缩进代码也可以帮助您查找错误。如果代码正确缩进,就更容易发现什么地方不对。

例如,看一下下面的代码示例:

// 未缩进的代码

function printHello() {
console.log("Hello, world!");
}
printHello();

// 缩进后的代码

function printHello() {
  console.log("Hello, world!");
}

printHello();

在未缩进的代码中,很难看到console.log()语句位于printHello()函数中。但是在缩进代码中,很明显console.log()语句位于printHello()函数中。这样更容易发现错误,比如忘记添加花括号。

缩进代码是一种风格问题,但重要的是保持缩进的一致性。大多数编程语言对代码如何缩进都有约定,所以遵循这些约定是个好主意。

一般来说,每当开始一个新的代码块时,都应该缩进代码。块是一起执行的一段代码。例如,一个块可以是一个函数、一个if语句或一个For循环。

7. 使用空格来提高代码可读性

除了缩进代码之外,还可以使用空格来提高代码的可读性。通过在代码行之间添加额外的空格,您将使您的代码更容易扫描和理解。这在检查大块代码时特别有用。

空间本身使它更容易跟踪你的阅读位置,就像段落对自然语言一样。但是,当空格将相关的代码行组合在一起时,它最能使代码更容易阅读。

在一个函数的结束和下一个函数的开始之间放一个空行是一种常见的做法。

function printHello() {
  console.log("Hello, world!");
}

function printWelcome(name) {
  console.log("Hello, " + name);
}

也可以在条件语句的子句之间添加空行

function printWelcome(name) {
  if (name === "John") {
    print("Welcome, John!");
  } 

  else {
    print("Welcome, stranger!");
  }
}

还可以在声明变量的代码行和使用这些变量的代码行之间添加空行。

<?php
$name = "John";
$location = "Sydney";

echo "Welcome to $location, $name!";
?>

空格和缩进都有各自的优点,但它们共同创建了一个可视化的层次结构,从而澄清了执行流程。当您结合使用空格来对相关的行进行分组,并使用缩进来指示作用域时,您的代码及其可读性将受益最大。

8. 使用数组和循环来提高效率

数组和循环是基础但功能强大的工具,可以帮助您编写更好的代码。如果你已经开始学习编码,你可能已经知道它们了。

通过使用数组,可以有组织地存储数据。这可以使您的代码更高效,更容易阅读。另一方面,循环可以帮助您自动化重复的任务。

一旦您知道如何正确地使用它们,它们可以为您节省大量的时间和精力。例如,它们通常可以消除复杂的、嵌套的条件块的需要。

嵌套if语句很难读,因为它们有太多代码行,在逻辑流中涉及太多分支。

下面是一个嵌套if语句的例子:

if (x > 0) {
  if (x < 10) {
    print("x is between 0 and 10");
  } else {
    print("x is greater than 10");
  }
} else {
  print("x is less than or equal to 0");
}

使用数组和循环可以更清楚地编写相同的逻辑:

let numbers = [-5, 0, 5, 10, 15];

for (let i = 0; i < numbers.length; i++) {

  let x = numbers;

  if (x > 0 && < 10) {
    console.log(`x is between 0 and 10`);

  } else if  (x > 10) {
    console.log(`x is greater than 10`);

  } else {
    console.log(`x is less than or equal to 0`);
  }
}

这段代码更容易阅读,因为它更简洁,逻辑流更线性。for循环遍历数组的元素,if语句测试每个元素是否满足指定的条件

这通常更有效,因为它消除了对多个条件测试的需要。

9. 尽可能编写自文档化代码

自文档化代码是易于阅读和理解的代码,不需要注释。这种类型的代码以一种明确其目的的方式编写。

这并不能取代好的注释习惯,但它确实迫使您记住高级程序结构。您将生成更容易理解、更容易维护、更不容易出错的代码。

有许多方法可以使您的代码自文档化。我们已经介绍了其中一些:

  • 使用清晰地描述性变量和函数名
  • 编写简短的函数,只做一件事,并把它做好
  • 通过使用命名常量来避免魔术数字(没有明显意义的数字)。
  • 使用空格将代码分隔成逻辑块。
  • 使用清晰和一致的编码约定。这使您的代码更容易阅读和理解,即使对不熟悉您的代码库的人也是如此。

下面是一些使代码自文档化的其他方法:

  • 避免不必要的代码。这包括死代码(不再使用但没有删除的代码)和声明明显内容的注释。
  • 编写易于测试的代码。这意味着您的代码应该是模块化的,并且具有定义良好的接口。它还应该以一致的方式优雅地处理错误。
  • 保持代码库小。这样可以更容易地找到您要查找的内容并理解代码是如何工作的
  • 保持代码的良好组织。这意味着使用一致的编码风格和结构,并使用注释来解释复杂的代码。
  • 文档很重要,但是自文档化的代码更好。它更容易阅读、理解和维护。因此,下次编写代码时,请自问是否可以做些什么使它更具有自文档性。

这些只是一些指导方针。当您成为一名更有经验的开发人员时,您将发现更多方法使您的代码具有自文档化功能。

10. 不要重复你自己(DRY)

优秀编码最重要的原则之一是DRY原则:不要重复自己。

这意味着您应该尽可能避免重复代码。重复的代码更难维护,也更容易出错。

可以使用许多工具来避免代码中的重复。

  • 功能和模块。函数允许您封装想要重用的代码,这一点我们在前面已经讨论过了(在我们第一次提到DRY原则时)。模块允许您将相关的功能分组在一起。
  • 数据结构。数据结构可以用来以一种易于访问和修改的方式存储信息。例如,如果您有一个名称列表,则可以将它们存储在数组中,而不是将它们硬编码到整个代码的函数调用中。
  • 继承。避免重复的一种更高级的方法是使用继承。这是一种通过让一个类继承另一个类来在类之间共享代码的方法。我们不会在这里详细讨论继承,但只要说它是一个强大的工具,可以帮助您避免重复代码就足够了。
  • 工具库。最后,您可以通过使用工具库来避免重复。有许多开源库可以用来执行常见的任务。例如,lodash库提供了广泛的实用函数

DRY原则是优秀编码最重要的原则之一。尽可能避免重复代码是很重要的。这节省了您的时间,因为您只解决一次问题,并且当其他因素发生变化时,只需要更改解决方案的一个实现。

而且,因为在发生故障时,您只需要修复一个实现,所以DRY代码更容易维护,也更不容易出错。

编写DRY代码的技巧

  1. 尽量避免重复使用代码。如果您知道您将在代码的其他地方再次进行某些操作,那么您可以在第一次将代码编写为独立的实体,从而避免返回重构
  2. 当你重用代码时,模块化它。不要将解决方案复制到新位置。相反,将它移动到适当类型的对象或数据结构中,然后引用它。
  3. 当您发现将代码重写为DRY代码有很大的好处时,就重构代码。这意味着在不改变其功能的情况下重构代码。重构有时可能是一个拖延陷阱,但如果您意识到需要再次使用大型函数的一部分,那么就值得进行重构
  4. 使用库和框架来避免重复工作。如果您不应该重复自己的话,为什么要编写代码来解决已经解决的问题呢?
  5. 使用继承在类之间共享代码。
  6. 在创建文档时遵循DRY原则—不要不必要地重复信息。
  7. 使用清晰的变量和函数名,并在必要时注释代码。

11. 编写SOLID代码

一个考虑如何编写软件的流行框架被称为SOLID。

SOLID是五个主要软件设计原则的缩写,由敏捷软件开发宣言的创始人和干净代码的作者Robert C. Martin创造。

SOLID的五大设计原则是:

  • 单一职责原则(Single responsibility principle)。该原则规定每个类或模块都应该有一个(且只有一个)更改理由。换句话说,每个类或模块应该只负责一件事。
  • 打开/关闭原则(Open/closed principle)。这个原则规定软件应该对扩展开放,但对修改关闭。也就是说,您应该能够扩展类或模块的功能,而不必修改代码本身。
  • Liskov替换原则(Liskov substitution principle)。这个原则规定子类应该可以替代它们的父类。也就是说,子类应该能够代替它的超类而不会引起任何问题。
  • 接口隔离原则(Interface segregation principle)。这个原则指出,不应该强迫客户依赖于他们不使用的方法。换句话说,每个界面都应该很小,并且专注于一个特定的目的。
  • 依赖性倒置原则(Dependency inversion principle)。这一原则指出依赖关系应该是倒置的。也就是说,高级模块不应该依赖于低级模块。相反,两者都应该依赖于抽象。

你不需要记住这些原则,但它们值得注意。当您开始编写更好的代码时,您可能会发现自己很自然地遵循了这些原则。

12. 不要重复造轮子

优秀编码最重要的原则之一是不要重复造轮子。这意味着您应该尽可能使用现有的库、工具和框架,而不是从头编写自己的代码。

有许多理由遵循这一原则。首先,它节省你的时间。您不必编写已经编写好的代码。其次,它减少了您必须维护的代码量。第三,它增加了其他人发现并修复现有代码中的任何bug的机会。

当然,这条规则也有例外。如果你需要的东西目前还不存,你就必须自己创造。但一般来说,尽可能重用现有代码是最好的。

13.使用版本控制系统

版本控制系统是一种工具,它允许您跟踪代码随时间的变化。

这对于恢复到以前的代码版本,或者查看谁在何时对代码进行了更改,都是很有帮助的。使用版本控制系统还可以帮助改进协作,因为它允许多个人员同时处理相同的代码库。

目前有几种不同的版本控制系统,其中最流行的包括Git和Mercurial。

建议学习Git,因为您可以放心地假设您将来加入的大多数团队都将使用它。

GitHub是一个流行的在线服务,它为Git存储库提供基于web的界面。它构建在Git之上,是当今最流行的用于代码协作的服务团队之一。即使是初学者,你也可能遇到过这种情况。

如果你有兴趣了解更多关于版本控制的知识,我们建议你看看下面的一些资源:

总结

编写好的代码对任何开发人员来说都是一项重要的技能,但这需要时间和实践才能掌握。

如果你刚刚开始,这篇文章中的技巧将帮助你马上写出更好的代码。

当你继续提高你的技能时,把这些建议记在心里,必要时再参考它们。通过练习,你很快就会写出很棒的代码!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值