読んだ本
「良いコード/悪いコードで学ぶ設計入門 ―保守しやすい 成長し続けるコードの書き方」
本の感想
「保守性の高いコードとは?どのような状態を保守性が高いと言えるか?」を明確にしてくれる本でした。
15章の「理想形を知って初めて課題を知覚できる」の言葉の通り、まずは理想形をしっかりと学ぶ必要があると痛感しました。
特に印象に残ったこと
クラス
- クラスが単体で正常動作するよう設計する
- クラスが果たす目的は、たったひとつに限定すべき(単一責任=単一目的)
- 良いクラスの構成要素は「インスタンス変数」「インタンス変数を不正状態から防御し、正常に操作するメソッド」
- 自分の身は自分で守らせる。自己防衛責務を全てのクラスが備える
⇒ 不正値の混入を防止するためのバリデーションをコンストラクタ内に定義する - 継承は注意して扱う
- 継承関係にあるクラス同士では、サブクラスはスーパークラスの構造に酷く依存するため
継承より委譲が推奨される。委譲とは、コンポジション構造にすること。
- 継承関係にあるクラス同士では、サブクラスはスーパークラスの構造に酷く依存するため
関数
- 関数が影響を受ける・与える範囲を限定する。関数が以下項目を満たすことを前提に設計する
- データ、つまり状態を引数で受け取る
- 状態を変更しない
- 値は関数の戻り値として返す
- staticメソッドはデータとデータを操作するロジックをバラバラに定義可能な構造であり、低凝集に陥りがち
- staticメソッドの使いどき: 凝集度に影響がない場合。例えばログ出力用メソッドやフォーマット変換用メソッドなど
- 共通処理クラス(Common・utilなど)を安易に作らないようにする
横断的関心ごとならまとめてOK(ログ出力・エラー検出・デバッグ・例外処理など) - アンチパターン
- 良くない1: 多すぎる引数
引数の量が多いということは、すなわちそれだけ処理させたい内瑤が膨らむため。
概念的に意味のある単位ごとにクラス化する - 良くない2: メソッドチェイン
ドットで数珠つなぎにして戻り値の要素に次々にアクセスする書き方により多くの要素にあらゆる箇所からアクセス可能で、影響範囲がいたずらに拡大可能な構造のため
- 良くない1: 多すぎる引数
- ポリシークラスにルールを集約する
- 引数
- フラグ引数は使わない(機能ごとにメソッドを分離する)
- nullを渡さない
- 引数は可能な限り少なく
- エラーは戻り値で返さない、例外をスローすること
共通
- nullが入り込む前提でロジックを組むと、至る所でnullチェックをしなければいけなくなる。nullの代わりに
empty
を使う - 疎結合高凝集にする
- 密結合を解消し、疎結合高凝集にするためには関心の分離「関心事、つまりユースケースや目的、役割ごとに分離する」が重要
- 可能な限り具体的で意味範囲が狭い、目的に特化した名前を選ぶ
覚えておきたいワード
凝集度
モジュール(クラス、パッケージ、レイヤーなど)内における、データとロジックの関係性の強さを表す指標
密接に関係し合うロジックが1箇所にぎゅっと集まっている高凝集な構造が良い
結合度
モジュール(クラス等)間の依存の度合いを表す指標
疎結合な設計が良い
完全コンストラクタ
不正状態から防護するための設計パターン
生成された段階で正常な値だけを持つ完全なコンストラクタを生成する
値オブジェクト Value Object
値の概念そのものをクラス(型)として表現する。
値オブジェクトと完全コンストラクタは得たい効果が近いためほぼセットで用いられる。
デメテルの法則
利用するオブジェクトの内部を知るべきではない。「知らない人に話しかけるな」
格言:尋ねるな、命じろ(Tell, Don't Ask)
他のオブジェクトの内部状態(変数)を訪ねたり、その状態に応じて呼び出し側が判断したりするのではなく、呼び出し側はただメソッドで命ずるだけで、命令された側で適切な判断や制御をするよう設計する。
詳細なロジックは呼ぶ側ではなく、呼ばれる側に実装する。
YAGNI原則
You aren’t going to need it. 実際に必要になったときにのみ実装せよ、という方針
目的駆動名前設計
ソフトウェアで達成したい目的をベースに名前を設計(命名)する。名前から目的や意図が読み取れることを特徴とする。
クラスベース
データとそのデータを操作するロジックをクラスにひとまとめにし、プログラムの構造を定義していく手法。クラスが構造の基本単位となる。
コンポジション
学ぶ必要があると感じたこと
本を読んで理解が浅いと感じたことを、次の勉強のためにメモします。
- 値オブジェクト・データクラスについて