まとめ
- その意味や意図が記述した本人以外には自明では数値や文字列をマジックナンバーと呼ぶ。
- マジックナンバーは、1.から意図が読みにくいので避けるべき。
- 1.にもある通り数字だけでなく文字列でもマジックナンバーを避けるべき。
参考文献
1.はPython
できれいなコードを書くためのヒントをまとめた書籍となっています。2.は、マジックナンバーの辞書的な意味を調べるのに使いました。
- https://book.mynavi.jp/ec/products/detail/id=127578
- https://e-words.jp/w/%E3%83%9E%E3%82%B8%E3%83%83%E3%82%AF%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC.html
具体例:数値のマジックナンバーについて
本記事ではまず、1時間15分の試験を今から始めた場合の試験終了時刻を求めた値をtime_limit
という変数に格納するような操作を考えます。
よくないと思われるマジックナンバー(数値)の例
まずは、以下によくないと思われる例を用意します。一般的にsnake_case
に則って変数名を決めるため出てくる変数time_limit
もそれに則りました。そしてこの4500
という値について、time
をインポートしていて変数もtime_limit
なのでなんらかの期限となる時刻と関係することまでは容易に伝わると思いますが、これが1時間15分の秒数であるというのは伝わりにくいかと思います。
import time
time_limit = time.time() + 4500
マジックナンバーを排除した例
次に、マジックナンバーを排除した例を記載します。Python
だとなるべく定数として扱いたい変数は大文字で表記することが多く、追加した変数2つはそれに則りました。SECONDS_PER_MINUTE
は1分に含まれる秒数を表し、MINUTES_PER_TEST
は1試験時間に含まれる分数を表しています。それらを使って変数SECONDS_PER_TEST
という1試験時間に含まれる秒数を格納する変数を作りました。これで、コードからtime_limit
が何を指すのかは見えやすくなったはずです。
import time
SECONDS_PER_MINUTE = 60
MINUTES_PER_TEST = 75
SECONDS_PER_TEST = SECONDS_PER_MINUTE * MINUTES_PER_TEST
time_limit = time.time() + SECONDS_PER_TEST
また、当たり前ですが別の意図によって作られた同じ値を持つ変数は分けておかなければなりません。例えば上の場合MINUTES_PER_TEST
は75ですが、MINUTES_PER_TEST
が60だった場合SECONDS_PER_MINUTE
と同じ値だからSECONDS_PER_MINUTE
をMINUTES_PER_TEST
のように扱うようなことは避けるべきです。
具体例:文字列のマジックナンバーについて
次に、sakana
定食と'niku'定食のどちらを頼むかをinput()
で受け取って、もし受け取った値がniku
の場合niku定食は売り切れとなっています。申し訳ございません。
と表示するような操作を考えてみます。ここで受け取る値は、sakana
とniku
の2つの値のみを想定しているということにします。
よくないと思われるマジックナンバー(文字列)の例
下記の場合はエラーとなりませんが、niku
と受け取ってもそれは誤字で記述されたniki
ではないので何も返ってきません。変数order
と比較することはできますが、誤字によってすり抜けてしまっています。ですので、誤字をしない以外という意識以外にも用意できるなんらかの工夫をしたほうがよいと思われます。
order = input("sakana定食かniku定食を選んでください。")
if order = "niki":
print("niku定食は売り切れとなっています。申し訳ございません。")
マジックナンバーを排除した例
次に、マジックナンバーを排除した例を記載します。NIKU
という変数を用意し、比較用に準備しました。同じような誤字をしてしまっていますが、この場合すり抜けることはなくエラーが発生するのでそれに対処する形で修正できます。このような単純な例だとそこまで深刻な話でもないのですが、受け取った文字列によって何らかの特別な操作が必要な場合このような工夫をしたほうがよいと思われます。
NIKI = "niku"
order = input("sakana定食かniku定食を選んでください。")
if order = NIKI:
print("niku定食は売り切れとなっています。申し訳ございません。")
感想
- そこまで強く意識していなかった部分なので、気をつけていきたい。
リーダブルコードを積ん読にしてN年が経過しました。
次にやる、この記事に関連すること
- 参考文献1.をもう少し読み込む
リーダブルコ(死後強まる念)