发布于 2026-01-06 9 阅读
0

编写简洁高效代码的 3 个技巧

编写简洁高效代码的 3 个技巧

原文发表于deepu.tech

软件工程最重要的方面之一是代码质量,而代码的可读性和可维护性是其中最重要的标准之一,尤其是在团队合作中,其他成员需要阅读和理解你的代码。在我看来,最好的代码无需任何解释或文档,即使是完全的初学者也能轻松阅读和理解。

编写复杂晦涩的代码很容易,而编写简洁易读的代码则难得多。

很容易就会得意忘形,写出冗长复杂的函数和代码,炫耀自己的聪明才智,尤其是对于初学者来说,为了给同伴留下深刻印象,往往会追求极致的效率。但所谓的“最聪明”未必是最易读、最易维护的。在我看来,写出易读、易维护的代码并不需要太多的技巧,但编写简洁清晰、易于阅读和维护的代码却需要技巧。这并非一朝一夕就能掌握的技能,而是需要多年积累才能形成的。

以下是一些提高代码效率、可读性、易导航性和可维护性的技巧。这并非一份详尽的清单,仅列举了一些可能有所帮助的方法。

1. 快速且尽早失败

编写任何逻辑时,尽量尽早进行失败断言,并快速失败。这样可以提升程序运行速度,避免先执行大量代码,最后却因为一些本可以提前检查的问题而失败。这种方法还能使代码更易于理解,因为它能更清晰地表达意图。

请看下面的函数,为了简单起见,我们使用 NodeJS 上的 JavaScript。请注意,为了简单起见,我使用了 NodeJS 文件系统 API 中的同步方法。

function processFile(filePath) {
  if (fs.existsSync(filePath)) {
    // check if file exists
    var fileContent = fs.readFileSync(filePath, "utf8"); // read the file content

    if (fileContent !== "") {
      console.log("Content found");
      // do stuff
    } else {
      throw Error("No content found on file!");
    }
  } else {
    throw Error("File not found!");
  }
}
Enter fullscreen mode Exit fullscreen mode

我们正在获取给定的文件并对其进行一些处理。如果文件不存在或内容为空,则抛出错误。这种方法本身没有问题,但如果处理步骤很多,读者必须先阅读所有步骤才能看到错误处理,因此意图不够清晰。此外,由于使用了多个 if/else 语句,函数的圈复杂度也更高。请考虑以下相同函数的版本。

function processFile(filePath) {
  if (!fs.existsSync(filePath)) {
    // check if file does not exist
    throw Error("File not found!");
  }

  var fileContent = fs.readFileSync(filePath, "utf8"); // read the file content

  if (fileContent === "") {
    throw Error("No content found on file!");
  }

  console.log("Content found");
  // do stuff
}
Enter fullscreen mode Exit fullscreen mode

这段代码逻辑相同,但更简洁易读,圈复杂度更低,意图也更清晰。

2. 提前返回

与尽早失败类似,尽早返回也更加理想,即利用语言基于返回值来控制代码执行流程的功能,以降低代码复杂度,提高代码可读性和意图表达。请考虑将以下逻辑添加到我们的函数中。

function processFile(filePath) {
    ...
    console.log("Content found");

    // check if the file content is base64 encoded: Lib used https://github.com/miguelmota/is-base64
    if (isBase64(fileContent.trim())) {
        console.log("Decoding content");
        // check if the base64 content is image and return a placeholder
        if (isBase64(fileContent.trim(), { allowMime: true })) {
            return "Image content";
        } else {
            // decode to string
            var buffer = Buffer.from(fileContent, "base64");
            var decoded = buffer.toString("ascii");
            return decoded;
        }
    } else {
        return fileContent;
    }
}
Enter fullscreen mode Exit fullscreen mode

该逻辑会检查内容是否经过 Base64 编码,如果不是,则对其进行解码。该函数运行正常,但也可以考虑以下版本。

function processFile(filePath) {
    ...
    console.log("Content found");

    // check if the base64 content is image and return a placeholder
    if (isBase64(fileContent, { allowMime: true })) {
        return "Image content";
    }
    // check if the file content is not base64 encoded: Lib used https://github.com/miguelmota/is-base64
    if (!isBase64(fileContent.trim())) {
        return fileContent;
    }

    console.log("Decoding content");
    // decode to string
    var buffer = Buffer.from(fileContent, "base64");
    var decoded = buffer.toString("ascii");
    return decoded;
}
Enter fullscreen mode Exit fullscreen mode

这样岂不是更简单易懂吗?所以尽量尽早返回,保持代码流程简洁。

3. 编写小而精炼的函数

最后,即使你采用命令式编程风格,也不要编写过于庞大的函数,尽量将其拆分成多个小函数。上面的例子虽然不是一个庞大的函数,但你仍然可以将其逻辑地拆分成两个部分,如下所示。

function decodeBase64(fileContent) {
    // check if the base64 content is image and return a placeholder
    if (isBase64(fileContent, { allowMime: true })) {
        return "Image content";
    }
    // check if the file content is not base64 encoded: Lib used https://github.com/miguelmota/is-base64
    if (!isBase64(fileContent.trim())) {
        return fileContent;
    }

    console.log("Decoding content");
    // decode to string
    var buffer = Buffer.from(fileContent, "base64");
    var decoded = buffer.toString("ascii");
    return decoded;
}

function processFile(filePath) {
    ...
    console.log("Content found");
    return decodeBase64(fileContent);
}
Enter fullscreen mode Exit fullscreen mode

拥有更小、更专注的功能有助于以下方面:

  • 单元测试变得更加容易。
  • 函数变得可重用和可组合。
  • 更容易集中注意力阅读,无需构建整个逻辑的心理模型。
  • 在小型函数中修改内容比在大型函数中修改内容更容易,因为你需要考虑的情况更少。
  • 更容易调试,也更容易发现错误。
  • 由于该功能专注于特定任务,因此副作用较少。

附加题:编写纯函数

这并非函数式编程的专属概念,尽管它因函数式编程而流行起来。一般来说,数据变更总是很棘手,可能导致意想不到的 bug。当我们尽量避免副作用(包括外部数据变更),保持函数的纯函数特性时,也能减少此类 bug 的发生几率。因此,请将纯函数与非纯函数分开,并尽可能多地编写纯函数。只有在不可避免的情况下,才在函数内部进行副作用和外部数据/状态变更。无论你遵循何种编程范式,都可以遵循这一原则。


如果您喜欢这篇文章,请点赞或留言。

你可以在TwitterLinkedIn上关注我。


封面图片来源:Unsplash用户Christopher Robin Ebbinghaus拍摄

文章来源:https://dev.to/deepu105/3-tips-for-clean-efficient-code-1ea8