Dependency injection is a software design pattern in which one or more dependencies (or services) are injected, or passed by reference, into a dependent object.
Причины для использования Dependency Injection
Развязка
Внедрение зависимостей делает ваши модули менее связаны приводит к более обслуживаемой кода.
Легче модульного тестирования
Вместо того чтобы использовать жестко закодированные зависимостей вы можете передать их в модуль вы хотели бы использовать. С этой картины в большинстве случаев, вы не должны использовать модули, как proxyquire.
Ускорение разработки
С инъекции зависимостей, после интерфейсы определены легко работать без каких-либо конфликтов слияния.
Как использовать Dependency Injection используя Node.js
Во-первых, давайте взглянем на то, как вы могли бы написать свои приложения без использования инъекции зависимостей, и как бы вы преобразовать его.
Образец модуля без dependency injection
// team.js
var User = require('./user');
function getTeam(teamId) {
return User.find({teamId: teamId});
}
module.exports.getTeam = getTeam;
Простой тест будет выглядеть так:
// team.spec.js
var Team = require('./team');
var User = require('./user');
describe('Team', function() {
it('#getTeam', function* () {
var users = [{id: 1, id: 2}];
this.sandbox.stub(User, 'find', function() {
return Promise.resolve(users);
});
var team = yield team.getTeam();
expect(team).to.eql(users);
});
});
То, что мы сделали здесь является то, что мы создали файл с именем team.js
, которые могут возвращать список пользователей, которые принадлежат к одной команде. Для этого нам потребуется модель User
, так что мы можем вызвать его метод, который возвращает find
список пользователей.
Выглядит хорошо, не так ли? Но когда дело доходит до тестирования, мы должны использовать тестовые заглушки с sinon.
В тестовом файле, мы должны потребовать модель User
, так что мы можем заглушки свой метод find
. Заметьте, что мы используем функцию песочницы здесь, так что мы не придется вручную восстановить исходную функцию после выполнения теста.
Sample module with dependency injection
/ team.js
function Team(options) {
this.options = options;
}
Team.prototype.getTeam = function(teamId) {
return this.options.User.find({teamId: teamId})
}
function create(options) {
return new Team(options);
}
Вы можете проверить это файл со следующим теста:
// team.spec.js
var Team = require('./team');
describe('Team', function() {
it('#getTeam', function* () {
var users = [{id: 1, id: 2}];
var fakeUser = {
find: function() {
return Promise.resolve(users);
}
};
var team = Team.create({
User: fakeUser
});
var team = yield team.getTeam();
expect(team).to.eql(users);
});
});
Хорошо, так как версия с инъекции зависимостей отличается от предыдущей? Первое, что можно заметить, является использование factory pattern: мы используем это, чтобы придать вариантов / зависимостей для вновь созданного объекта - это когда мы можем придать модели User
.
В тестового файла мы должны создать поддельный модель, которая будет представлять модель User
, то мы просто ввести это путем передачи его в create
функции Team
модели. Легко, не так ли?
Dependency Injection в реальных проектах
Вы можете найти примеры внедрения зависимостей в много проектов с открытым кодом. Например, большинство Express/Koa middlewares, которые вы используете в вашей повседневной работе использует ту же самую подход.
Express middlewares
var express = require('express');
var app = express();
var session = require('express-session');
app.use(session({
store: require('connect-session-knex')()
}));
Фрагмент кода выше, используя зависимость инъекций с заводской схеме: на сессии промежуточного мы передаем модуль connect-session-knex
- он должен реализовать интерфейс, что модуль session
будет звонить.
В этом случае модуль connect-session-knex
должен реализовать следующие методы:
- store.destroy(sid, callback)
- store.get(sid, callback)
- store.set(sid, session, callback)
No comments :
Post a Comment