【読書メモ】ユースケース駆動開発 実践ガイド 1

- 自分用読書メモ


# 読んだきっかけ

- 個人開発で学習記録アプリを作った
    - 動くものはできた
    - しかし、goto文がないだけのスパゲッティコード
    - 問題
        - 根本的に設計能力がない
            - オブジェクト指向, OOPなどを基礎から学習
        - なんらかの開発手法を学び、実践する
            - 個人開発でも取り入れやすい軽量なものが良い

# 概要

- iconixプロセスとドメインを中核に据えた設計の実践
    - iconix
        - オブジェクト指向の分析・設計手法をコンパクトにまとめたもの
        - 最小限のumlコアセットから設計, 実装までを繋ぐ軽量な開発プロセス
            - ドメインモデル, ユースケース, シーケンス, ロバストネス分析, (クラス)
    - 読みやすい
        - 架空のオンライン書店システムの構築を行う実践形式
        - 対話形式
            - 前半の説明は飛ばしても良い
        - ワークブック形式
            - 豊富な練習問題
        - コード付き
        - アンチパターンと修正例

# まとめ

- UML
    - ドメインモデル
        - ドメインの概念的なデータモデル
            - ≒オブジェクト図
            - 対象領域を理解
        - 事前に全て洗い出せ
        - 全ての言葉を厳密に定義し、顧客との共通言語とせよ
        - 他のUMLは必ずこのドメインモデルの言葉を使え
    - ユースケース
        - 顧客の要求を目に見える形にする
        - システムの仕様に基づいて具体的かつ詳細に書け
        - 必ず代替コースを書け
    - ロバストネス分析
        - ソフトウェアの振る舞いを明確にする
    - シーケンス
        - 振る舞いをオブジェクトに割り当てる
        - ドメインモデルにあるデータで処理が実現できることを証明せよ
        - メソッドを洗い出せ
    - クラス
        - この書籍では深く解説されていない
        - ドメインモデルやシーケンス図を作り込めばクラス図は自明となる

# 前書き

- アジャイルの悪口
    - プロセスを軽視していないか
        - 自らの技量を過大評価している
    - yagni, dtsttcpw, XP信者の気付け薬
- 対象者
    - オブジェクト指向らしい分析・設計の考えを身につけたい開発者
    - 設計者・プログラマにとって真に有効なユースケースを書きたいビジネス分析者
    - UMLのモデリングスキルを高めたいモデラー
    - 繰り返し可能かつ学習コストが低い分析・設計プロセスを必要とするマネージャー

## 第1章 iconixプロセス

- iconixプロセス
    - 概要
        - ユースケースからコードを作る手順
    - 手順
        - 要求
            - 機能要求
                - システムができることを定義
            - ドメインモデリング
                - わかりやすい用語で問題領域を理解
            - 振る舞い要求
                - ユーザーとシステムの対話方法
                - ユースケースのドラフト
                    - guiの紙芝居
            - 要求レビュー
                - ユースケース記述の確認
    - 設計
        - ロバストネス分析
            - ロバストネス図でユースケース記述を書き直す
                - ユースケースのステップに対するオブジェクトの絵
            - ロバストネス図を書きつつ、ドメインモデルを更新
            - コントローラを設定し、名前を付ける
                - ユースケースを動かすための論理的な機能
            - ドラフト版のユースケースを更新
        - 詳細設計
            - 1つのユースケースに1つのシーケンス図を作る
                - 実装の詳細, クラスへの責務の割り当て
            - シーケンス図を書きながらドメインモデルを更新し、操作を加える
                - ドメインモデル(≒オブジェクト図)がクラス図(真なる静的なドメインモデル)に進化する
            - 静的モデルの整理
        - 詳細設計レビュー
        - 実装
            - コーディングと単体テスト
            - 統合テストとシナリオテスト
                - 設計もユースケースが駆動する
                    - 基本コース, 代替コースともに、それに基づいたテストケースを設定する
            - 後の保守運用に備えてコードレビューとモデルの更新をする

# 第1部 要求定義

## 第2章 ドメインモデリング

- プロジェクトの用語集
- 静的な部分の基礎
- is-a関係, has-a関係で表現
    - is-a
        - 汎化
        - クレジットカード, コンビニ支払い is a 決済手段
    - has-a
        - 集約
        - 書籍 has a 書籍レビュー, 価格, カテゴリ, etc
- 最初に作る
    - ステークホルダー間の共通言語とする
    - 動的な部分と静的な部分を結び付けることができるようになる
        - 動的な部分の基礎 : ユースケース
        - 静的な部分の基礎  : ドメインモデル
        - 最初にドメインモデルを作り、ユースケースはその用語を用いる
        - ユースケースが設計, 実装を駆動できるようになる
