在此依赖注入示例中,控制反转出现在哪里?
Where does Inversion of Control arise during this example of Dependency Injection?
我完全糊涂了。关于依赖注入和控制反转的定义,有许多来源相互矛盾。这是我的理解要点,没有太多额外的细节,在大多数情况下让事情对我来说更复杂:依赖注入意味着我的函数不是召唤所需的依赖,而是将依赖作为参数提供。控制反转意味着,例如,当您使用一个框架时,它是调用您的用户区代码的框架,并且控制被反转,因为在 'default' 情况下,您的代码将调用库中的特定实现。
现在据我了解,不知何故,因为我的函数不再让人联想到依赖关系,而是将其作为参数,当我像下面这样使用依赖注入时,控制反转神奇地发生了。
所以这里是我为自己写的一个愚蠢的例子来围绕这个想法:
getTime.js
function getTime(hour) {
return `${hour} UTC`
}
module.exports.getTime = getTime
welcome.js
function welcomeUser(name, hour) {
const getTime = require('./time').getTime
const time = getTime(`${hour} pm`)
return(`Hello ${name}, the time is ${time}!`)
}
const result = welcomeUser('Joe', '11:00')
console.log(result)
module.exports.welcomeUser = welcomeUser
welcome.test.js
const expect = require('chai').expect
const welcomeUser = require('./welcome').welcomeUser
describe('Welcome', () => {
it('Should welcome user', () => {
// But we would want to test how the welcomeUser calls the getTime function
expect(welcomeUser('Joe', '10:00')).to.equal('Hello Joe, the time is 10:00 pm UTC!')
})
})
现在的问题是getTime函数的调用是在welcome.js函数中实现的,无法被测试拦截。我们想做的是测试 getTime 函数是如何被调用的,但我们不能这样做。
另一个问题是 getTime 函数几乎是硬编码的,所以我们不能模拟它,这可能很有用,因为我们只想单独测试 welcomUser 函数,因为这是单元测试的使用(getTime 函数例如,可以同时实施)。
所以主要的问题是代码是紧密耦合的,它更难测试,而且到处都是破坏。现在让我们使用依赖注入:
getTime.js
function getTime(hour) {
return `${hour} UTC`
}
module.exports.getTime = getTime
welcome.js
const getTime = require('./time').getTime
function welcomeUser(name, hour, dependency) {
const time = dependency(hour)
return(`Hello ${name}, the time is ${time}!`)
}
const result = welcomeUser('Joe', '10:00', getTime)
console.log(result)
module.exports.welcomeUser = welcomeUser
welcome.test.js
const expect = require('chai').expect
const welcomeUser = require('./welcome').welcomeUser
describe('welcomeUser', () => {
it('should call getTime with the right hour value', () => {
const fakeGetTime = function(hour) {
expect(hour).to.equal('10:00')
}
// 'Joe' as an argument isn't even neccessary, but it's nice to leave it there
welcomeUser('Joe', '10:00', fakeGetTime)
})
it('should log the current message to the user', () => {
// Let's stub the getTime function
const fakeGetTime = function(hour) {
return `${hour} pm UTC`
}
expect(welcomeUser('Joe', '10:00', fakeGetTime)).to.equal('Hello Joe, the time is 10:00 pm UTC!')
})
})
据我了解,我上面所做的是依赖注入。多个消息来源声称,如果没有控制反转,依赖注入是不可能的。但是控制反转在哪里出现?
还有常规的 JavaScript 工作流程,您只需全局导入依赖项并稍后在您的函数中使用它们,而不是在函数内部要求它们或将其作为参数提供给它们?
查看 Martin Fowler 关于 IoC 和 DI 的文章。 https://martinfowler.com/articles/injection.html
IoC:非常通用的词。这种反转可以通过多种方式发生。
DI:可以看成是这个通用词IoC的一个分支。
所以在你的代码中,当你具体实现 DI 时,有人会说你的代码在 DI 的风格中具有这种 IoC 的一般概念。真正相反的是,寻找行为的默认方式(默认方式是在方法中编写它,相反的方式是从外部注入行为)。
我完全糊涂了。关于依赖注入和控制反转的定义,有许多来源相互矛盾。这是我的理解要点,没有太多额外的细节,在大多数情况下让事情对我来说更复杂:依赖注入意味着我的函数不是召唤所需的依赖,而是将依赖作为参数提供。控制反转意味着,例如,当您使用一个框架时,它是调用您的用户区代码的框架,并且控制被反转,因为在 'default' 情况下,您的代码将调用库中的特定实现。
现在据我了解,不知何故,因为我的函数不再让人联想到依赖关系,而是将其作为参数,当我像下面这样使用依赖注入时,控制反转神奇地发生了。
所以这里是我为自己写的一个愚蠢的例子来围绕这个想法:
getTime.js
function getTime(hour) {
return `${hour} UTC`
}
module.exports.getTime = getTime
welcome.js
function welcomeUser(name, hour) {
const getTime = require('./time').getTime
const time = getTime(`${hour} pm`)
return(`Hello ${name}, the time is ${time}!`)
}
const result = welcomeUser('Joe', '11:00')
console.log(result)
module.exports.welcomeUser = welcomeUser
welcome.test.js
const expect = require('chai').expect
const welcomeUser = require('./welcome').welcomeUser
describe('Welcome', () => {
it('Should welcome user', () => {
// But we would want to test how the welcomeUser calls the getTime function
expect(welcomeUser('Joe', '10:00')).to.equal('Hello Joe, the time is 10:00 pm UTC!')
})
})
现在的问题是getTime函数的调用是在welcome.js函数中实现的,无法被测试拦截。我们想做的是测试 getTime 函数是如何被调用的,但我们不能这样做。 另一个问题是 getTime 函数几乎是硬编码的,所以我们不能模拟它,这可能很有用,因为我们只想单独测试 welcomUser 函数,因为这是单元测试的使用(getTime 函数例如,可以同时实施)。
所以主要的问题是代码是紧密耦合的,它更难测试,而且到处都是破坏。现在让我们使用依赖注入:
getTime.js
function getTime(hour) {
return `${hour} UTC`
}
module.exports.getTime = getTime
welcome.js
const getTime = require('./time').getTime
function welcomeUser(name, hour, dependency) {
const time = dependency(hour)
return(`Hello ${name}, the time is ${time}!`)
}
const result = welcomeUser('Joe', '10:00', getTime)
console.log(result)
module.exports.welcomeUser = welcomeUser
welcome.test.js
const expect = require('chai').expect
const welcomeUser = require('./welcome').welcomeUser
describe('welcomeUser', () => {
it('should call getTime with the right hour value', () => {
const fakeGetTime = function(hour) {
expect(hour).to.equal('10:00')
}
// 'Joe' as an argument isn't even neccessary, but it's nice to leave it there
welcomeUser('Joe', '10:00', fakeGetTime)
})
it('should log the current message to the user', () => {
// Let's stub the getTime function
const fakeGetTime = function(hour) {
return `${hour} pm UTC`
}
expect(welcomeUser('Joe', '10:00', fakeGetTime)).to.equal('Hello Joe, the time is 10:00 pm UTC!')
})
})
据我了解,我上面所做的是依赖注入。多个消息来源声称,如果没有控制反转,依赖注入是不可能的。但是控制反转在哪里出现?
还有常规的 JavaScript 工作流程,您只需全局导入依赖项并稍后在您的函数中使用它们,而不是在函数内部要求它们或将其作为参数提供给它们?
查看 Martin Fowler 关于 IoC 和 DI 的文章。 https://martinfowler.com/articles/injection.html
IoC:非常通用的词。这种反转可以通过多种方式发生。
DI:可以看成是这个通用词IoC的一个分支。
所以在你的代码中,当你具体实现 DI 时,有人会说你的代码在 DI 的风格中具有这种 IoC 的一般概念。真正相反的是,寻找行为的默认方式(默认方式是在方法中编写它,相反的方式是从外部注入行为)。