次のリファクタリングに標準化された名前があるかどうか疑問に思っています:
class Foo:
def do_something_awesome(self):
my_bar = Bar(42)
return my_bar.reticulate_splines()
ここで、クラスFoo
は、クラスBar
に明示的に結合されています。これは、そのクラス名に依存してmy_bar
オブジェクトを作成するためです。この明示的な結合が気に入らない場合は、
class Foo:
def __init__(self, bar_generator):
self.bar_generator = bar_generator
def do_something_awesome(self):
my_bar = self.bar_generator.create_bar(42)
return my_bar.reticulate_splines()
Martin FowlerのリファクタリングブックまたはKerievskiのパターンブックへのリファクタリングブックでこれを読んだと誓うことができますが、見つからないようです。
それとは別に、これは合理的なリファクタリングと見なされますか?私はそれがファクトリオブジェクトと依存性注入の混合だと感じています。
あなたのbar_generator
はファクトリーと呼ばれ、そのような「注入された」ファクトリーを使用するようにクラスFoo
を設計することは(オブジェクトを独自に構築する代わりに)「依存性注入」と呼ばれます-これがすでに述べた。ただし、これはリファクタリング手順の呼び出し方法ではありません。
ファウラーのリファクタリングカタログ を見ると、変換は3つのステップで達成できます。
コンストラクターをファクトリー関数で置き換える は、bar
の作成を新しいメンバー関数create_bar
に抽出しますが、Foo
の中にあります
関数をコマンドで置換 は、create_bar
を新しく作成されたクラスbar_generator
に移動します。それでもbar_generator
はFoo
内に作成されます。
Parameterize Function は、bar_generator
をそのパラメーターにするコンストラクターに適用できます。
それとは別に、これは合理的なリファクタリングと見なされますか?
Bar
からの分離が合理的な目的を満たしている場合、それは妥当です。 「私はこの明示的な結合が好きではありません」私見は非常に弱い理由です。 "明示的なカップリングはクラスのユニットテストを妨げる"または "明示的なカップリングは異なるコンテキストでの再利用を防ぐ"たとえば、より良い理由です。
総称名で区別することは困難ですが、bar_generator
がポリモーフィックオブジェクトを返さない場合、つまり複数の異なるタイプのオブジェクトを返さない場合、実際にはファクトリオブジェクトではない可能性があります。純粋な形のファクトリオブジェクトは、ポリモーフィズムと組み合わせて使用されます。それらが返すオブジェクトは通常、インターフェースまたは抽象クラスにキャストされ、具象型は実行時に決定されます。
my_bar
のタイプが実行時に変更されず、常に同じタイプである場合、Service Locatorこの(アンチ)パターンのより良い名前かもしれません。これは必ずしもアンチパターンではありませんが、概念的なコードを考えると、アンチパターンのように見えます。
bar_generator.create_bar
がFooクラス自体からのランタイムデータを必要としない場合は、従来の依存関係注入がより優れた手法になります。
foo = Foo()
bar = Bar(42)
foo.do_something_awesome(bar)
Bar
オブジェクトがdo_something_awesome
でのみ必要な場合は、クラスのフィールドではなく、メソッドの引数にすることを検討してください。クラス全体ではなく、methodの依存関係と考えてください。