问题描述
我使用单独的路由器文件作为主应用程序和身份验证应用程序的模块.我无法获得将变量(数据库客户端)传递到路由器的最佳方法.我不想硬编码或传递它:
module.exports = function(app, db) {
也许使用单例寄存器或使用全局 db 变量是最好的方法?
您对设计模式有何经验?哪种方式最好,为什么?
推荐答案
我发现使用依赖注入,传递东西,是最好的风格.它确实看起来像你有的东西:
// App.js module.exports = function App() { }; // Database.js module.exports = function Database(configuration) { }; // Routes.js module.exports = function Routes(app, database) { }; // server.js: composition root var App = require("./App"); var Database = require("./Database"); var Routes = require("./Routes"); var dbConfig = require("./dbconfig.json"); var app = new App(); var database = new Database(dbConfig); var routes = new Routes(app, database); // Use routes.
这有很多好处:
- 它迫使您将系统分成具有明确依赖关系的组件,而不是将依赖关系隐藏在文件中间的某个位置,它们调用 require("databaseSingleton") 或更糟糕的是,global.database.
- 它使单元测试变得非常容易:如果我想单独测试 Routes,我可以使用伪造的 app 和 database 参数注入它,并且只测试 Routes 代码本身.
- 它将所有对象图连接放在一个地方,即组合根(在本例中是 server.js,即应用程序入口点).这使您可以在一个地方查看所有内容如何在系统中组合在一起.
我见过的更好的解释之一是对马克·西曼的采访,.NET 中的依赖注入一书的作者.它同样适用于 JavaScript,尤其是 Node.js:require 通常用作经典的服务定位器,而不仅仅是模块系统.
问题描述
I use separate router files as modules for main app and auth app. I can't get the best way to pass variables(db client) into routers. I don't want to hardcode it or pass it with:
module.exports = function(app, db) {
Maybe it's best way to use singleton register or use global db variable?
What is your experiense with design-patterns? Which way is the best and why?
推荐答案
I have found using dependency injection, to pass things in, to be the best style. It would indeed look something like you have:
// App.js module.exports = function App() { }; // Database.js module.exports = function Database(configuration) { }; // Routes.js module.exports = function Routes(app, database) { }; // server.js: composition root var App = require("./App"); var Database = require("./Database"); var Routes = require("./Routes"); var dbConfig = require("./dbconfig.json"); var app = new App(); var database = new Database(dbConfig); var routes = new Routes(app, database); // Use routes.
This has a number of benefits:
- It forces you to separate your system into components with clear dependencies, instead of hiding the dependencies somewhere in the middle of the file where they call require("databaseSingleton") or worse, global.database.
- It makes unit testing very easy: if I want to test Routes in isolation, I can inject it with fake app and database params and test only the Routes code itself.
- It puts all your object-graph wiring together in a single place, namely the composition root (which in this case is server.js, the app entry point). This gives you a single place to look to see how everything fits together in the system.
One of the better explanations for this that I've seen is an interview with Mark Seeman, author of the excellent book Dependency Injection in .NET. It applies just as much to JavaScript, and especially to Node.js: require is often used as a classic service locator, instead of just a module system.