0
0

More than 1 year has passed since last update.

【良いコード悪いコードで学ぶ設計入門】5章メモ 

Posted at

現在、設計やリファクタリングの勉強のためにミノ駆動本(良いコード悪いコードで学ぶ設計入門)を読んでいます。

各章、セクションのなかで特に気になった部分を中心にQiitaへアウトプットしていきたいと思います。

5.5 多すぎる引数

1つのメソッドに与える引数が多すぎるコード
→処理させたい内容が膨らむ
→ロジックが複雑化する、重複コードが増える可能性が増える

(例)


class RecoverMagicPointMethod {

  int recoverMagicPoint(int currentMagicPoint, int originalMaxMagicPoint, List<Integer> maxMagicPointIncrements, int recoveryAmount) {
    int currentMaxMagicPoint = originalMaxMagicPoint;
    for (int each : maxMagicPointIncrements) {
      currentMaxMagicPoint += each;
    }
    return Math.min(currentMagicPoint + recoveryAmount, currentMaxMagicPoint);
  }
}


プリミティブ型執着

プリミティブ型執着とは、boolean,int,float,double,Stringのような
プログラミング言語が標準で用意しているプリミティブ型だけで
構成されるコードのこと

(Before)


class Common {
  int discountedPrice(int regularPrice, float discountRate) {
    if (regularPrice < 0) {
      throw new IllegalArgumentException();
    }
    if (discountRate < 0.0f) {
      throw new IllegalArgumentException();
    }
    return 0;
  }
}

改善案

プリミティブではなくクラスの型を渡す
Beforeと異なり、引数もクラスになっている
各クラスに関連の高いロジックが凝集する

(After)


class DiscountedPrice {
  final int amount;
  DiscountedPrice(final RegularPrice regularPrice, final DiscountRate discountRate) {
    // regularPriceとdiscountRateを使った計算
    amount = 0;
  }
}

意味のある単位ごとにクラス化する

引数の増加を防ぐために、概念的に意味のあるクラスを作成することを意識する。
以下は、魔法力に関するクラス。

/** 魔法力 */
class MagicPoint {
  private int currentAmount;
  private int originalMaxAmount;
  private final List<Integer> maxIncrements;
}

魔法力に関するロジックもカプセル化してここに定義してみる。
インスタンス変数はprivate化しておく(他のクラスから余計なことをさせないように)

/** 魔法力 */
class MagicPoint {
  private int currentAmount;
  private int originalMaxAmount;
  private final List<Integer> maxIncrements;

  // 省略

  MagicPoint() {
    originalMaxAmount = 100;
    maxIncrements = new ArrayList<>();
  }

  /** @return 現在の魔法力残量 */
  int current() {
    return currentAmount;
  }

  /** @return 魔法力の最大量 */
  int max() {
    int amount = originalMaxAmount;
    for (int each : maxIncrements) {
      amount += each;
    }
    return amount;
  }

  /**
   * 魔法力を回復する
   * @param recoveryAmount 回復量
   */
  void recover(final int recoveryAmount) {
    currentAmount = Math.min(currentAmount + recoveryAmount, max());
  }

  /**
   * 魔法力を消費する
   * @param consumeAmount 消費量
   */
  void consume(final int consumeAmount) {
    // 省略
  }
}

クラス図

image.png

まとめ

・引数が多い場合は、データを引数として扱うのではなく、データをインスタンス変数と
して扱う設計を意識する

・プリミティブ型はなるべく使わずにクラスの型を渡すようにする

参考文献

良いコード悪いコードで学ぶ設計入門
https://gihyo.jp/book/2022/978-4-297-12783-1

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0