フィーチャーツリーを作る | ドメイン駆動設計ハンズオン
Prev: はじめに | ドメイン駆動設計ハンズオン
誰がフィーチャーツリーを考えるか
本来は、ビジネスサイドやプロダクトオーナーが主体となって作成するものです。なぜなら、フィーチャーツリーはこれから作成しようと考えているシステムやサービスの言わば青写真であり、どういう構想を持っているかはビジネスサイドやプロダクトオーナーしか知りえないことだからです。もちろん、ビジネスサイドやプロダクトオーナーがこういう分析に慣れていない場合も考えられるので、そういう場合は分析に慣れているエンジニアがサポートしたほうが良いだろうと思います。
また、あくまで青写真であり完全なものを作ろうとする必要はありません。今時点で必要十分な詳細度であれば問題ありません。そして、折に触れて詳細度を上げたり、機能のツリー構造を再構築するような見直しを継続して行っていきます。
フィーチャーツリーを作る
特に作り方に決まりはありませんが、機能をリストアップしてグルーピングを数サイクル繰り返す形になるでしょう。
では実際にECサイトのフィーチャーツリーを考えていきます。まず必要となる機能をリストアップしてみます。
- 商品の検索
- ショッピングカート
- 決済機能
- 注文機能
- 配送状態確認
この時点で機能をグルーピングしてみます。ショッピングカートと注文機能と配送状態確認は同じ注文に関する機能なのでグルーピングできそうです。注文グループと注文機能で紛らわしいので機能の方は注文受付機能に変えましょう。決済機能は注文の際に呼ばれますが、注文以外の支払い(例えば有料会員とか)でも利用されるので注文グループに入れるのはやめておいたほうが良さそうです。
- 商品の検索
- 決済機能
- 注文
- ショッピングカート
- 注文受付機能
- 配送状態確認
有料会員といえば、ユーザーが自身の情報を変更できる機能が必要でした。商品についても管理画面から登録したり変更できたりする必要がありそうです。
- 商品の検索
- 決済機能
- ユーザー情報変更
- 商品管理
- 注文
- ショッピングカート
- 注文受付機能
- 配送状態確認
追加した商品管理と商品の検索はどちらも商品カタログというグループにまとめられそうです。
- 決済機能
- ユーザー情報変更
- 商品カタログ
- 商品の検索
- 商品管理
- 注文
- ショッピングカート
- 注文受付機能
- 配送状態確認
一旦ハンズオンとしては十分なフィーチャーツリーができたのでよしとしましょう。
Next: ユースケースの洗い出し
商品管理は管理者が行う操作だから、管理グループを作ってその中に入れたほうが良いのではないかと考えるかもしれません。しかし、それはやめておいたほうが良いでしょう。
管理グループが作られると、ありとあらゆる管理機能がそのグループに放り込まれます。ユーザー管理、セール管理、売り上げ管理、ダッシュボード機能などなど。これらの機能は管理者が使うという以上の共通性がありません。
逆に商品管理は商品の検索機能とシナジーがある場合が多いのです。例えばセール機能が組み込まれた場合、商品の検索機能と商品管理機能の両方でセール適用価格を表示したいなら同じ処理を再利用したくなります。同じ商品カタロググループに入っていれば再利用することに違和感はありません。ProductCatalog::SaleCalculationRule
のようなSpecificationを用意して、双方の機能から利用すれば良いからです。
しかし、管理機能からも利用されるとなるとどこにおけば良いのかわからなくなります。商品管理のAdministration::ProductAdministration
とProductCatalog::ProductSearch
の双方で使うSaleCalculationRule
はどこにおくべきでしょうか。
ProductCatalog::SaleCalculationRule
におけばAdministration
モジュールとProductCatalog
モジュールが結合してしまいます。他のモジュールでもAdministration
モジュールで使われる機能があるならモジュール同士が結合してしまいます。
あるいは、SaleCalculationRule
のようなAdministration
モジュールで使われるものはトップレベルのモジュールに入れるか、Share
モジュールのような色々なところから使われる想定のモジュールを作って、そこに格納する案もあります。しかし、Administration
モジュールから使われるありとあらゆるものが放り込まれて収拾がつかなくなるのはいうまでもないでしょう。
基本的にカテゴリが近い機能は近い場所におくことを推奨します。なぜなら、カテゴリが近いということは同じ処理を利用する可能性が高く、近い場所にあれば共有したい処理の置き場所に頭を悩ませる必要がないからです。かりに、グループが異なったとしても共通の祖先グループのModuleにおけば良いと私は考えています。
例
- AAAグループ
- b1、c1で共通で利用するSpecification
- BBBグループ
- b1、b2で共通で利用するSpecification
- b1機能
- b2機能
- CCC グループ
- c1機能
Next: ユースケースの洗い出し