リファクタリング入門:マジックナンバーを排除する

リファクタリング入門:マジックナンバーを排除する

プログラミングをするうえで、コードの可読性と保守性を高めることはとても重要です。そのためには、リファクタリングによる継続的なコード改善が欠かせません。特に初心者の方がつまずきがちなポイントとして、「マジックナンバー」と呼ばれるものがあります。本記事ではマジックナンバーの問題点と、それを定数や変数に置き換えることでコードの可読性・保守性を向上させる方法を学びましょう。

マジックナンバーとは何か?

マジックナンバーとは、ソースコード中に直接埋め込まれた数値リテラルを指します。たとえば、以下のようなコードを見たことはありませんか?


# マジックナンバーの例
total_price = item_count * 120
discount_price = total_price - 500

ここで登場する「120」や「500」が、いわゆるマジックナンバーです。もちろん、このように直接数値を使っても動作はしますが、後々の変更やコードの拡張性を考えると、いくつか問題があります。

  • 「120」や「500」が何を意味しているのか、コードを読んだ人が即座に理解しにくい
  • 数値の変更が必要になった時、コード全体から同じ数字を探して修正する必要がある
  • 他の箇所で同様の数値が使われていても、それが同じ意図か別の意図か判断しづらい

このような問題を抱えるコードは、保守しにくくバグも生まれやすくなります。初心者の方はついつい直接数値リテラルを書きがちですが、後から見たときに「この数字って何だっけ?」と迷わないようにする仕組みが必要です。

マジックナンバーを排除するメリット

マジックナンバーを定数や変数に置き換えるだけで、意外なほど多くのメリットが得られます。たとえば以下のような利点があります。

  1. 可読性の向上:定数や変数にわかりやすい名前をつけることで、数字の意味を明確にできます。
  2. 変更が容易:値を一か所で定義しておけば、変更が必要な時にその部分だけ修正すればよくなります。
  3. バグの防止:同じ数字が複数箇所に登場する場合、それらの意図が同じか違うかを判別できるようになります。結果的に、バグ混入を防ぎやすくなります。
  4. 再利用性の向上:同じ定数をいろいろな場所で使い回すことで、コードの重複を減らしてDRY(Don’t Repeat Yourself)の原則にも近づけます。

定数や変数を使う方法

マジックナンバーを排除する基本的なアプローチは、定数(または変数)として定義した上で、それをコード内で使うようにすることです。Pythonには、定数を明示的に定義する機能はありませんが、慣習的に大文字で書く変数を定数のように扱います。たとえば、次のように書き換えられます。


# 定数を使った例

# 商品1点あたりの価格
ITEM_PRICE = 120

# 割引の金額
DISCOUNT_AMOUNT = 500

def calculate_discounted_price(item_count):
    total_price = item_count * ITEM_PRICE
    discount_price = total_price - DISCOUNT_AMOUNT
    return discount_price

# 関数を呼び出して確認
print(calculate_discounted_price(5))  # 5点購入の場合

このように、マジックナンバーを「ITEM_PRICE」や「DISCOUNT_AMOUNT」のように定数に置き換えるだけで、コードがぐっと読みやすくなります。数字だけでなく、文字列リテラルもマジックナンバーに近い概念(マジックストリング)として扱う場合がありますが、同様に定数化することで可読性が向上します。

命名のポイント

マジックナンバーを置き換えるときに重要になるのが「名前付け」です。名前付けがわかりにくいと、せっかく定数にしても意味を正確に伝えられません。たとえば、「ITEM_PRICE」を「A」や「PRICE1」のようにすると、具体的に何を表しているのか分かりにくくなります。

  • 意味が想像できる名前:「ITEM_PRICE」は「商品1個あたりの価格」だと一目で分かります。
  • 大文字で表記:「Pythonの慣習」で、定数として扱う変数はすべて大文字にします。
  • 必要があればコメントを加える:名前だけでは不足するなら、一言コメントを書き添えておくとより親切です。

こうしたルールを守ることで、あとからコードを読んだ開発者や自分自身が迷わずに済みます。特に初心者のうちは、変数や定数の命名を軽視しがちですが、ソフトウェア全体の品質に影響する重要な要素です。

保守性が高いコードへ:将来的な変更に備える

マジックナンバーを定数に置き換える最大の理由は、「将来的な仕様変更に備えること」です。ビジネスロジックは時間とともに変更される可能性が高く、商品価格や割引額が変わることは日常茶飯事です。その際、定数を一か所変えるだけで済むようにしておけば、ミスや手間を大幅に減らせます。

また、別のプロジェクトで同じロジックを流用したいケースも考えられます。定数として値をまとめておけば、流用先に合わせて値を変えるだけで動作するため、再利用性も高まります。これらは大規模開発に限らず、小さなスクリプトでも同様にメリットがあります。

テストとの相性も良くなる

マジックナンバーを排除すると、テストとの相性も良くなります。例えば、単体テストを書く際に、テストコードの中でマジックナンバーを直書きしてしまうと、実際の処理とテストのロジックの間に不整合が生じやすくなります。以下のように、テストコードでも定数を用いることで、変更に強いテストを書けるようになります。


import unittest

ITEM_PRICE = 120
DISCOUNT_AMOUNT = 500

def calculate_discounted_price(item_count):
    return item_count * ITEM_PRICE - DISCOUNT_AMOUNT

class TestPriceCalculation(unittest.TestCase):
    def test_calculate_discounted_price(self):
        # テストでも定数を使う
        self.assertEqual(calculate_discounted_price(1), 120 - 500)
        self.assertEqual(calculate_discounted_price(5), 5 * 120 - 500)

if __name__ == "__main__":
    unittest.main()

実際の値が将来変わった場合にも、テストコード側の定数を一緒に変えれば良いので、修正漏れが減り、テスト結果の信頼性が向上します。テスト対象だけでなくテストコードからもマジックナンバーを排除するのがポイントです。

まとめ:まずはマジックナンバーを減らそう

リファクタリング入門として、マジックナンバーを排除することは非常に効果的な第一歩です。以下のポイントを押さえておきましょう。

  • マジックナンバーはコードの可読性と保守性を低下させる
  • 定数や変数に置き換えれば、意味を明確にできるうえ変更に強い
  • 名前付けを適切にすることで、コードを読む他人や将来の自分にも優しい
  • テストコードからもマジックナンバーを排除し、修正漏れを防ぐ

このような小さなリファクタリングの積み重ねが、最終的には大きな品質向上につながります。初心者のうちは、ついコードを早く書くことに意識が向きがちですが、今回のように些細な箇所からでもリファクタリングを実施してみると、後々の手戻りが減って開発速度も向上します。ぜひ、マジックナンバーの排除を日常のコーディング習慣に取り入れてみてください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です