一个简单的问题。我试图将我的node.js应用程序拆分为依赖于特性或功能的相关模块。例如。用于读取日志文件的日志读取模块,用于与IRC机器人等一起工作的IRC模块。
我目前使用全局事件发射器模块将所有内容绑定在一起,该模块执行需要传递的所有消息的所有管道,例如我想要输入到我的数据库的日志条目。
这一段时间以来一直运行良好但我已经到了这样的程度,我觉得我需要开始需要一些功能模块来完成其他工作。我想远离紧密耦合(因此事件模块),但是真的有什么不好吗?
在查看其他一些node.js项目时,我经常会看到一个app.js文件,其中需要10个左右的其他模块,其中看起来试图在一个地方做所有事情。我试图保持我的轻松和易读。你有没有想过这个做得好的例子?
答案 0 :(得分:1)
我遇到的最好的经验法则是:模块是否可以单独测试?我可以要求模块并从测试用例中调用它的功能吗?如果模块依赖于其他模块,那么用模拟模块来模拟这些模块有多难?
在我看来,可测性是关注点良好分离的最佳指标。如果你的模块确实需要十个其他模块,那也没关系。即使你实际上没有花时间编写测试,我也会始终保持可测试性。
即使只是保持测试打开的选项总比没有好,它对于模块的专业化程度是一个有用的指南。如果你有三个模块而你不能使用另一个模块,那么它们可能属于一个模块。或者这三个模块可能很大,在拆分时更容易导航;对于那种情况,我通常会创建一个包装模块。
我创建了一个具有相关名称的目录,并在其中抛出一个index.js
文件,该文件需要其他三个模块(或者我需要的任何东西)。然后从我的应用程序的其余部分,我可以访问该模块,就好像它是一个专门的API,即使在内部它很复杂并分成多个子模块。包装器模块从我的应用程序的其余部分隐藏了这些混乱,这样我仍然可以模块化,同时保持API简单。这是一个很好的解决方法,适用于将组合到一个模块中的东西过于混乱并且在拆分配置中使用模块时也很混乱的情况。
如果模块足够通用(如果可能的话我通常会这样做),那么我经常将它作为独立模块发布到NPM。然后我就像在NPM上的任何其他模块一样在我的项目中要求它。例如,我一直在编写一个脚本来将我的所有mongoose模型加载到一个db
对象中以便于访问。代码将循环遍历项目根目录的dbmodels
目录中的mongodb模型文件。它需要模块,用mongoose注册模型数据,并生成一个我可以使用的简单db
对象(例如db.User.findOne({ username: 'munkee' }, function (err, user) { ... }
)。
我没有继续将相同的代码块复制并粘贴到我构建的每个项目中,而是创建了一个名为mongoose-simpledb的通用NPM模块。如果你看the code for that module,你会发现它并不复杂。它虽然通用且有用,但我认为它应该在NPM注册表中占有一席之地。它使新项目中的事情变得容易多了。其他人发现它也很有用只是一个很好的奖励:)