web-dev-qa-db-ja.com

クラス内の明示的なオブジェクト構築を削除するためのリファクタリング

次のリファクタリングに標準化された名前があるかどうか疑問に思っています:

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のパターンブックへのリファクタリングブックでこれを読んだと誓うことができますが、見つからないようです。

それとは別に、これは合理的なリファクタリングと見なされますか?私はそれがファクトリオブジェクトと依存性注入の混合だと感じています。

3
Lagerbaer

あなたのbar_generatorはファクトリーと呼ばれ、そのような「注入された」ファクトリーを使用するようにクラスFooを設計することは(オブジェクトを独自に構築する代わりに)「依存性注入」と呼ばれます-これがすでに述べた。ただし、これはリファクタリング手順の呼び出し方法ではありません。

ファウラーのリファクタリングカタログ を見ると、変換は3つのステップで達成できます。

それとは別に、これは合理的なリファクタリングと見なされますか?

Barからの分離が合理的な目的を満たしている場合、それは妥当です。 「私はこの明示的な結合が好きではありません」私見は非常に弱い理由です。 "明示的なカップリングはクラスのユニットテストを妨げる"または "明示的なカップリングは異なるコンテキストでの再利用を防ぐ"たとえば、より良い理由です。

3
Doc Brown

総称名で区別することは困難ですが、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の依存関係と考えてください。

1
Greg Burghardt