私がこのバーに通い始めたのは、コードの匂いなんてまるでわからなかった頃のことだ。
その日、看板のない路地裏の店を教えてくれたのは、取引先の営業担当だった。「面白い人がいるんですよ、コードの話をウイスキーで解く人が」。半信半疑で重い木の扉を押すと、カウンターだけの小さな空間が広がっていた。磨き上げられた一枚板のカウンターに指先で触れると、すべすべした木目の感触が心地よかった。壁一面に並ぶウイスキーのボトル、そしてその向こうに、白いシャツに黒のベストを着た男が立っている。
「いらっしゃいませ。今夜は何をお召し上がりになりますか」
穏やかな声だった。私はボトルの壁を見上げて、少し笑った。
「おすすめを」
何を選べばいいかなんて、わからなかったから。
来店——105という名の琥珀
マスターがカウンターの奥へ手を伸ばし、一本のボトルを取った。琥珀色の液体をグラスに注ぐ。濃い、力強い色だ。氷を入れないストレート。グラスを目の前に置かれた瞬間、甘く、どこか焦がしたような濃厚な香りが鼻先をかすめた。
「グレンファークラス 105でございます」
「105? お酒の名前が数字なの?」
「ブリティッシュプルーフで105。アルコール度数にすると60%——つまり、この琥珀色の液体の強さを、数字だけで名付けたお酒です。今夜はストレートで」
一口含んだ。甘い果実のような香りのあとに、強烈な熱が喉を走り抜けた。目が潤む。
「……つよい」
「ええ。ですが——105という数字だけを聞いて、この味を想像できる方はほとんどいません」
マスターの言葉の意味は、そのときの私にはわからなかった。
余韻が舌に残っているうちに、扉が軋んだ。振り返ると、スーツの上着を脱いでネクタイを緩めた若い男性が立っていた。二十代前半に見える。途方に暮れた顔で、肩からノートPCの入ったバッグを提げている。
「あの、ここって予約とかいりますか」
「いいえ。どうぞ、お好きな席に」
新人くん——と私は心の中で呼んだ。入社したばかりの頃のうちのエンジニアに、少し雰囲気が似ていたから。
彼はカウンターの端にぎこちなく座り、しばらく黙っていた。マスターが水の入ったグラスを置くと、せきを切ったように話し始めた。
「あの、いきなりで変な話なんですけど……コードが読めないんです。自分の先輩が書いたコードが」
聞けば、入社二年目。半年前に先輩が退職し、引き継いだシステムのコードが数字だらけで、何をしているのかわからないという。
新人くんはバッグからノートPCを取り出し、画面をマスターに向けた。
「if文の中に36とか72とか3600が並んでて。先輩に聞こうにも、もういなくて」
| |
「36って何の36なんですか、って聞ける人がもういないんです」
私はグラスの105を見た。数字だけの名前のお酒。そういえば。
「……うちのシステムにも、36とか72とか、謎の数字がいっぱいあるのよね」
なぜそんなことを口にしたのか、自分でもわからない。新人くんの話を聞いていたら、なんとなく浮かんだだけだった。
「動いてるからいいのよね」
マスターがグラスを拭く手を止めた。ほんの一拍。カウンターの向こうから、静かにこちらを見た気がした。たぶん、気のせいだ。
テイスティング——ラベルのないボトル
「お客さま」
マスターが新人くんに向き直った。
「コードに書かれた36という数字。これは無料トライアルの日数でしょうか、それともセッションの有効期限でしょうか」
新人くんは考え込んだ。
「えっと……たぶんトライアル日数、だと思うんですけど……。72は何だろう。3600は秒だから1時間? でも確証はないです」
「お客さまのコードは、Magic Numbers——マジックナンバーと呼ばれる状態です」
マジックナンバー。聞いたことのない言葉だった。マスターは続けた。
「コードの中に裸のリテラル値——つまり、数字がそのまま書かれていて、その意味が文脈から読み取れない状態を指します」
私は思わず新人くんに聞いた。
「ねえ、書いた人がいなくなったら、もう誰にもわからないの? ドキュメントとかないの?」
新人くんは力なく首を振った。「仕様書もないんです。コメントもなくて」
マスターが棚のボトルを一本指さした。ラベルが剥がれたボトルだった。
「ラベルのないボトルは、中身を知る人がいなくなったとき、ただの液体になります」
新人くんが小さくうなずいた。「まさにそれです。先輩がいなくなって、36がただの数字になった」
なぜ問題なのか
マスターはカウンターに指で3つの点を打った。
「マジックナンバーの問題は、3つあります」
「まず、同じ数値でも意味が違うこと。36がトライアル日数だとして、別のファイルにある36がグリッドの列数だったら——一括置換した瞬間に、レイアウトも壊れます」
「次に、値を変更したいときの手間。トライアル期間を30日に変えるとき、すべてのファイルを検索して《この36はどの36か》を一つずつ判断しなければなりません」
「最後に、タイポが検出できないこと。3600を360と書き間違えても、プログラムはそのまま動きます。ただし、セッションが1時間ではなく6分で切れるようになります」
新人くんが頭を抱えた。「それ、うちのシステムで起きてたらどうしよう……」
私は横から新人くんに言った。「6分でセッション切れたら、お客さん怒るわよね、さすがに」
新人くんが苦笑いした。「怒るどころじゃないですよ。問い合わせ殺到です」
ブレンド——名前を付けるということ
「最初の一歩は、名前を付けることです」
マスターはおもむろにカウンターの下からノートを取り出し、何かを書き留めた。革表紙の手帳——テイスティングノートに見えた。書き終えると、新人くんに向き直った。
「Perlではuse constantで名前付き定数を宣言できます」
| |
新人くんは画面を見比べている。
「でも、値は同じですよね? 何が変わったんですか?」
「3つのことが変わりました」
マスターはグレンファークラスのボトルを持ち上げ、ラベルを指でなぞった。
「一つ目。36がFREE_TRIAL_DAYSになったことで、このコードを初めて読む人にも意味が伝わります。ラベルが貼られたボトルです」
「二つ目。トライアル期間を30日に変えたければ、定数の定義を1箇所変えるだけで済みます。ラベルの裏側に産地が書いてある——一箇所を直せば、すべての文脈で正しくなる」
「三つ目。FREE_TRILA_DAYSと書き間違えたら、コンパイルエラーになります。36を63と間違えても、Perlは何も言いません」
新人くんの目が明るくなった。「あ、テストでFREE_TRIAL_DAYSって書けば、何をテストしてるかもわかる……!」
もう一歩先へ
「もう一歩、踏み込んでもよろしいでしょうか」
マスターはボトルをカウンターに戻し、別の角度から語り始めた。
「定数は定義したファイルの中に閉じ込められます。テストのときだけトライアル期間を1日にしたい——そんなとき、定数では対応できません」
「Mooのhasを使えば、値をオブジェクトの外から注入できます」
| |
「isa => Intとすることで、文字列や小数が渡された瞬間にエラーになります。値の《意味》と《制約》が、コードに刻まれるわけです」
新人くんが身を乗り出した。「テストのときだけ値を変えられるってことですか?」
「ええ。SubscriptionService->new(free_trial_days => 1)と書けば、1日のトライアル期間でテストできます。本番のデフォルト値は変わりません」
「うわ、テスト書くとき毎回困ってたんです、固定値が変えられなくて!」
私はウイスキーのグラスを傾けながら、なんとなく思った。ラベルの話は経営でも同じだ。名前のない予算項目は誰も管理しない。——でも、それはただの感想。技術の話は、まだ私には遠い世界のことだった。
ラストオーダー——お取り置きです
新人くんは晴れやかな顔で立ち上がった。
「明日、まず定数に名前つけるところから始めます。ありがとうございました」
ノートPCをバッグにしまいながら、彼は私にも軽く頭を下げた。「ありがとうございます、お話に付き合っていただいて」
「頑張ってね」
扉が閉まり、店内に静けさが戻った。グラスの氷が溶ける音が、妙にはっきり聞こえた。
「あの子、嬉しそうだったわね」
「名前がつくと、問題ではなく、課題になりますから」
マスターの声は穏やかだった。
ふと、カウンターの端に目がいった。最も遠い位置に、麻布をかぶった一本のボトルが置いてある。さっきは気づかなかった。
「あのボトルは?」
「お取り置きです」
微笑むだけで、それ以上は何も言わない。
マスターがカウンターの下からあのノートを取り出し、何かを書き留めていた。
「お客さまの好みを記録しているのですか?」
「ええ、そのようなものです」
そうして私は店を出た。路地裏の夜風が肌に涼しく、扉の向こうからかすかにグラスの触れ合う音が聞こえた。なぜかもう一度この店に来たいと思った。
あの夜、私はまだ何も知らなかった。36という数字が、自分の会社に何をもたらしているのかも。
🥃 マスターのテイスティングノート
本日の銘柄: グレンファークラス 105
お客さまの症状: マジックナンバー(Magic Numbers)
ノージング(香り)── 問題の検知
コードの中に36, 72, 3600のような裸のリテラルが散在していたら、このアンチパターンを疑いましょう。「なぜその値なのか」がコードから読み取れないとき、それはラベルのないボトルです。
パレット(味わい)── 問題の本質
数字に名前がないということは、その意味が書いた人の頭の中にしかないということです。同じ36でもトライアル日数とグリッド列数では意味が違う。一括置換の事故、タイポの見逃し、そして「書いた人がいなくなったら誰にもわからない」——マジックナンバーは、コードから文脈を奪います。
フィニッシュ(余韻)── 解決の方針
use constantで名前を付けるのが第一歩。さらにMooのhasとTypes::StandardのIntで値をオブジェクトに注入すれば、テスト時の差し替え、型による不正値の検出、デフォルト値の一元管理が手に入ります。ラベルを貼ることで、「ただの数字」は「意味のある設定値」に変わります。
ペアリング(相性の良いパターン)
- Primitive Obsession(プリミティブ型偏執)—— 定数化の次のステップとして、値をオブジェクトに昇格させる
- Types::Standard による型制約 ——
EnumやIntで値の範囲と意味をコードに刻む - Single Responsibility Principle —— 定数値の管理責任を明確にする
「ラベルのないボトルは、中身を知る人がいなくなったとき、ただの液体になります」
