操作の開始時にいくつかのビジネス ロジック ステップを実行する必要がある、非常に複雑なビジネス要件があるとします。たとえば、ユーザーがリクエストを送信する場合、実行する必要がある手順は次のとおりです。
- データを検証する
- リクエストがすでに存在するかどうかを検証する
- ユーザーが存在するかどうかを検証する
- ユーザーがリクエストを送信するのに十分な金額を持っているかどうかを検証します
- ユーザーがリクエストをすぐに発行できるかどうかを検証する
- リクエストのアイテムがあるかどうかを検証する
- リクエストのアイテムが有効かどうかを検証する
- アイテムにマイナスの金額がないことを検証する
- ... (さらなる検証)
- データをリポジトリに保存する
- ユーザーまたは適切な関係者に電子メールを送信する
- ... (おそらく別の手順を実行する必要があります)
上記の例は実際のビジネス要件とはかけ離れているかもしれませんが、そうであると考えると、この操作には約 10 以上のサービスがあると思います。
コンストラクターの依存関係を使用する場合、コンストラクターが 10 個以上あるのは悪いことなので、リファクタリングするとうまくいくと思います。リファクタリングされたデザインの例:
ISubmitter(IValidator, IRequestRepository, INotification)
IValidator(IRequestValidator, IItemValidator)
IRequestValidator(IRequestRepository, IUserValidator, IItemExistValidator)
IUserValidator(IUserRepository, IUserFinancialValidator, IUserPublisherValidator)
IItemValidator(IItemRepository, IItemAmountValidator)
... // maybe more
アイテムの金額の検証プロセスでは、サブミッターから 4 つのレイヤーが作成されました: ISubmitter->IValidator->IItemValidator->ItemAmountValidator。
関心の分離に関しては、必要な正しい実装を簡単に取得できることを知っています (例: ItemAmountValidation)。しかし、コードのデバッグに関しては、どの検証クラスを使用しているかを追跡するのが難しくなりませんか? コンストラクターの注入は、インターフェイスではなく実装で定義されているためですか?
最悪のシナリオを考えてみましょう。デバッガーが開発者ではなく、最小限のテスト シナリオしかなく、ドキュメントがまったくない場合です。