Staticは悪いですが、Factoryパターンはどうですか?


13

私はTDDプロジェクトに参加しているので、この種の開発に関係する優れた慣行に可能な限りこだわります。それらの1つは、静的およびグローバルを可能な限り回避することです。

私はこの問題に直面しています。「オプション」(追加の「マイクロ記事」)をリンクできるオブジェクト「記事」があります。

私はすべてが非常に切り離されているため、基本的にオブジェクトごとに1つのクエリを作成する必要があるため、非生産的であるか、あまり多くのクエリを生成しない良いアプローチを持つ方法を理解することはできません。

私の実際の観点から、3つのオプションがあります。

1)記事内のビルド:

class Article
{
    //[...]
    public function getArrOption(){
        //Build an array of Options instance.
        //return an array of Options.
    }
}

プロ:まっすぐ進む

定数:保守性:articleオブジェクトには、Optionオブジェクトの構築ロジックが含まれるようになりました。これはおそらくコードの重複につながります。

2)optionFactoryを使用する

class Article
{
    //[...]
    public function getArrOption(){
        return OptionFactory::buildFromArticleId($this->getId());
    }
}

プロ:ロジックの構築はArticleクラスの外にありません

Const:「静的なモックは難しい」というルールを破り、Articleクラスのテストを難しくしています。

3)すべてのロジックを分離します。

//Build the array of Option instance in a controller somewhere, using a Factory:
$arrOption = OptionFactory::buildFromArticleId($article->getId());

プロ:記事は彼自身の責任のみを扱い、オプションへの彼の「父」リンクを気にしません。物事は本当に切り離されています

Const:オプションにアクセスする必要があるたびに、コントローラー内により多くのコードが必要になります。私がすべきことという意味では決してオブジェクト内の工場を使用していない、と私にutopicのその音の種類...

最善の方法は何ですか?(私は何かを見逃しましたか?)ありがとう。

編集:

言うまでもなく、クラス内でファクトリを呼び出せない場合、基本的に怠laな初期化パターンも使用できません...


それが適切かどうかはわかりませんが、PHPでコーディングしているので、「アプリケーション」の状態は少なくなります。セッションCookieに保存されていない場合、各ページ間ですべてのデータをリロードする必要があります。つまり、アプリケーション言語のようにすべてをプリロードすることはできません。
-FMaz008

@job:それは、ユニットテストの際にメソッド内の静的呼び出しを置き換えることはほとんど不可能だからです。目標は、依存性注入を使用することです。ただし、ファクトリは通常静的であるため、注入できません。
FMaz008

回答:


12
  1. 静的は「悪い」ものではなく、偽物ではありません。モックが意味をなさない場合でも使用できます。

  2. これはFactoryパターンではなく、Repositoryパターンのように見えますが、そうではない場合があります。ファクトリーは、同じインターフェース/基本クラスを持つ複数のクラスがあり、どのクラスを返すかを決定するロジックを分離したい場所です。リポジトリはリポジトリからデータを取得し、そのリポジトリの実装を抽象化します(記事は、オプションが同じDB、別のDB、XMLファイル、CSVファイルなどに保存されているかどうかを知る必要はありません)。

  3. あなたはArticleクラスにObjectFactory(またはRepository、その他)オブジェクトを与える可能性を無視しました。このオブジェクトはbuildFromArticleメソッドを呼び出すことができます。

私のPHPは錆びていますが、次のように見えると思います。

class Article
{
    private $_option_repository;

    public function __construct($option_repository) {
        $_option_repository = $option_repository;
    }

    //[...]

    public function getArrOption(){
        return $_option_repository->buildFromArticleId($this->getId());
    }
}

これは上記のすべての長所を満たしていると思います。


したがって、Factory / Repository / Mapperのインスタンスを使用してもかまいませんか?オブジェクトによって返される可能性のあるすべてのオブジェクトのすべてのファクトリ/リポジトリ/マッパーをインジェクトする必要がある場合、すぐに多くのことが行われるため、依存関係コンテナまたは何かが必要になります。(記事-> OptionGroup->オプション->記事など)
-FMaz008

1
それは大丈夫です、それは望ましいです。私は通常、複数のクラスでテストできるほど小さいコードの繰り返しを削除するために静的な使用を予約しています。そして、はい、IOC / DIコンテナはあなたの人生をずっと楽にします。使用してください。
pdr

1

静的メソッドを必要としないこと、抽象ファクトリーが混乱することが実証されていること、そして解決策として依存性注入に向けた言語のわずかな変更を提案していることを主張する論文からの引用です。

インスタンスとそのクラス間の緊密な結合はカプセル化を破壊し、静的メソッドのグローバルな可視性とともにテストを複雑にします。依存性注入をプログラミング言語の機能にすることで、静的メソッドを完全に取り除くことができます。次のセマンティックの変更を採用しています。

(1)グローバルのすべての出現をインスタンス変数へのアクセスに置き換えます。

(2)インスタンス化されたときに、そのインスタンス変数がオブジェクトに自動的に注入されるようにします。

「Seuss:細かな設定可能性のために静的メソッドから責任を分離する」

ウェイバックマシンリンク


3
このリンクは質問に回答するかもしれませんが、回答の重要な部分をここに含め、参照用のリンクを提供する方が良いでしょう。リンクされたページが変更されると、リンクのみの回答が無効になる可能性があります。
ブヨ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.