嵐の前の静けさ
十二杯目の夜。
いつもの時間ではなかった。少し遅い。会社を出たのが遅かったのではなく、路地裏の角で一度立ち止まったからだ。
エンジニアの加藤くんから受けた報告が、まだ頭の中をぐるぐる回っている。消費税率の改定対応——先週の話の続きだ。バグを追いかけたチームが行き着いた先は、一つの巨大なクラスだった。OrderProcessorクラス。1,200行。メソッドが40以上。社内のほとんどのモジュールから参照されている。加藤くんは「すべての問題がここに集まっています」と言った。
重い木の扉に手をかけた。11回押してきた扉。今夜で——何回目だろう。数えなくてもわかる。12回目だ。
押した。いつもの軋み。いつもの空気。
バーには誰もいなかった。ゲスト客がいない夜は初めてだ。マスターがいつもの場所に立っていて、カウンターが磨き上げられていた。いつも以上に。まるで今夜のために磨いたみたいに。
「いらっしゃいませ」
穏やかな声。11回聞いた声と同じで、同じでないような気がした。
メニューを見なかった。見なくてよかった。
「今夜は——私が選びます」
マスターが一瞬だけ、目の奥に何かを浮かべた。10回通えば気づけなかった類の変化。11回通ったから——いや、12回目だからわかる。温かいものが奥にある。名前はつけられない。
「かしこまりました」
棚を見た。グレンファークラス、ジョニーウォーカー グリーン、ボウモア、アードベッグ——全部知っている。名前だけじゃない。どの夜に出されたか、何の話をしていたか、その一杯が何を照らしていたかを、覚えている。
直感で一本を指した。銘柄は重要ではない。選んだことが重要だった。
マスターが静かにグラスに注いだ。受け取って、一口含む。
視線が自然に落ちた。取り置きボトル。真正面。先週——いや、11回目の夜からそのまま。麻布がずれて中が見えている。
逃げられないほど、目の前にある。
「マスター」
声が思ったより静かだった。
「このボトルのこと——聞いてもいいですか」
取り置きボトルの開封
マスターの手が取り置きボトルに伸びた。
12回通って、このボトルに触れるマスターを見るのは初めてだった。通うたびに少しずつ位置が変わり、麻布がずれ、琥珀色がちらつき——気づけばいつも視界の端にあった。一度手を伸ばしかけたとき、「まだ、早いですよ」と静かに止められたことがある。
今夜、マスターは止めなかった。
麻布を外す所作は、いつもウイスキーをサーブするときと同じ丁寧さだった。布がカウンターに落ちて、中身が——全部、見えた。
琥珀色。でも以前ちらりと見えた色よりもずっと濁っている。複数の原酒が混ざり合って、どの個性も識別できない。甘さと苦味と煙と青さが溶け合って、一つの「重い」色になっていた。
反射的に鼻を近づけた。11回の夜で育った鼻が反応する。甘い——でも雑味が強い。一つ一つの香りが喧嘩している。潰し合っている。どこかで嗅いだ匂いが、何層にも重なって、何一つはっきりしない。
「たくさんの匂いがするのに——一つも、はっきりしない」
マスターが静かに言った。
「こちらは——11回の夜にお出しした原酒を、同じ瓶に注ぎ足したものでございます」
11種。11回の夜。11杯のウイスキー。
「一つの瓶に、すべてを」
「はい。グレンファークラス、ジョニーウォーカー、ボウモア、グレンドロナック、白州、アードベッグ——これまでの夜にお出ししたすべてを」
マスターが一拍置いて、言った。
「これは——あなたの会社のシステムです」
心臓が跳ねた。
比喩だ——でも比喩じゃない。11種の原酒を一つの瓶に注ぎ足した。11の問題を一つのクラスに注ぎ足した。
「OrderProcessorクラス、のこと——ですか」
マスターが頷いた。その頷き方は「はい」という肯定だけとは違っていた。何が違うのか言葉にはできないが、11回の夜のすべてが、今この瞬間のためにあったのだと——そう言っているように見えた。
11の記憶
マスターがカウンターの下からテイスティングノートを取り出した。
何度も見ていた。マスターが営業中に何かを書き留めていた、あの革表紙のノート。「お客様の好みを記録しています」と聞いたことがある。ウイスキーの好みを、と。
開かれたページ。
ウイスキーの好みではなかった。
1ページ目——日付。そして、私の言葉。
「36とか72とか、謎の数字がいっぱいあるのよね。動いてるからいいのよね」 —— Magic Numbers — 定数化・型制約
私の目が揺れた。これは——初めての夜に漏らした言葉だ。バーカウンターに肘をついて、新人くんの話を笑いながら聞いていた夜。他人事だと思っていた夜。
2ページ目。
「うちのOrderクラス、顧客情報も在庫情報も全部持ってて。便利よね」 —— Feature Envy — 責務の切り離し
3ページ目。
「田中さんが書いたコード、3年前から残ってて——怖くて消せないですよね」 —— Dead Code — 不要コードの除去
4ページ目。
「基底クラスの半分を空でオーバーライドしてるって言ってたの。そういうものなんでしょ?」 —— Refused Bequest — 継承より合成
5ページ目。
「なんでも一度マネージャークラスを通す設計にしてるの。安全だからって」 —— Middle Man — 委譲の適正化
6ページ目。
「メールアドレスも電話番号も全部文字列で持ってる」 —— Primitive Obsession — 値オブジェクト・型制約
7ページ目。
「手順書って、ステップが増えたら困らない? うちは三十あるんだけど」 —— Temporal Coupling — 不変設計・ビルダー
8ページ目。
「矢印がずらっと並んでたわ。うちのエンジニアは当たり前だって言ってたけど」 —— Law of Demeter — 委譲による結合度低減
9ページ目。
「前のCTOが全部設定してて……辞めてからは誰もわからない部分がたくさんあるの。引き継ぎ資料もない」 —— Service Locator — 依存性注入
10ページ目。
「『将来必要になる』って作った抽象化層が3つあって。もう3年、一度も使われてない」 —— Speculative Generality — YAGNI
11ページ目。
「消費税率の変更で15ファイルも修正が必要になったの。エンジニアがおかしいって顔してたわ。……私も、おかしいと思った」 —— Shotgun Surgery — 責務の集約
ページをめくるたびに、11回の夜が蘇った。バーの席で、ウイスキーのグラスを傾けながら、自分がいかに無防備に会社のことを漏らしていたか。——そして、マスターがその一つ一つに名前を付けていたこと。
12ページ目は——空白だった。
「ここから先は」
マスターの声が、いつもより少しだけ柔らかかった。
「あなたが、お書きください」
なぜ最初から言ってくれなかったの?
沈黙が落ちた。カウンターの木目の筋が、いやに鮮明に見えていた。
「最初から——わかっていたんですか」
「はい」
その一言が、11回分の夜の重さを持っていた。
初めての夜、「36とか72とか謎の数字がいっぱいあるの」と笑いながら言ったとき。2回目の夜、「Orderクラスが全部持ってて便利よね」と他人事の顔で言ったとき。3回目の夜、「田中さんのコード、怖くて消せない」と困った顔で言ったとき。——全部、聞いていた。聞いて、名前を付けて、ノートに書いた。
なのに、一度も言わなかった。「あなたの会社のコードに問題がありますよ」と。
手が微かに震えた。怒りではない。11回分の時間への、惜しさ。もっと早くわかっていれば。もっと早く手を打てていれば。
「なぜ——最初から言ってくれなかったんですか」
マスターがグラスを磨く手を止めた。12回通って、マスターが手を止めるのを何度も見てきた。でも今夜のそれは違った。グラスをカウンターに置いて、こちらを向いた。正面から。
「ウイスキーの味は——自分の舌でしか、学べません」
その言葉を聞いた瞬間、何かが——落ちた。胸のどこかで、ずっと宙に浮いていたものが。怒りが溶けて、溶けた後に残ったのは、「ああ」という感覚だった。説明されて理解したのではない。11回の夜を自分の足で歩いたから、この一言の重みがわかる。
10回目の夜を思い出した。マスターが「私も誰も注文しないカクテルをメニューに載せていた」と言った夜。あの人にも、自分の舌で学んだ夜があったのだろう。
長い息を吐いた。
「——動いてるだけじゃ、足りなかった」
口からこぼれた言葉に、自分で驚いた。初めての夜に「動いてるからいいのよね」と言った自分が、遠い。3回目の「とりあえず動いてるし」も、5回目の「動いてるうちは大丈夫でしょ」も、6回目の「動いてる……わよね?」も、9回目の「動いてるけど……」も。先週の夜にはこの言葉自体が出てこなくなっていた。
そして今夜、最後の形になった。
テイスティング——自分の言葉で
マスターが濁ったボトルを私の前に置いた。
「——いかがですか。あなたの会社のシステムを」
いつもはゲスト客のコードに対してマスターがやっていたこと——テイスティング——を、私がやる番なのだ。コードの行は読めない。エンジニアの言葉では語れない。でも、11回の夜で育った「鼻」がある。
濁ったボトルに鼻を近づけた。目を閉じた。
「このシステムには——名前のない数字が散らばっている」
グレンファークラスの夜が蘇る。105という数字だけの名を持つウイスキー。
「36は無料トライアルの日数。72はセッションタイムアウトの秒数。でもコードには、ただ数字だけが書いてある」
マスターが静かに頷いた。言葉が次から次へとこぼれた。11回の夜で嗅いだ匂いが、一つずつ名前を持って浮かび上がってくる。
他人のデータに手を伸ばすクラス。呼ばれないまま残った3年前のコード。半分空のオーバーライド。何もせず転送するだけのマネージャー。型のない文字列。順番を間違えたら壊れる初期化。ドットの連鎖。辞めたCTOしか知らない設定。誰も使わない抽象化層——。
どの匂いにも、あの夜のウイスキーの記憶が重なっていた。
「そして——消費税率の変更で15ファイル。一つを変えたら、全部に影響する」
目を開けた。
「全部、このクラスの中にある。一つの樽に、全部詰め込んでしまった」
マスターが頷いた。
「God Class、と呼ばれています。一つのクラスにすべてを注ぎ足した——濁ったブレンド」
God Class。神のクラス。一つのクラスがすべてを知り、すべてを制御し、すべての変更がそこに流れ込む。
「11回分の問題が、全部ここに」
「いいえ」
マスターの声が静かに返った。
「11回分の答えも、全部ここに」
ブレンド——原酒を分ける
マスターが一枚の紙をカウンターに置いた。書かれていたのは、コードだった。
「あなたの会社のOrderProcessorクラスを——縮小したものとお考えください」
| |
エンジニアの言葉ではわからない。でも、11回の夜で覚えた目で見ると——
「税の計算と、割引と、在庫確認と、バリデーションと、通知——全部、同じ場所にある」
「はい。一つの樽に5種類の原酒を注ぎ足したようなものです。一つの味を変えたいだけなのに、樽ごと開けなければならない」
マスターが新しい紙を出した。
「同じ原酒です。ただし今度は——適切に分けます」
| |
「前回——バランタインの夜に、修理屋さんが書いたコード」
あの夜のゲスト客を思い出した。消費税率の変更で15ファイルを修正した、20代の保守担当エンジニア。あの子が書き直した TaxPolicy が、ここでも使われている。
「はい。あの夜の答えが、今夜の設計の一部になります」
マスターがさらに紙を出した。
| |
| |
| |
| |
「そして——これらを、一つの注文として束ねます」
| |
「……つまり——」
言葉を探した。11回の夜で学んだ言葉で。
「原酒を種類ごとに分けて、それぞれの瓶に入れる。税のことは税の瓶が知っている。割引のことは割引の瓶が知っている。注文は——それぞれの瓶から、必要なだけ注いで調合する。ブレンダーのレシピ帳に従って」
「はい。——同じ原酒でも、設計次第で味は変わります」
マスターの声が穏やかだった。いつもの穏やかさと同じで、同じでないような。
「消費税率を変えたいなら、TaxPolicyの1行だけ。割引のルールを変えたいなら、DiscountPolicyだけ。在庫のしきい値を変えたいなら、InventoryCheckerだけ。——散弾銃で壁中に穴をあけるのではなく、一丁のライフルで一つだけ撃つ」
Mooの has と型制約が、原酒を正しい瓶に入れるための仕組みだということが——言葉ではなく、11回分の夜の蓄積で、腑に落ちた。
再ブレンド
マスターが棚からボトルを一本ずつ降ろした。
グレンファークラス。ジョニーウォーカー グリーン。ボウモア。グレンドロナック。白州。アードベッグ。ラスティネイルの原酒。余市。タリスカー。終売蒸留所のボトル。バランタイン。——そして、空のブレンディンググラス。
11本。11回の夜。
「同じ原酒です」
マスターがブレンディンググラスに原酒を一つずつ加えていく。量を計り、順序を守り、それぞれの個性が活きるバランスを指先で探っている。カウンターの上の11本のボトルと、マスターの手元のブレンディンググラスと、テイスティングノートが、同じ直線上に並んでいた。
出来上がったブレンドは——濁ったボトルとは全く違っていた。透明感のある琥珀色。
「——いかがでしょうか」
受け取った。鼻を近づける。
11種の香りがする。でも一つにまとまっている。それぞれの原酒の個性が潰し合わずに共存している。グレンファークラスの甘さ、ボウモアの煙、アードベッグの力強さ、白州の爽やかさ——全部がそこにあるのに、一つの味として調和している。
「……たくさんの味がする。でも一つにまとまってる」
言ったあとに気づいた。同じ言葉を——11回目の夜に、バランタインを飲んで言った。でもあの夜は「なぜまとまるのか」がわからなかった。今夜はわかる。原酒が適切な量で、適切な順序で、適切な設計のもとに調合されているから。
一つの瓶にすべてを注ぎ足した濁ったブレンドと、11種の原酒を適切に調合したオリジナルブレンド。同じ材料。同じ量。設計だけが違う。
小さく笑った。何がおかしいのか自分でもよくわからない。でも——12回分の重みを含んだ笑いだった。
ラストオーダー
テイスティングノートの空白のページに、もう一度指先で触れた。紙の手触りが冷たい。
「ここから先は——私が書くんですね」
マスターが穏やかに頷いた。
「はい」
それだけだった。それだけで十分だった。
立ち上がった。コートを羽織った。いつもの動作。でも今夜は——重さが違う。11回分の夜を置いて、12回目の夜を持って帰る。
「マスター」
振り返りかけて——やめた。
言いたいことは、もう全部言った。11回分の夜のすべてが、テイスティングノートの中にある。残りの空白ページは、自分で書く。
扉に手をかけた。押した。路地裏の夜風が頬に触れた。
ペンが紙を擦る、かすかな音が聞こえた気がした。扉が閉まりかける隙間から。マスターが何を書いたかは見えない。
振り返らなかった。
路地裏は静かだった。遠くで車のエンジン音がして、どこかの店のドアが閉まる音がして、それからまた静けさが戻った。
そして私は今夜、自分のコードの匂いを、初めて自分の鼻で嗅いだ。
🥃 マスターのテイスティングノート
本日の銘柄: マスターのオリジナルブレンド お客さまの症状: 神のクラス(God Class)
ノージング(香り)── 問題の検知
一つのクラスが「Manager」「Processor」「Handler」という名前を持ち、税計算も在庫確認も通知もバリデーションもすべて引き受けているなら、このアンチパターンを疑いましょう。クラスの説明に「そして」が3つ以上連なるとき——それは一つの樽にすべてを注ぎ足した濁ったブレンドです。
パレット(味わい)── 問題の本質
God Classは単に「大きい」のではありません。複数の無関係な責務が一箇所に集中することで、すべての変更がこのクラスに流れ込みます。Magic Numbers、Feature Envy、Dead Code、Shotgun Surgery——11のアンチパターンは、God Classという一つの巨大な樽の中で互いに雑味を生み合っていたのです。
フィニッシュ(余韻)── 解決の方針
Single Responsibility Principle——一つのクラスが変更される理由は一つだけ。Mooの has と InstanceOf で責務ごとの専門クラスに委譲し、God Classを薄いオーケストレーション層に変えます。税率のことは TaxPolicy が知り、在庫のことは InventoryChecker が知る。同じ原酒でも、設計次第で味は変わります。
ペアリング(相性の良いパターン)
- Single Responsibility Principle(変更理由を一つに閉じる)
- Extract Class(大きなクラスから責務を抽出する)
- Moo::Role / Composition(継承ではなく合成で設計する)
「ウイスキーの味は——自分の舌でしか、学べません」
