ソースコードの整理
プログラムの変更が楽になる書き方
- 変数名・関数名にはわかりやすい名前を使う
- 長いメソッドは段落を分ける
- 段落をメソッドとして独立(抽出)させてもよい
- 変更箇所をそのメソッド内に限定できる(そのロジックを他の場所でも使うことになると、変更箇所がその分だけ増える
- 抽出元のメソッドが読みやすくなる
- メソッド名からコードの意図を読み取りやすくなる
- 関連性が強いデータとロジックを抽出することでロジックを再利用しやすくなる
- 目的ごとに変数を用意する
- 一つの変数を複数の目的に使い回さない
- 異なるクラスの重複したコードをなくす
- それぞれのクラスで共通のコードをそれぞれメソッドに抽出する
- 参照側で抽出したメソッド呼び出しを、参照先のメソッドのオブジェクトの呼び出しに変更する(2つのクラスに参照関係がある場合)
- 共通のメソッドの置き場所として別のクラスを作る(2つのクラスに参照関係がない場合)
- 狭い関心事に特化したクラスにする
安全性を高める書き方
値オブジェクト
- 値の範囲を制限して安全性を高める(値を扱うためのクラスをつくる)
- intは、マイナス21億からプラス21億の範囲の整数
- BigDecimalは、実質的に無限の範囲の数
- 新しいクラスを定義し、実際の業務ロジックで使う範囲に値の範囲を限定する
- 値オブジェクトは不変にする
- 値が異なれば別のオブジェクトにする
- 変数を変更するセッターを作らない
class Quantity { static final int MIN = 1; static final int MAX = 100; int value;
- 型を使って意図を明らかにする
- intではなく値オブジェクトを渡すことによって引数の渡し間違えを防ぐ
- 業務の関心事を直接的に表現できる
// Bad: int amount(int unitPrice, int quantity) { Money amount(Money unitPrice, Quantity quantity) { if(quantity.isDiscountable) return discount(unitPrice, quantity) return unitPrice.multiply(quantity.value()) ; }
値オブジェクトの例
- Quantity: 数量
- Unit: 単位
- Amount: 金額
- Currency: 通貨
- Days: 日数
- Period: 期間
- Telephone: 電話番号
- Email: メアド
- Url: URL
- LIne: 一行のテキスト
- Description: 説明文
コレクションオブジェクト
- コレクションを扱うコードがあちこちに散らばるとコードが読みにくくなり変更作業が煩雑になる
- forやifなど複雑な処理を行うため
- コレクション型を扱うロジックを専用クラスに閉じ込める
- クラスでは目的のコレクション以外の変数を持たせない(意図を明確にしコードを簡潔にするため)
class Customers { List<Customer> customers; void add(Customer customer) { ... } void removeIfExist(Customer customer) { ... } int count() { ... } Customers importantCustomers() { ... } }
- コレクションオブジェクトを安定させる
- 値オブジェクトと同じ理由
- コレクション操作のロジックをコレクションオブジェクトに移動させる
- コレクション操作の結果も同じ型のコレクションオブジェクトとして返す
- コレクションの要素を変化させる操作では、捜査の結果として別のオブジェクトを作って返す
- 個々のコレクションオブジェクトは内部の状態が変わらない不変スタイルのオブジェクトになる
値オブジェクトやコレクションオブジェクトのように、あるクラスに データとロジックを閉じ込めると、そのオブジェクトを使う側のロジッ クが単純になる。使う側のプログラムの記述が簡単になるように、使われる側のクラスに便利なメソッドを用意するのが オブジェクト指向設計のコツ。