- ガイドライン
    - 最初に作り、用語集、共通言語とする
        - 曖昧な要求は敵, 言葉の定義をする
    - 現実世界, 問題領域のオブジェクトに焦点を合わせる
        - ソフトウェアは変化しやすいが、現実世界はしにくい
    - is-a, has-a関係で表現
    - 2時間で作る(あまり時間をかけず、あとから更新する)
    - データモデル, データベーステーブルと混同しない
        - ドメインのオブジェクト(を表現したシステム中で意味のあるクラス(データとメソッドの集約))はテーブルや各レコードと一致するわけではない
    - 最終的なクラス図と完全に合致しなくてもよい(相似の関係にはある)
        - クラス図では実装のためにデザインパターン, GUIヘルパーなどを使う
            - 詳細な設計はクラス図の範疇
            - GUI部品などのクラスは使用してはいけない！
- 実践
    - ユースケース
        - 書店はwebベースとし、様々なフロントエンド技術(ex. react, vue, etc)に対応する柔軟なアーキテクチャである
        - インターネット経由で注文を受け付け、書籍を売ることができる
        - ユーザーは精算前に、オンラインショッピングカートに書籍を加えられる
        - 同じように、ショッピングカートから品目を取り出すことができる
        - ユーザーは購入予定リストを利用できる
        - …
    - ドメインモデル
        - 書店
        - ユーザー
        - 書籍
        - 品目
        - ショッピングカート
        - インターネット
        - 精算
        - 購入予定リスト
        - 注文
        - …
    - 修正
        - インターネット
            - 一般的すぎる言葉
        - 書店
            - 意味が広すぎるため、言及されることが無い
        - 著者
            - ドメインモデルには小さすぎる
        - 品目
            - 必要だが意味があいまい
            - ユーザーがカートに入れられるものである
            - 取扱品目に変更
        - 精算
            - 名詞に見せかけた動詞
        - ユーザー
            - ドメインモデルではなくアクター
        - このように適切に修正する
    - 現状のドメインモデル
        - 先端がひし形の矢印は集約, has-a
        
        ![image(9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289989/d553f308-e4ed-44f4-be75-1222fe6cff33.png)

        
    - モデルの更新
        - 先ほどの変更と「注文履歴」と「注文発想」などが発見されたとする
        - (左下の書籍一覧などの方向を間違えていたので修正)
        
        ![image(8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289989/89a14d57-b7a9-46eb-a7c7-659eafdd6d81.png)
        
    - 汎化
        - is-a関係
        - ex. cat is a animal, 猫は動物
            - 猫は動物よりも狭い概念, 洗練された概念
        - サブクラス : 詳細化したクラス
        - スーパークラス : 一般化したクラス
        - サブタイピング (継承): 一般化したクラスからサブクラスを作ること
        - xxxカタログの扱い
            - 検索結果や購入予定リストなどは書籍一覧のサブタイピング
            - 先端が▻は汎化, 継承
            
            ![image(11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289989/2d769e5c-a740-43d0-8846-3553b0e2177c.png)

            
        - ミニカタログ, マスター書籍カタログは書籍カタログのサブタイピング
    - さらに更新
        
        ![image(12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289989/14b9584d-a3af-4cbc-bae8-157166a39c38.png)

        
- 注意点
    - 多重度はまだ考慮しなくてよい
    - ER図(データベースのテーブル)を考えるわけでは無い
        - 適切なドメインモデルに分割する
    - 抽象クラスかどうかを考えるのは早い
        - is-a関係の場合, メソッドまで考えなくてよい
    - デザインパターンなどのアーキテクチャを挿入するには早い
        - 詳細設計でやる
- 練習問題
    - ドメインモデルで4種類の関係でないものは？
        - 選択肢
            - has-a, creats(~を作る), is-a, know about(~を知っている)
        - A. creats, これは振る舞い, メソッドで(動的, 詳細な設計)定義されるもの
        - 4種の関係性
            - has-a, is-a
            - know about
                - 顧客 know about 注文 → 顧客が注文を知っている(保持している, has-aに近いか？)
    - ドメインクラスの一覧を作るとき、属性についてどのように説明しますか？
        - 選択肢
            - 属性は常にカーディナリティ(多重度)を持つ
            - 属性は振る舞いを持たず、インスタンスに含ませることのみできる
            - 属性は通常、他の値の合成ではない単一の値を持つ
            - 属性は、他の多くの値を合わせた単一の値も持つ
        - A. 属性は通常、他の値の合成ではない単一の値を持つ
            - 多重度はまだ考えない, 値を合成しなくてよい(テーブルとは異なる), 振る舞いは持たないが、インスタンスにのみ含ませることができるは極端
    - システム中のドメインクラスを発見するには、どの方法を使うか？
        - 選択肢
            - 名詞句の分析
            - リバースエンジニアリング(後工程, コード自体からモデルを更新)
            - クラス動詞分類
            - エクストリームプログラミング
        - A. 名詞句分析, xpはない, 動詞はメソッドに割り当て, リバースエンジニアリングは発見というより復元
    - 子クラスが親クラスを拡張していることを指す用語
        - 選択肢
            - 集約, 継承, コンポジション(移譲), カプセル化
        - A. 継承, 調べればわかる
    - オンライン音楽ショップドメインモデルを描け。まず、画面を見ずに、ショップの仕組みを想像するように。その後、itunesなど実際にサービスを参考に。その2つを比べて優劣とその理由を付ける。
        - 後日、追記
    - amazonのデータベーススキーマをリバースエンジニアリングし、モデリングツールで取り込むとする。これはよいスタートと思うか？また、リバースエンジニアリングしたGUIプロトタイプから良いドメインモデルを構築するにはどんな変更を加える必要があるか？
        - amazonのデータベーススキーマをリバースエンジニアリングし、モデリングツールで取り込むとき
            - 回答例
                - A. あまりよくない
                    - 良い点
                        - データの取りこぼしはない
                    - 悪い点
                        - ドメインにおいて、意味のあるまとまり、粒度にするには向かない
                            - 個別のテーブル, フィールド, レコードはドメインモデルには小さすぎる
                        - テーブルの関連性とドメインオブジェクトの関連性は一致するわけでは無い
        - リバースエンジニアリングしたGUIプロトタイプから良いドメインモデルを構築する際に加える必要のある変更
            - 回答例
                - DBスキーマと同様、表示項目, 入力項目はドメインモデルには小さい
                - 操作手順に注目すれば関連性が見えるか？
                    - 「商品をカートに入れる」→ 商品、カート、在庫 などが関与
        - あるプロジェクトの第3リリースをするとする。第2リリースのコードからリバースエンジニアリングした完全なクラス図があるとする。第3リリースでは、DBMS, GUIフレームワークが含まれる。ドメインモデルの構築のために、前リリースの詳細クラス図にどのような変更を加える必要があるか？
        - 回答例
            - 問題設定
                - 前提 : 第2リリースの完全な詳細クラス図(実装よりの情報)
                - 目的 : DB, GUIフレームワークの変更を含む第3リリースに向けてドメインモデルを構築
            - 回答
                - ドメインモデル構築
                    - クラス図とドメインモデルの違い
                        - デザインパターン, GUIクラス, DBアクセスのDAOなど実装の詳細を省く
                    - 抽象化してドメインモデルを作る
                - DBMS, GUIフレームワークの変更
                    - 第2リリース時点でのDB, GUIフレームワーク固有の機能を調査
                    - 変更するフレームワークの機能に合わせクラス図を更新
                        - GUIロジックとビジネスロジックを分離
                - 技術的制約をビジネス上の制約に優先しない

## 第3章 ユースケースモデリング

- ユーザーとシステムの対話, 相互作用
    - ユーザーガイドを書くのに似ている
    - アルゴリズムとは違い対話を表現
- 注意点
    - 具体的に
        - 抽象的に書けと主張する人も多い
        - 設計者, プログラマから見て曖昧なものになる
        - 実行時の振る舞いであることを忘れない
            - 設計, テストを駆動する
    - 代替コースを忘れない
        - 例外処理が作れない
    - ドメインモデルをまず作る
        - ドメインモデルの言葉でユースケースを書く
            - 両者が結びつかない限り、ユースケース駆動のオブジェクト指向設計は出来ない
    - 2段落ルール
        - 基本, 代替コースも2段落に収まるように
        - 長くなる時、分割すべき
    - アクターとユースケース図でユースケースを組織化
    - 叙述的に書く
        - ex . ログイン機能
            - 機能要求レベルの書き方
                - 「ユーザーはパスワードを使った認証方式でログインできる」
            - ユースケース
                - 「ユーザーはユーザー名とパスワードを入力して「ログインボタン」をクリックする。システムはユーザー名からユーザー情報を取り出し、パスワードをチェックする。そして、ユーザーはシステムにログインする。」
                - バウンダリ/GUIオブジェクトの名前を使う
    - イベントと応答の流れをユースケースに書く
        - システムが起点になるとき
            - 上記のユースケースの前に「システムはログイン画面を表示する。ユーザーは…」
        - 述べるのではなく示す
        - 対話(ユーザーの操作とシステムの応答)の手順を、ユーザー・システムの両側を書く
            - 最終的なソフトウェア設計の規定にはソフトウェアの振る舞いも明確になっていないといけない→両側の目線で書く
    - 紙芝居, GUIプロトタイプ, 画面のモックアップを使う
        - 具体的なユースケースを作るには、ユーザーが操作する画面の構成要素を明確にする必要がある
        - デザインをしているわけでは無い, ナプキンの裏のスケッチ程度でよい
    - 名詞→名刺→動詞という文で書く
        - 名詞はオブジェクトのインスタンス
            - ドメインモデル(エンティティ)かバウンダリ/GUIオブジェクト
        - 動詞はオブジェクト間のメッセージ
            - コントローラ(ソフトウェアの機能)
        - シーケンス図を描くの楽になる
- パッケージに組織化
    - ユースケースが出揃ったら関連する機能ごとにまとめる
        - UMLではパッケージ(図)という仕組みがある
- 実践
    - テンプレート
        - ユースケース名 : 目的の分かる短い動詞句
        - 使用時のコンテキスト : ユースケースの起きる条件
        - スコープ : 設計スコープ, ブラックボックスだと考えられている設計対象システム
        - レベル : 要約, ユーザー目的, サブ機能のいずれか
        - 主アクター : 主アクターのロール名または説明
        - ステークホルダーと利益 : そのユースケースに関するステークホルダーと主な利益
        - 事前条件 : すでにそうなっていると想定している状態
        - 最低保証 : どのようにユースケースが終了したとしても守られる利益
        - 成功時保障 : 目的が達成されるときの状態
        - トリガー : 何がユースケースを開始するか(時間イベントの場合も)
        - 主成功シナリオ : トリガーからの目的の達成, 事後処理までのシナリオのステップを記述
            - ステップ番号とアクション記述
        - 拡張 : 拡張を1つずつ記述する, それぞれで主成功シナリオのステップを記述
            - 変更されたステップ : 条件 : アクションまたはサブユースケース
        - 技術およびデータのバリエーション : 結果としてシナリオの分岐が起きるバリエーション
            - ステップ番号またはバリエーション番号 : バリエーションリスト
        - 関連情報 : プロジェクトで必要な関連情報を何でも
- 基本コースと代替コース
    - 基本コース : 主成功コース
    - 代替コース : 技術およびデータのバリエーションでの例外を表現
    - 例
        - 基本コース
            - 顧客は現在表示されている書籍の「レビューを書く」ボタンをクリックし、システムの「レビューの記入」画面を表示する。顧客を書籍レビューを入力し、書籍評価を5つ星までの範囲で指定し、「送信」ボタンをクリックする。システムはレビューが短すぎたり長すぎたりしないか、書籍評価が1~5の間になっているかどうか確認する。そしてシステムは確認画面を表示し、レビューを追加する為めにモデレータに送る。
        - 例外コース
            - ユーザーがログインしていない : ユーザーはまずログイン画面を表示し、ログインしてからもう一度「レビューの記入」画面に移動する。
            - ユーザーが書いたレビューが長すぎる(1MB以上) : システムはレビューを拒絶し、レビューが拒絶された理由を説明するメッセージを表示する。
            - レビューが短すぎる(10文字未満) : システムはレビューを拒絶する。
- 注意点
    - 明確なバウンダリオブジェクトを使う
        - × システムは検索フォームを持つページを表示する。
        - 〇 システムは「検索」ページを表示する
    - 操作と手順を明確に、具体的に
        - × ユーザーは変更したい商品に対して追加や削除を行い、「更新」ボタンをクリック
        - 〇 ユーザーは取扱品目の横にある「数量」フィールドをクリックし、値を1から2に変更し、「更新」ボタンをクリック
- 練習問題
    - ユースケースによってとらえるもの
        - 選択肢
            1. オブジェクト, クラス, およびそれらの関係
            2. システム内の処理の流れ
            3. 独立した、目に見えるユーザー機能
            4. 時間によって構成されるオブジェクト間の協調作業
        - A. 3, 1はクラス図, 4はシーケンス図, 2はシステム内に限らない,
    - ソフトウェア設計を駆動するためのユースケースはどうあるべきか
        - 選択肢
            1. 抽象的、本質的で、技術に依存せず、実装から独立している
            2. 曖昧、不完全、ぼんやりしている
            3. 特定されていて曖昧でなく、ユーザーのアクションとシステムの応答を明確に節
            4. 「完全武装」している(特に事前条件、事後条件、機能要求が記述されている)
        - A. 3, ユーザーの操作とシステムの応答から成る双方向の対話を表現する必要がある, 1は設計者・プログラマを混乱させる, 2は論外, 4はドキュメントとしては悪くないが、ユースケース駆動の観点からもっと軽量でよい