wildcatsの日記

赤羽在住でIT関係の会社の社長やってます。

僕がマジックナンバーが嫌いな理由

家に帰ったらエントリを書くつもりが、息子を寝かしつけると同時に自分も寝てしまっていたようです(^_^;
今はAM4:00です。変な時間に起きちゃったな。

自分がマジックナンバが嫌いな理由を書いておきます。
理由は簡単で
・コードを読んでもマジックナンバの意味が理解できない。
・1つの論理定数を変更する為に複数のコードを修正しなくてはならない。
ということです。

例えば銀行から初めてお金を借りるときの限度額が300万円としましょう。
融資希望額と限度額を比較するようなプログラムを書いたときに
マジックナンバを使ったケースでは


if (amountWishingLoan > 300) {
throw new ExcessAmountLoanExcepion();
}
amountWishingLoanは融資希望額でExcessAmountLoanExcepionは融資額超過例外だとしてください。
この300の意味を始めてこのコードを読んだ人が理解しづらいと思います。
理解してもらいやすくする為にはこのマジックナンバにコメントを書くことでしょうか?

// 初期融資超過額を超えた場合には融資額超過例外をthrowする。
if (amountWishingLoan > 300) {
throw new ExcessAmountLoanExcepion();
}
でもコメントを書くくらいだったら初めからprivateの定数にしておいたほうが一目で理解できます。

private static final int AMOUNT_INITIAL_LOAN_LIMIT = 300;

if (amountWishingLoan > AMOUNT_INITIAL_LOAN_LIMIT) {
throw new ExcessAmountLoanExcepion();
}

もちろん今日は定数であっても明日には変化するかもしれませんのでその場合には以下のコードを自分は書きます。

private static final int AMOUNT_INITIAL_LOAN_LIMIT = 300;

protected int getAmountInitialLoanLimit() {
return this.AMOUNT_INITIAL_LOAN_LIMIT;
}

if (amountWishingLoan > getAmountInitialLoanLimit()) {
throw new ExcessAmountLoanExcepion();
}

で。。このif文の条件があちこちに出てくるならこんな感じですかね。。。


private static final int AMOUNT_INITIAL_LOAN_LIMIT = 300;

protected int getAmountInitialLoanLimit() {
return this.AMOUNT_INITIAL_LOAN_LIMIT;
}

protected boolean isInitialLoanLimit(final int aAmountWishingLoan) {
return aAmountWishingLoan > getAmountInitialLoanLimit();
}

if (isInitialLoanLimit(amountWishingLoan)) {
throw new ExcessAmountLoanExcepion();
}

また一つの論理定数の変更の件は1クラス内の複数の箇所で300というマジックナンバを用いている場合に
300の値に修正が入った際に複数の箇所を変更しなくてはならず変更漏れが発生しやすいということです。
またEclipseなどのIDEを用いればprivateな定数を定義しておくことでコードを書いている段階での入力ミスを抑制できる利点があると思います。

ちなみにpublicな定数が嫌いだからと言って全てprivateな定数にするのかと言われると実はそうでもなく、プリミティヴ型以外はTypeSafeEnumにする場合も多いです。使い分けは今回のフィードバックがあり次第かな?

ただ元ネタのSaisseさんの日記を読むとマジックナンバをアクセサで隠蔽するということを書かれているので
上記の話はあんまり意味無いかなぁ〓?(^_^;