現場で役立つシステム設計の原則 を読んで
を読んで、学んだこと、感想をメモしていく。
変更が大変なプログラムの特徴は次の3つ。
- メソッドが長い
- クラスが大きい
- 引数が多い
業務で使われる用語に合わせて、その用語の関心事に対応するクラスを ドメインオブジェクト と呼ぶ。アプリケーションの対象領域 (ドメイン) の関心事を記述したオブジェクトという意味。
関連する業務データと業務ロジックを1つにまとめたこのようなオブジェクトを ドメインオブジェクト と呼ぶ。
値を扱うための専用クラスを作るやり方を 値オブジェクト (Value Object) と呼ぶ。
値オブジェクトは業務の用語そのもの。
- 業務で扱う情報の名前
- 業務上の判断や計算に使う用語
1つのオブジェクトを使いまわしたほうが便利で効率的かもしれないが、オブジェクトの値が変わることを前提にすると、そのオブジェクトが、ある時点でどのような値を持っているのか、いつも心配することになる。処理の途中で値が変わると、プログラムは不安定になり、変更したときに思わぬ副作用が起きがち。
値オブジェクトを「不変」にするやり方は次のとおり
- インスタンス変数はコンストラクタでオブジェクトの生成時に設定する
- インスタンス変数を変更するメソッド (setter メソッド) を作らない
- 別の値が必要であれば、別のインスタンス (オブジェクト) を作る
このような設計のやり方を 完全コンストラクタ と呼ぶ。
コレクション型のデータとロジックを特別扱いにして、コレクションを1つだけ持つ専用クラスを作るやり方を コレクションオブジェクト あるいは ファーストクラスコレクション と呼ぶ。
コレクションの操作を安定させる方法は、3つ。
- コレクション操作のロジックをコレクションオブジェクトに移動する
- コレクション操作の結果も同じ型のコレクションオブジェクトとして返す
- コレクションを「不変」にして外部に渡す
逆に、コレクションへの参照を返すメソッドを用意すると、コレクションの状態が不安定になり、コレクションオブジェクトのメリットを失う。
どうしてもコレクションを渡す必要がある場合は、変更不可のコレクションに変換して渡す。
業務アプリケーションでは、業務ロジックを整理するために、画面インターフェース / 業務ロジック / データベース入出力の3つの関心事を分離する 三層アーキテクチャ が一般的。
名前 | 説明 |
---|---|
プレゼンテーション層 | 画面や外部説明インターフェース |
アプリケーション層 | 業務ロジック、業務ルール |
データソース層 | データベース入出力 |
業務ロジックをわかりやすく整理する基本のアプローチ
- データとロジックを一体にして業務ロジックを整理する
- 三層のそれぞれの関心事と業務ロジックの分離を徹底する
クラス設計で大切なことは、使う側のクラスのコードがシンプルになるように設計すること。
- メソッドをロジックの置き場所にする
- ロジックを、データを持つクラスに移動する
- 使う側のクラスにロジックを描き始めたら設計を見直す
- メソッドを短くして、ロジックの移動をやりやすくする
- メソッドでは必ずインスタンス変数を使う
- クラスが肥大化したら小さく分ける
- パッケージを使ってクラスを整理する
関連性の強いデータとロジックだけを集めたクラスを 凝集度が高い と言う。
凝集とは「切っても切れない」関係。
三層 + ドメインモデルの構造では、業務ロジックを記述するのはドメインモデルだけ。業務的な判断 / 加工 / 計算のロジックは、すべて、ドメインモデルを構成するドメインオブジェクトに任せる。
業務アプリケーションのコードが複雑になる理由は、業務ロジックの複雑さ。業務ロジックの複雑さをドメインモデルとして分離し整理することで、三層のコードはシンプルになり、構造も単純になる。
名前 | 説明 |
---|---|
プレゼンテーション層 | UI など外部との入出力を受け持つ |
アプリケーション層 | 業務機能のマクロな手順の記述 |
データソース層 | データベースとの入出力を受け持つ |
ドメインモデル | 業務データと関連する業務ロジックを表現したドメインオブジェクトの集合 |
ドメインモデルで設計する狙いは次の3つ
- 業務的な判断 / 加工 / 計算のロジックを重複なく一元的に記述する
- 業務の関心事とコードを直接対応させ、どこに何を書いてあるかわかりやすく整理する
- 業務ルールの変更や追加のときに、変更の影響を狭い範囲に閉じ込める
業務に使っている用語をクラス名にする
ドメインオブジェクトの設計の基本は、現実の業務の中で使われている具体的な言葉の単位で業務ロジックを整理すること。クラス名やメソッド名を業務で使う用語と一致させる設計をまず行う。
ドメインモデルの設計でありがちな失敗に、業務では実際に使っていない抽象的な言葉をクラス名として使ってしまうこと。広い抽象的な名前を使ったクラスは、具体的には何も説明していない。業務の現実の詳細を的確に捉えていない。
ドメインモデルの設計に取り組むときに、ドメインモデルとデータモデルを別のものとして考えることが大切。
ドメインモデルは、業務ロジックの整理の手法。業務データを判断 / 加工 / 計算するための業務ロジックを、データひとかたまりにして「クラス」という単位で整理するのがオブジェクト指向の考え方。関心の中心は業務ロジックであり、データではない。
データモデルは、文字どおりデータが主役。業務で発生するさまざまなデータを整理して、どうテーブルに記録するかを考える。
全体を俯瞰する道具
- パッケージ図
- 業務フロー図
パッケージ図
分析の初期の段階は、クラス単位で考えるよりも、業務ロジックのおおよその置き場所をパッケージとして割り振ってみる。
業務フロー図
業務のさまざまな活動を、時間軸に沿って図示したものが業務フロー図。クラスの候補を見つけるときに、業務の流れに沿って登場するオブジェクトとして発見できる。
業務の関心事を分類
業務を分析し理解するために、業務の関心事を ヒト / モノ / コト の3つに分類する方法がある。
分類 | 例 |
---|---|
ヒト | 個人、企業、担当者など |
モノ | 商品、サービス、店舗、場所、権利、義務など |
コト | 予約、注文、支払、出荷、キャンセルなど |
モノに対する関心事を表現する属性
- 数量、金額、率
- 説明、注釈
- 状態
- 日月や期間
- 位置
コトの基本属性
属性 | 説明 |
---|---|
対象 | 何についての発生した事象か |
種別 | どういう種類の事象か |
時点 | いつ起きた事象か |
コトに注目すると全体の関係を整理しやすい
- コトはヒトとモノとの関係として出現する (だれの何についての行動か)
- コトは時間軸に沿って明確な前後関係を持つ
手続き型の場合は、データクラスを受け取った機能クラスで、if 文 / switch 文を使って必要な条件判断と分岐を実行する。条件の組み合わせは、基本的に if 文の入れ子構造になる。これがトランザクションスクリプトと呼ばれる手続き型の業務ルールの記述方法。
役に立つドメインオブジェクトは、クラス名やメソッド名がそのまま業務の言葉と一致する。