适合您的下一个 Node.js 项目的完美架构流程
作者:皮耶罗·博雷利✏️
一位比我更睿智的人说过,好的开始是成功的一半。我想不出还有什么名言能更好地描述每个开发人员在开始一个新项目时所面临的处境。以实用的方式规划项目结构是开发过程中最难的环节之一,实际上也是一个微妙的环节。
通过查看我之前在 LogRocket上写的文章,我们可以定义一条关于讨论 Node.js 技术的路径,如何选择要使用的前端框架,现在我们可以尝试更深入地研究如何在决定要使用的技术堆栈后构建我们的 Web 应用程序。
良好建筑的重要性
在项目架构方面,拥有一个良好的起点对于项目本身的生命周期以及如何应对未来不断变化的需求至关重要。糟糕、混乱的项目架构通常会导致:
- 代码难以阅读且混乱,使得开发过程更长,产品本身更难测试
- 无用的重复,使代码更难维护和管理
- 新功能实现困难。由于结构可能变得一团糟,在不破坏现有代码的情况下添加新功能可能会成为一个真正的问题。
考虑到这些要点,我们都同意我们的项目架构极其重要,并且我们还可以声明几点,这些要点可以帮助我们确定这个架构必须帮助我们做什么:
- 实现干净且可读的代码
- 在我们的应用程序中实现可重用的代码片段
- 帮助我们避免重复
- 在我们的应用程序中添加新功能使生活变得更轻松
建立流程
现在我们可以讨论一下我通常所说的应用程序结构流程。应用程序结构流程是开发应用程序时要遵循的一套规则和通用实践。这些经验是我们多年使用某项技术的经验总结,我们了解哪些方法有效,哪些方法无效。
本文旨在创建一个快速参考指南,帮助您在开发 Node.js 应用程序时建立完美的流程结构。让我们开始定义规则:
规则 1:正确地将文件组织到文件夹中
在我们的应用中,所有东西都必须有它的位置,而文件夹是分组常见元素的最佳位置。特别地,我们要定义一个非常重要的分离,这就引出了规则#2:
规则 2:明确区分业务逻辑和 API 路由
瞧,像 Express.js 这样的框架真是太棒了。它们为我们提供了管理请求、视图和路由的强大功能。有了这样的支持,我们或许会忍不住把业务逻辑放到 API 路由里。但这很快就会让它们变成巨大的、单片的块,变得难以管理、难以阅读,而且容易分解。
也请不要忘记,我们的应用程序的可测试性将会降低,从而延长开发时间。此时,您可能会想:“那么,我们该如何解决这个问题?我应该把我的业务逻辑清晰、智能地放在哪里?” 答案就在规则3中。
规则3:使用服务层
这是我们所有业务逻辑应该存放的地方。它本质上是一个类的集合,每个类都有自己的方法,用于实现我们应用的核心逻辑。这一层中唯一需要忽略的部分是访问数据库的部分;这部分应该由数据访问层来管理。
现在我们已经定义了这三个初始规则,我们可以用图形方式表示结果如下:

然后,将我们带回到规则#1的后续文件夹结构可以变成:
通过查看最后一张图片,我们还可以在思考结构时建立另外两个规则。
规则 4:使用 config 文件夹保存配置文件
规则 #5:为长 npm 脚本创建一个脚本文件夹
规则#6:使用依赖注入
Node.js 确实充满了令人惊叹的功能和工具,让我们的生活更加轻松。然而,众所周知,由于可测试性和代码可管理性方面的问题,处理依赖关系在大多数情况下会非常麻烦。
有一个解决方案,称为依赖注入。
依赖注入是一种软件设计模式,其中将一个或多个依赖项(或服务)注入或通过引用传递到依赖对象中。
通过在我们的 Node 应用程序中使用它,我们:
- 拥有更简单的单元测试流程,将依赖项直接传递给我们想要使用的模块,而不是对其进行硬编码
- 避免无用的模块耦合,使维护更加容易
- 提供更快的 git 流。定义接口后,它们将保持原样,这样我们就可以避免任何合并冲突。

