ユースケース駆動開発実践_詳細設計

以下のユースケースモデリングロバストネス分析ができている状態で詳細設計を行いたいと思います。ユースケース駆動開発実践ガイドでは詳細設計でシーケンス図の作成を行うのですが、オブジェクトに対して処理を割り当てる前にドメインモデルを見直してみたいと思います。

1.ログイン
 ユーザはログイン画面を表示しユーザ名、パスワードを入力してログインボタンをクリックする。
 システムはユーザ名から対象のユーザアカウントを取得してパスワードが一致しているかチェックする。
 パスワードの一致が確認できたらセッションにユーザアカウントの情報を保存し、TOP画面を表示する。

2.商品をカートに入れる
 ユーザはTOP画面にアクセスする。
 システムは商品カタログに登録されている商品リストの一覧を取得してTOP画面に表示する。
 ユーザは商品一覧にある商品のカートに入れるボタンをクリックする。
 システムはセッションからユーザアカウントを取り出して、それに紐づくショッピングカートを取得して商品を追加する。
 

3.商品の購入
 ユーザはショッピングカート画面にアクセスする。
 システムは商品の品目、合計金額が表示されたショッピングカート画面を表示する。この時前回ショッピングカート画面を表示した時から金額の変更があったものはそれを通知するメッセージをだす。
 ユーザは購入ボタンをクリックする。
 システムは支払い方法、届け先住所、クーポンコードの入力項目がある注文内容入力画面を表示する。この時、クレジットカードと届け先住所は個人情報から取り出して選択候補として選べるようにしておく。
 ユーザは支払い方法、届け先住所それから任意でクーポンコードを入力し、注文内容確認ボタンをクリックする。
 システムは支払い方法と、届け先住所をチェックして問題ないことを確認する。それから商品の合計金額が3000円未満であれば配送料200円を追加する。クーポンコードの入力がある場合は、それを合計金額に反映する。それから注文内容(品目、支払い方法、届け先、クーポン入力、合計金額)が表示された注文内容確認画面を表示する。
 ユーザは注文確定画面を表示する。
 システムは注文内容を確定する。この時支払い方法毎で以下の処理を行う。
  - 支払い方法がクレジットカードの場合は注文確定の際に外部システムのクレジットカードの決済処理を呼び出す。支払いが行えたら、支払い状況を支払い済みに更新する。
  - 支払い方法が銀行振込の場合は、外部システムで振込用のワンタイム口座を作成して注文確定画面に口座の情報、支払い期限を表示する
 

f:id:steavevaivai:20180503121152p:plain

f:id:steavevaivai:20180503121204p:plain

f:id:steavevaivai:20180503121222p:plain

ドメインモデルを見直す

とりあえず初期のドメインモデルを見直してみます。 f:id:steavevaivai:20180430221438p:plain 初期のドメインモデルに対して、各オブジェクトが担当する機能領域を図示化すると以下のようになるかと思います。 f:id:steavevaivai:20180503161700p:plain 基本的には集約ごとで担当機能の領域で線を引くことが多いのかと思います。詳細設計のプロセスではドメインオブジェクトに機能を割り振っていくのですが、ドメインオブジェクトに機能を割り振る前に複数のオブジェクトをまとめて大まかな機能に分類していく方が全体像が把握しやすく、大まかな機能間を疎結合でクリーンに保ちやすいのかと思います。
↑の図では4つの機能領域に分けておりまして、それぞれ以下のようになっています。

ユーザアカウント: ユーザのアカウント、個人情報を管理するための機能    
ショッピング: ユーザのショッピングカートを管理するための機能    
注文: 注文処理周りの機能
商品管理: 商品管理周りの機能

この初期のドメインモデルから掘り起こした機能領域では以下のような問題があります。
- ショッピングと注文が似ていそうだが別の機能領域に分けており、これだと商品の注文を行う際に注文を行う際にショッピングと注文の両方に更新、永続化が行われるかもしれない

実践ドメイン駆動設計で言われているのですが集約内ではトランザクション整合性、集約間では結果整合性になるようにすることで大規模で高トラフィックな開発にも対応できるとのことらしいです。大規模でも高トラフィックでもないのであれば問題ないのかもしれないですが、ショッピングと注文の機能をどのように対応するのが良いのか考えてみたいと思います。

ドメインモデルの洗練

ショッピングと注文の機能領域について、ショッピングカートと注文のドメインオブジェクトは共に品目の管理を行なっているのですが状態が異なっています。ショッピングの品目については注文をされる前の品目で、注文の品目については注文後の品目を表しているという違いがあります。状態を分けると以下のようになるかと思います。 f:id:steavevaivai:20180503161734p:plain ショッピングのモデルは現状ショッピングカートと品目のオブジェクトしかなく、それであれば注文のオブジェクトに注文状態のフィールドを持たせることでも対応可能になり機能領域間の連携での対応が不要でシンプルになるかと思いますのでそうします。

また、クーポンと発送料金については追加料金でまとめて、クーポン管理用の機能を追加して以下のようにドメインモデルを更新しておきます。 f:id:steavevaivai:20180503161750p:plain 今回の機能領域には含まれていませんが実際のショッピングサイトを作る場合は発送と在庫管理も必要になるかと思います。

シーケンス図作成の前のオブジェクト、サービス抽出

シーケンス図ではオブジェクトに処理を割り当てるので、先に割り当て対象のオブジェクト、サービスを抽出しておきたいと思います。大きく分けると以下のようになると思います。 - ユーザアカウント機能 - ユーザアカウントオブジェクト - 個人情報オブジェクト - ユーザアカウントサービス

  • 注文機能

    • 注文オブジェクト
    • 注文サービス
  • 商品管理機能 

    • 商品カタログオブジェクト
    • 商品管理サービス
  • クーポン管理機能 

    • クーポンマスタオブジェクト
    • クーポンサービス
  • アプリケーションサービス: リクエス毎の制御を行うサービス

シーケンス図作成

それではユースケースごとでシーケンス図を作成したいと思います。 まずログイン時のシーケンス図を作成します。 f:id:steavevaivai:20180503161807p:plain

次にショッピングカートへの商品追加のシーケンス図を作成します。 f:id:steavevaivai:20180503161830p:plain

シーケンス図では処理をどこに割り当てるかをわかりやすくすることができます。細かく書きすぎるとわかりづらくなりそうなので、ユースケースの全体像をまとめる時は、まずサービスのインターフェースレベルの粒度で書くのがわかりやすくなりそうな気がします。