Created
April 4, 2018 15:34
-
-
Save takasek/2cbb7be66fe6d91c412985b0456cbc6c to your computer and use it in GitHub Desktop.
依存グラフの解決を行うオブジェクトが必要な理由 #CodePiece
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
do { | |
struct A {} | |
struct B { let a: A } | |
struct C { let b: B } | |
// 何もしないと、「AをinjectしたC」を作りたいときこうなる | |
let c = C(b: B(a: A())) | |
// 「CがBに依存している」という知識は、本来Cを使う場合は不要なはず | |
// そのため、依存グラフを解決する Resolver を考える | |
struct Resolver { | |
func resolveC(a: A) -> C { | |
return C(b: B(a: a)) | |
} | |
} | |
let c2 = Resolver().resolveC(a: A()) | |
// これで、依存グラフについての知識をこのコードから排除できた | |
} | |
do { | |
struct A {} | |
struct X { let a: A } // 中間層 X が生まれたとする | |
struct B { let x: X } | |
struct C { let b: B } | |
// 「AをinjectしたC」を作るコードは以下のように変更しなければならない | |
//let c = C(b: B(a: A())) | |
let c = C(b: B(x: X(a: A()))) | |
// これは、「CがBやXに依存している」という知識をこのコードが持ってしまっているから。 | |
// 依存解決の責務を Resolver に逃がしていれば、コードに変更は起こらない。 | |
// 変更の影響範囲は Resolver 内に留められる。 | |
let c2 = Resolver().resolveC(a: A()) | |
} |
補足ですが、もし、どうしても C と A の結合を残したいのならば、次のように C を設計します:
do {
struct A {}
struct B {}
struct C {
let b: B
init(a: A) { self.b = B(a: a) }
}
let c = C(a: A())
}
最初に提示していただいたケースでは B に別のものを使わないことが前提となっていますから、この書き方でも問題ないはずです。
となると、「CとAの結合は残したい」場合は「Bを除いたCの単体テストは行わない」ということでしょうか?
……と思いましたが、イニシャライザを複数用意すればいいだけですね。なるほど。
do {
struct A {}
protocol B {}
struct BImpl: B { ... }
struct BStub: B { ... }
struct C {
let b: B
init(a: A) { self.b = BImpl(a: a) }
init(b: B) { self.b = b }
}
let c = C(a: A())
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
この例ですが、これが単体テストなら 私は以下のようにします:
なお、B をテストダブルへと置き換えられない理由があるならば、この例は使えません。
ただし、私の経験則では、単体テストであるオブジェクトをテストダブルへと置き換えられない場合、設計を間違っていることが多いです。
間違っている原因は責務過多/密接合/CQSができてないのいずれかです。
また、単体テストではなく結合テストをしたいのならば、下のように書きますね:
これは組み合わせのテストですから、どのような組み合わせでテストしたいのかが明示されるべきだからです。