虽然方法简单,但作为代码实现方式仍然不够灵活。如果我们想修改这个测试,让它使用示例数据库,会发生什么?我们应该修改代码以适应新的需求。为什么不直接将数据库作为依赖项传递呢?
规则7:使用单元测试
现在我们已经掌握了依赖注入,接下来就可以为项目实现单元测试了。测试是应用程序开发中极其重要的一个阶段。项目的整个流程(而不仅仅是最终结果)都依赖于测试,因为错误的代码会减慢开发进度并导致其他问题。
测试应用程序的一种常见方法是按单元进行测试,其目标是隔离一段代码并验证其正确性。在过程式编程中,单元可以是一个单独的函数或过程。此过程通常由编写代码的开发人员执行。
这种方法的好处包括:
提高代码质量
单元测试可以提高代码质量,帮助你在代码进入其他开发阶段之前发现可能被忽略的问题。它可以暴露边缘情况,让你编写出更好的整体代码。
更早发现错误
这里的问题在很早的阶段就能发现。由于测试将由编写代码的开发人员执行,因此可以更早地发现错误,并且您将能够避免极其耗时的调试过程。
降低成本
应用程序中的缺陷越少,调试时间就越少,而调试时间越少,项目成本就越低。时间在这里尤其重要,因为宝贵的开发时间现在可以用于开发产品的新功能。
规则#8:使用另一层进行第三方服务调用
在我们的应用程序中,我们经常需要调用第三方服务来检索某些数据或执行某些操作。然而,如果我们不将这些调用分离到另一个特定的层,我们可能会遇到失控的代码,导致其变得过于庞大而难以管理。
解决这个问题的常用方法是使用发布/订阅模式。这种机制是一种消息传递模式,其中发送消息的实体称为发布者,接收消息的实体称为订阅者。
发布者不会将消息直接发送给特定的接收者。相反,他们会将已发布的消息分类到特定的类别中,而无需知道哪些订阅者(如果有的话)正在处理这些消息。
类似地,订阅者将表达对处理一个或多个类别的兴趣,并且只接收他们感兴趣的消息——而完全不知道有哪些发布者。
发布-订阅模型支持事件驱动架构和异步并行处理,同时提高性能、可靠性和可扩展性。
规则#9:使用 linter
这个简单的工具将帮助您执行更快、更好的整体开发过程,帮助您关注小错误,同时保持整个应用程序代码的统一。

规则10:使用样式指南
还在为如何以一致的方式正确格式化代码而苦恼吗?不妨借鉴一下Google或Airbnb提供的优秀代码风格指南。这样一来,阅读代码将变得异常轻松,你也不会再为如何正确定位花括号而感到沮丧。

规则#11:始终注释你的代码
写一段很难理解的代码,尤其是让人难以理解代码背后的原因?千万别忘了给它加注释。这对你的同事和未来的自己都非常有用,因为他们都会在你第一次写完代码六个月后,仍然想知道你为什么要这么做。
规则#12:关注文件大小
过长的文件极难管理和维护。请始终关注文件长度,如果文件过长,请尝试将其拆分成多个模块,并将它们打包到文件夹中,形成相互关联的文件。
规则#13:始终使用 gzip 压缩
服务器可以使用 gzip 压缩来减小文件大小,然后再将其发送到 Web 浏览器。这将减少延迟和卡顿。

规则 #14:使用承诺
使用回调是 JavaScript 中处理异步代码最简单的机制。然而,原始回调通常会牺牲应用程序的控制流、错误处理和语义,而这些正是我们在使用同步代码时所熟悉的。一个解决方案是在 Node.js 中使用 Promise。
Promises 的优点多于缺点,因为它使我们的代码更易于阅读和测试,同时仍然提供函数式编程语义以及更好的错误处理平台。

规则 #15:使用 Promise 的错误处理支持
我可以保证,当你的应用出现意外错误或行为时,绝对不会令人愉快。编写代码时,错误是不可避免的。这只是人之常情。
处理它们是我们的责任,我们不仅应该在我们的应用程序中使用承诺,还应该利用 catch 关键字提供的错误处理支持。
结论
创建 Node.js 应用程序可能具有挑战性,我希望这套规则能够帮助您在确定要使用哪种类型的架构以及哪些实践将支持该架构时找到正确的方向。
编者注:觉得这篇文章有什么问题?您可以在这里找到正确版本。
插件:LogRocket,一个用于 Web 应用的 DVR
LogRocket是一款前端日志工具,可让您重播问题,就像它们发生在您自己的浏览器中一样。无需猜测错误发生的原因,也无需要求用户提供屏幕截图和日志转储,LogRocket 让您重播会话,快速了解问题所在。它可与任何应用程序完美兼容,不受框架限制,并且提供插件来记录来自 Redux、Vuex 和 @ngrx/store 的额外上下文。
除了记录 Redux 操作和状态外,LogRocket 还记录控制台日志、JavaScript 错误、堆栈跟踪、带有标头 + 正文的网络请求/响应、浏览器元数据以及自定义日志。它还会对 DOM 进行插桩,以记录页面上的 HTML 和 CSS,即使是最复杂的单页应用程序,也能重现像素完美的视频。
免费试用。
您的下一个 Node.js 项目的完美架构流程一文首先出现在LogRocket 博客上。
文章来源:https://dev.to/bnevilleoneill/the-perfect-architecture-flow-for-your-next-node-js-project-1ail