bottlejs
を使うと最小構成ぐらいの DI ができる (js)
var Barley = function() {};
var Hops = function() {};
var Water = function() {};
var Beer = function(barley, hops, water) { /* A beer service, :yum: */ };
(js)
var bottle = new Bottle();
bottle.service('Barley', Barley);
bottle.service('Hops', Hops);
bottle.service('Water', Water);
bottle.service('Beer', Beer, 'Barley', 'Hops', 'Water');
request
とかを使って外部と通信するようなモジュールをテストする場合、sinon
とかで fakeserver
を作ったりして試すことになるとおもうんだけど、そもそも request
自体を差し替え可能にしておくことでこれをしなくてよくなる。 (coffee)
module.exports = class Some
constructor: (@request)->
get: (url)->
@request url, (err, res, body)-> # ...
lib/some.coffee
を用意して (coffee)
bottle = new Bottle()
bottle.service 'request', -> require 'request'
bottle.service 'Some', require('./lib/some'), 'request'
bottle.container.Some.get url
request
を注入することができる。テストでは (coffee)
describe 'Some', ->
it 'blah blah', ->
bottle = new Bottle()
bottle.service 'request', -> (str, callback)-> callback null, null, 'fake response'
bottle.service 'Some', require('./lib/some'), 'request'
bottle.container.Some.get # ...
request
がエラったときを試したいときは (coffee)
bottle.service 'request', -> (str, callback)-> callback new Error('blah')
require
が相対パスで解決されるのが困る問題をちょっと緩和できる]require
はモジュール名でない場合相対パスで解決されるので「あれ?あのモジュールってこのファイルからだとどうなるんだっけ...」みたいなのが発生する。これが bottlejs
だと依存モジュールをその場で呼び出すことになるのでちょっと緩和できる(とおもう)。_
|--- index.coffee
|--- client
|--- model
|--- some.coffee
|--- controller
|--- some.coffee
|--- util
|--- some.coffee
(coffee)
module.exports = class SomeController
constructor: ->
@model = require '../model/some'
@someutil = require '../../util/some'
SomeController
側では (coffee)
module.exports = class SomeController
constructor: (@model, @someutil)->
(coffee)
bottle = new Bottle()
bottle.service 'SomeUtil', require './util/some'
bottle.service 'SomeModel', require './client/model/some'
bottle.service 'SomeController', require './client/controller/some', 'SomeModel', 'SomeUtil'
constructor
に依存の解決系を書いて各メソッドでそれらを使ったコードを書くみたいな感じで書けるのでスッキリしていい。bottle =...
みたいな依存管理系のコードが増えるので記述量自体は増えるとおもう。require
していれば、呼び出し元がそのモジュールがどんなモジュールに依存してるかを知らなくても呼び出すことができるが、上のようなコードスタイルにすると呼び出す前に依存を解決しないといけなくなるので呼び出すモジュールがなにに依存してるか確認してそれを注入してやらないといけなくなる手間が発生する。