C#
私の選択した言語で申し訳ありませんが、私は読むことJava
ができますが、おそらくそれを書こうとする構文を破壊します...同じ概念がとの間C#
にJava
も当てはまります。テスト可能。
与えられた:
public class MyUI
{
public void SomeMethod()
{
Foo foo = new Foo();
foo.DoStuff();
}
}
public class Foo
{
public void DoStuff()
{
Bar bar = new Bar();
bar.DoSomethingElse();
}
}
public class Bar
{
public void DoSomethingElse();
}
IOCコンテナーを使用せずに、DIを使用するように簡単にリファクタリングできます。さらに、いくつかの手順に分解することもできます。
(潜在)ステップ1-依存関係を取り込みますが、呼び出し(UI)コードに変更はありません。
public class MyUI
{
public void SomeMethod()
{
Foo foo = new Foo();
foo.DoStuff();
}
}
public class Foo
{
private IBar _iBar;
// Leaving this constructor for step one,
// so that calling code can stay as is without impact
public Foo()
{
_iBar = new Bar();
}
// simply because we now have a constructor that take's in the implementation of the IBar dependency,
// Foo can be much more easily tested.
public Foo(IBar iBar)
{
_iBar = iBar;
}
public void DoStuff()
{
_iBar.DoSomethingElse();
}
}
public interface IBar
{
void DoSomethingElse();
}
public class Bar
{
public void DoSomethingElse();
}
リファクタリング2(IOCコンテナを実装して呼び出しコードをすぐに変更する場合は最初のリファクタリング):
public class MyUI
{
public void SomeMethod()
{
Foo foo = null // use your IOC container to resolve the dependency
foo.DoStuff();
}
}
public class Foo
{
private IBar _iBar;
// note we have now dropped the "default constructor" - this is now a breaking change as far as the UI is concerned.
// You can either do this all at once (do only step 2) or in a gradual manner (step 1, then step 2)
// Only entry into class - requires passing in of class dependencies (IBar)
public Foo(IBar iBar)
{
_iBar = iBar;
}
public void DoStuff()
{
_iBar.DoSomethingElse();
}
}
ステップ2は技術的には単独で行うこともできますが、(潜在的に)はるかに多くの作業になる可能性があります-DIに求めている機能を現在「更新」しているクラスの数によって異なります。
ステップ1->ステップ2のルートを使用することを検討してください-とはFoo
無関係に、の単体テストを作成できますBar
。一方、ステップ1のリファクタリングの前は、両方のクラスの実際の実装を使用せずに簡単に達成することはできませんでした。ステップ1->ステップ2(すぐにステップ2ではなく)を実行すると、時間の経過に伴う小さな変更が可能になり、リファクタリングが問題なく機能することを確実にするために、テストハーネスを開始できます。