Open4

「現場で役立つシステム設計の原則」気になったとこ

ryoryo

altテキスト

読む目的

変更に強いオブジェクト指向の設計ができるようになりたいから

ryoryo

第1章 小さくまとめてわかりやすくする

小見出し

  • なぜソフトウェアの変更は大変なのか
  • プログラムの変更が楽になる書き方
  • 小さなクラスでわかりやすく安全に
  • 複雑さを閉じ込める

値の範囲を制限した専用の「型」を作る

なんで🤔

内容的に不適切な値が入り込んで、バグが発生するのを防ぐため

int 数量; // intはマイナス21億からプラス21億の範囲の整数
string 電話番号; // stringは全ての文字種を、実質的に無制限の長さで扱える


どうする🧐

業務で扱うデータの種類ごとに、専用のクラスやインターフェイスを作る

class Quantity {
    static final int MIN = 1;
    static final int MAX = 100;

    int value;
    // 中略
}


うれしいこと😊

  • 目的に特化した「型」を宣言、利用することで、ソースコードは業務ロジックの意図を表現するようになる
  • 業務ルールが変更になった時に、クラス名やインターフェイス名を手がかりに変更の対象箇所を特定しやすくなる
ryoryo

第2章 場合分けのロジックを整理する

小見出し

  • プログラムを複雑にする「場合分け」のコード

複文は単文にする

なんで🤷🏻‍♂️

  • 文の中に文を書く「複文」は、意図をわかりにくくする
  • 複文は、文と文が密に結合している
Yen fee() {
   Yen result;
   if (isChild()) {
       result = childFee();
   } else if (isSenior()) {
       result = seniorFee();
   } else {
       result = adultFee();
   }
   return result;
}


どうする🤔

複文を分解して、単文を並べる構造に変更する。

Yen fee() {
    if (isChild()) return childFee();
    if (isSenior()) return seniorFee();
    return adultFee();
}


うれしいこと😊

  • シンプルで分かりやすい構造になる
  • 区分ごとのロジックの独立性が高くなる

???
それぞれが関連する内容(isChild, isSenior)でも分解した方がいいの?


区分や状態遷移のルールも、列挙型で記述する

なんで🤷🏻‍♂️

多様を使えば区分ごとのロジックを整理できるが、一覧性に欠け、コードの見通しが悪くなる。

どうする🤔

列挙型を使って記述する

enum State {
    審査中,
    承認済み,
    実施中,
    中断中,
    差し戻し中,
    終了
} // 状態の列挙

allowed.put(審査中, EnumSet.of(承認済み, 差し戻し中)); // 遷移可能な状態の宣言

allowedStates = allowed.get(from); // 遷移可能な状態の取得

canTransit = allowedStates.contains(to); // 遷移可能かどうかの判定


うれしいこと😊

  • 状態の一覧をわかりやすく表現が可能
  • 判定にif文/switch文が不要になる
ryoryo

第3章 業務ロジックをわかりやすく整理する

小見出し

  • データとロジックを別のクラスに分けることがわかりにくさを生む
  • データとロジックを一体にして業務ロジックを整理する
  • 三層の関心事と業務ロジックの分離を徹底する

クラス設計で大切なこと

使う側のクラスのコードがシンプルになるように設計する

次のような点に気をつけて、オブジェクト指向らしいクラスを設計する

  • データを持つクラスにロジックを書いて、使う側のクラスにロジックを書かないようにする
    → コードの重複をなくせる。変更の範囲をそのクラスに限定できる。
  • メソッドは小さく分け、必ずインスタンス変数を使う
    → そのクラスに相応しくないコードを発見しやすくなる
  • クラスが肥大化してきたら小さく分ける
    → 関連性の高い部分を別クラスを分けることで、意図が明確で使いやすい凝集度の高いクラスが出来上がる