
・マジックナンバーって何?
・マジックナンバーをLaravelで対策するためにはどうすれば良いの?
と疑問をお持ちの方のお悩みを解決できる記事になっています!
Webアプリケーション、スマホアプリ等の開発でコードを書いていく中で気をつけるべきことはたくさんありますが、その1つにマジックナンバーがあります。
チーム開発する上で必ず対策する必要のあることなので、マジックナンバーを知らない方はぜひこの記事で理解を深めてください。
また、僕が普段業務で使用しているLaravel(PHPフレームワーク)での対策方法についても解説しますね!
プログラミング初学者でも取り入れやすく、コードのレベルを上げることのできることをまとめています。


マジックナンバーとは何かを知ろう
まずはマジックナンバーとは何なのかを理解していきましょう。
マジックナンバーとは?
ズバリ『何を意味しているかわからない数字』です。
Wikipediaにはこのように書かれています。
プログラムにおけるマジックナンバー(英: magic number、魔法の数字)とは、何らかの識別子もしくは定数として用いられる、プログラムのソースコード中に書かれた具体的な数値である。そのプログラムを書いた時点では製作者は数値の意図を把握しているが、他のプログラマーまたは製作者本人がマジックナンバーの意図を忘れたときに閲覧すると「この数字の意味はわからないが、とにかくプログラムは正しく動く。まるで魔法の数字だ」という皮肉を含む。
https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B8%E3%83%83%E3%82%AF%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0)
このように自分はコードを書いている時は理解できているけど、同じチームメンバーや自分が意味を理解できなくなってしまった数字のことを言います。
既存コードを読み解いていく中で『ん?この数字はどういう意味?』と思ったことがありませんか?
その数字がまさにマジックナンバーです(笑)
マジックナンバーを使うと何がダメなのか?
ではマジックナンバーの何がダメなのか?を解説します。
(先ほど書いた『ん?この数字はどういう意味?』となる時点でダメですが…)
デメリットはこちらです。
- チームメンバー(自分含む)が数字の意味を理解するのに時間がかかる
- 数字を変更したい場合に複数箇所の修正が必要になることがある
これはサンプルコードで解説します。
例えば以下のコードのように注文ステータスで処理を分けるプログラムがあったとします。
<?php
class Order
{
public function method1($orderStatus)
{
if ($orderStatus === 1) {
// 処理
}
if ($orderStatus === 2) {
// 処理
}
}
public function method2($orderStatus)
{
if ($orderStatus === 1) {
// 処理
}
}
}
チームメンバー(自分含む)が数字の意味を理解するのに時間がかかる
このコードを見て注文ステータスの1や2ってどんなステータスなのかわかりませんよね。
注文受付中なのか、キャンセルなのか、はたまた発送完了して注文処理完了なのか…
残念ながら(意味不明な)数字を見た人はその数字の意味を調べる旅に出ないといけません。
それはとても非効率です。
数字を変更したい場合に複数箇所の修正が必要になることがある
仮にキャンセルのステータスを数字の1
と設定していたとします。
(あまりあってはいけないですが)アプリケーションの仕様変更でキャンセルを3
に変更しなければならなくなった場合、上記コードの中に1
はmethod1、method2それぞれにあるので2箇所の修正が必要です。
これが10箇所、100箇所…となっていった場合、たった1つの数字の変更がどれほど大変な作業になるかは容易に予想できると思います。
Laravelでマジックナンバーを対策する方法を知ろう
まず、対策方法としては言語・フレームワークに関わらず決まっており
その数字がどういう意味なのかを表す定数を定義する
です!
というわけで、Laravelでマジックナンバーを対策する方法を解説します!
クラス定数を定義する
先ほどのコードをクラス定数を定義して書き直します。
<?php
class Order
{
// クラス定数を定義
private const ORDER_STATUS_CANCEL = 1;
private const ORDER_STATUS_PREPARE = 2;
public function method1($orderStatus)
{
if ($orderStatus === self::ORDER_STATUS_CANCEL) {
// 処理
}
if ($orderStatus === self::ORDER_STATUS_PREPARE) {
// 処理
}
}
public function method2($orderStatus)
{
if ($orderStatus === self::ORDER_STATUS_CANCEL) {
// 処理
}
}
}
キャンセルは1
、準備中は2
を表すクラス定数ORDER_STATUS_CANCEL
、ORDER_STATUS_PREPARE
を定義しています。
// クラス定数を定義
private const ORDER_STATUS_CANCEL = 1;
private const ORDER_STATUS_PREPARE = 2;
あとは各メソッドで呼び出して使うだけですね。
if ($orderStatus === self::ORDER_STATUS_CANCEL) {
// 処理
}
この状態だとコードを読むときに『ふむふむ、注文ステータスがキャンセルの時の処理ね!』と簡単に理解できます。
また、キャンセルを1
→3
に変更することになってしまってもクラス定数を下記のように変更すれば良いので、修正は1箇所で済みます。
// クラス定数の値を1→3に変更
private const ORDER_STATUS_CANCEL = 3;
クラス定数はprivateにしているのでそのクラスでしか使わない値を定義する時に使うのが良いです。
configファイルを作成する
次はconfig(設定)ファイルを作成する方法です。
Laravelのconfig
ディレクトリにconst.php
を作成します。
(ファイル名は自由ですが定数を定義するファイルなのでconstにしています)
<?php
return [
'orderStatus' => [
'cancel' => 1,
'prepare' => 2,
],
];
これをモデル(やコントローラー)で呼び出します。
<?php
class Order
{
public function method1($orderStatus)
{
if ($orderStatus === config(const.orderStatus.cancel)) {
// 処理
}
if ($orderStatus === config(const.orderStatus.prepare)) {
// 処理
}
}
public function method2($orderStatus)
{
if ($orderStatus === config(const.orderStatus.cancel)) {
// 処理
}
}
}
以下のコードで
configディレクトリのconst.phpのorderStatusというキーの配列の中のcancelというキーの値を取得する
という意味を表します。
config(const.orderStatus.cancel)
クラス定数の方法と同様、コードを読めば簡単に注文ステータスを理解できるようになりました。
configファイルに設定するとどのクラスから値を取得することができるので、複数のクラスから取得したい値を定義するのが良いです。
(クラス定数を使うとクラス毎に同じ定数を定義する必要があります…)
定数クラスを作成する
最後に定数クラスを作成する方法です。
app
ディレクトリにConsts
ディレクトリを作成し、その中にOrderStatusConsts.php
を作成します。
(Consts
ディレクトリ、OrderStatusConsts.php
ともに名前は自由ですがわかりやすいように命名しています)
<?php
namespace App\Consts;
class OrderStatusConsts
{
public const CANCEL = 1;
public const PREPARE = 2;
}
次にモデルやコントローラーで呼び出すときの記述を簡潔にするために、config/app.php
にエイリアス(別名)を定義しておきます。
<?php
return [
(略)
'aliases' => [
(略)
// 追記
'OrderStatusConsts' => App\Consts\OrderStatusConsts::class,
],
];
モデルで呼び出します。
<?php
class Order
{
public function method1($orderStatus)
{
if ($orderStatus === \OrderStatusConsts::CANCEL) {
// 処理
}
if ($orderStatus === \OrderStatusConsts::PREPARE) {
// 処理
}
}
public function method2($orderStatus)
{
if ($orderStatus === \OrderStatusConsts::CANCEL) {
// 処理
}
}
}
クラス定数を定義する方法とconfigファイルを作成する方法と同様、『何だこの数字?』となることはなくなりました。
定数クラスを定義する方法はconfigファイルへの定数定義と同じく、複数のクラスからアクセスする値を定義する時に使うのが良いです。
最後に


マジックナンバーはチーム開発をする上で開発効率を下げる原因になるので必ず無くしましょう。
おさらいですが、マジックナンバーの概要とLaravelでの対策方法をまとめます。
マジックナンバーの概要
- チームメンバー(自分含む)が数字の意味を理解するのに時間がかかる
- 数字を変更したい場合に複数箇所の修正が必要になることがある
- マジックナンバーとは自分はコードを書いている時は理解できているけど、同じチームメンバーや自分が意味を理解できなくなってしまった数字
Laravelでの対策方法
- クラス定数を定義する
- configファイルを作成する
- 定数クラスを作成する
チーム開発では自分が理解できれば良いという気持ちはチームメンバーにも迷惑をかけチームの開発効率を下げる原因になってしまいます。
コードを書く上で気をつけるべきことはたくさんありますが、その1つのマジックナンバーを防いで快適な開発ライフを送りましょう。
コメント