現在、設計やリファクタリングの勉強のためにミノ駆動本(良いコード悪いコードで学ぶ設計入門)を読んでいます。
各章、セクションのなかで特に気になった部分を中心に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) {
// 省略
}
}
クラス図
まとめ
・引数が多い場合は、データを引数として扱うのではなく、データをインスタンス変数と
して扱う設計を意識する
・プリミティブ型はなるべく使わずにクラスの型を渡すようにする
参考文献
良いコード悪いコードで学ぶ設計入門
https://gihyo.jp/book/2022/978-4-297-12783-1