マスターがグラスに氷を入れている。
席に着いたばかりだった。いつもの席。5回目ともなると椅子の高さにも慣れて、腰を下ろした瞬間にカウンターと自分の位置がぴたりと合う。
白いラベルに緑の文字。棚から降ろされたボトルが、カウンターの上で暖色の照明を受けている。
「今夜は軽やかに」
注文していない。何も言っていない。なのにマスターはもうボトルを傾けている。
琥珀色——というほど濃くない。白州。淡くて明るい、若葉のような色。グラスの中に注がれたそれに、マスターが炭酸水をゆっくり加える。泡が立ち上り、氷がかすかに鳴った。
「……わかるんですか、今日の気分」
マスターが穏やかに微笑んだ。
「お顔を見れば」
嬉しかった。メニューを見て「おすすめを」と言っていた頃が遠い。通っているなあ、と思う。
口をつけると、軽い。爽やかだ。先週のグレンドロナックの重厚さとはまるで違う。柑橘の香りが鼻を抜けて、泡と一緒に消えていく。
「おいしい。これは——白州ですか」
「はい。ハイボールにすると、白州の青みのある香りが軽やかに立ちます」
カウンターの端に、あのボトルがある。麻布をかぶった取り置きボトル。前回よりまた近い。確実に、私の座っている側に寄っている。もう聞かない。聞いたところではぐらかされるだけだから。ただ「近いな」と思う。
来店——炭酸が立てる泡
扉がきっちりと開いた。
「きっちり」としか言いようのない開け方だった。力まず、乱暴でもなく、ちょうど人ひとり分の幅を確保して、まっすぐ入ってくる。ジャケットの袖をきれいにまくった男性。革の手帳を小脇に抱えている。
マスターが声をかけた。
「いらっしゃいませ。今夜は何をお召し上がりになりますか」
「ジンソーダをお願いします。——すみません、実は設計の相談で来たんですが」
丁寧だけど無駄がない。会議の冒頭で「今日のアジェンダは」と切り出しそうな、そういう人だ。心の中で「マネージャーさん」と呼んだ。仕切りが上手そうな雰囲気。会議室にいそう。
マネージャーさんはジンソーダを一口飲んで、革の手帳を開いた。付箋が几帳面に貼ってある。
「私はもともとエンジニアだったんですが、3年前にPMに転向しました。ただ、今もアーキテクチャレビューには参加していまして」
なるほど、エンジニア出身の管理職か。うちの会社にもいるタイプだ。
「弊社のフレームワークでは、ドメインクラスが外部サービスを直接呼ばないように、すべて Manager クラスを経由する設計にしています」
思わず口を挟んだ。
「あ、それうちもやってる! うちの開発チーム、なんでも一度マネージャークラスを通す設計にしてるの。安全だからって」
マネージャーさんの目が輝いた。
「おお、御社もですか! やっぱりそうですよね。たとえば OrderService を使うときは OrderManager を通す。間に一枚噛ませるのが定石です」
間に一つクラスを挟んで整理する——前回の委譲の話でぼんやり理解した仕組みだ。同じことをやっていると聞いて、なんだか嬉しい。
「わかるわー、私もそういう仕事してるから。取引先とエンジニアの間に立って仲介するの」
自分で言って、妙にしっくりきた。「間に立つ」仕事をしている人間として、マネージャーさんの話は他人事じゃない。
マネージャーさんが嬉しそうにうなずいた。けれどすぐに表情を曇らせた。
「ただ……最近、新人に言われたんです。『この Manager クラス、何もしてなくないですか?』って」
マネージャーさんがタブレットを取り出して、コードを見せてくれた。
| |
「見てください、5つのメソッドすべてが OrderService ときれいに対応しています。統一された窓口です」
嬉しそうだった。仲間を見つけたからか、新人に言われる前の自信が戻っている。
「右から左にきれいに流れてるのね」
「そうなんです。シンプルで、一貫性がある」
私もうなずいた。「間に立って整理するって大事よね。全部直接やりとりしたらカオスだもの」
マスターが静かにうなずいた。「おっしゃる通りです。中間者が必要な場面はございます。——問題は、この中間者が必要かどうかです」
テイスティング——薄まるハイボール
マスターがカウンターの下からもう一つグラスを取り出した。
氷を入れる。白州を注ぐ。そこまでは私のハイボールと同じだった。しかし炭酸水を注ぐ手が——止まらない。
注いでいる。まだ注いでいる。
グラスの中のウイスキーの色がどんどん薄まっていく。淡い琥珀から、透き通った黄色へ。黄色から、ほとんど透明へ。
「ハイボールは、ウイスキーの個性を炭酸が引き立てる飲み方です。——しかし、炭酸を足しすぎれば」
グラスの中は、ただの炭酸水にしか見えなかった。
「中身が、消えます」
マネージャーさんの手帳を持つ手が止まった。
「お客さまの OrderManager は、このグラスと同じ状態でございます。中を通る度に、何も加えずに通過させている。ウイスキーの色——つまりクラスの責務が、薄まって消えています」
「この状態を、Middle Man と呼びます」
なぜ問題なのか
マスターが続けた。
「Middle Man が問題になる理由は、3つございます」
「まず、認知的負荷の増加です」
聞き慣れない言葉だった。
「コードを読む人が OrderManager を開きます。しかし実装はありません。OrderService に転送しているだけです。読む人はもう一段掘って OrderService を開かなければなりません。クラスが増えるほど、たどる道が長くなる。迷路の中に空部屋がある状態です」
マネージャーさんが眉をひそめた。「迷路の空部屋……」
「次に、変更の二重コストです。OrderService に新しいメソッドが追加されるたびに、OrderManager にも同じ転送メソッドを手書きしなければなりません。一箇所の変更が二箇所の変更になります」
マネージャーさんが嘆息した。「先月 archive_order を追加したとき、Manager にも丸写しのメソッドを書かされました」
「最後に、偽の安心感です。『Manager を通しているから安全だ』と思い込んでいても、何もチェックしていない Manager は安全を担保していません。鍵のかからないドアが付いているだけでございます」
私はうなずいた。「わかる。うちの会社のSlack経由の承認フローみたい。全部通すけど何もチェックしてないの」
言ってから、自分の会社のことをまた漏らしていることに気づいた。最近多い。ゲスト客の話を聞くたびに、うちのことが口から出る。
マスターが薄まったグラスを静かに下げた。
「炭酸を足すたびに薄まっていく。やがて、元のウイスキーの味は誰にもわからなくなります」
中間者が必要なとき
マネージャーさんが反論した。さすが元エンジニア、論理で返してくる。
「しかし、カプセル化は重要な設計原則ではないですか。内部の実装を隠すことで——」
マスターが穏やかに遮った。
「おっしゃる通りです。カプセル化は重要でございます。——ですが、OrderManager は何を隠していますか?」
マネージャーさんが口を開きかけて、閉じた。画面のコードを見返している。確かに——全部、受け取ったものをそのまま渡しているだけだ。何も変えていない。何も止めていない。何も隠していない。
「カプセル化が効果を発揮するのは、内部の実装詳細を隠すときです。隠すべきものがないのに中間者を置いても、それはただの迂回路でございます」
私が口を挟んだ。「じゃあ、間に立つのが全部ダメってわけじゃないのね? 鍵がちゃんとかかるドアなら意味がある、ってこと?」
「ええ。バリデーション、ログ記録、アクセス制御——中間者が付加価値を提供しているなら、それは Middle Man ではありません。必要な中間者です」
ブレンド——炭酸の量を見極めるブレンダーの仕事
マスターが口を開いた。
「解決策は、不要な中間者を取り除くことです」
解決策1: Remove Middle Man(直接呼び出し)
「最もシンプルな方法は、OrderManager を経由せず、OrderService を直接使うことです」
| |
マネージャーさんが戸惑った顔をした。「それだけですか? でもカプセル化が——」
「OrderManager は何も隠していませんでした。右から左に渡しているだけです。カプセル化の名目で中間者を置いても、隠すべきものがなければ、それはただの迂回でございます」
解決策2: 選択的委譲(固有ロジックのあるメソッドだけ残す)
「もし OrderManager に固有のロジックを持つメソッドと、ただの転送メソッドが混在している場合は、handles で整理できます」
| |
「handles は Moo が自動で委譲メソッドを生成します。手書きの転送コードが消える分、コードが減り、意図が明確になります。手書きで残すのは、バリデーションやログなどの付加価値を持つメソッドだけです」
私が思わず言った。「ちょうどいい炭酸の量ってことね。足しすぎたら薄まるし、足さなきゃストレートのまま」
マスターがわずかにうなずいた。
「まさに、そのとおりでございます」
前回褒められたときは「見事な例え」と言われた。今回は短いうなずきだけ。でも穏やかな目が「わかっている」と言っていた。——気がした。
前回の委譲との対比
マネージャーさんが考え込んでいた。
「先ほどの handles ですが——これを全メソッドに適用したら、結局同じことになりませんか?」
マスターの声がわずかに力を帯びた。
「鋭いご質問です。handles で全メソッドを委譲してしまえば、それはまた Middle Man になります。転送コードが手書きか自動かの違いだけで、構造的には変わりません。——道具は、使い方次第でございます」
私はふと前回のことを思い出した。前回は handles で「必要なものだけ選ぶ」という話だった。今回は逆に「全部委譲したら意味がない」。同じ道具なのに。
「ねえマスター。前に来たとき、handles は選ぶための道具だって聞いたけど——全部選んだらダメってこと?」
「ええ。あのときの Refused Bequest は《もらいすぎたものから必要なものだけ選ぶ》問題でした。今回の Middle Man は《何も付け加えずに通すだけ》の問題です。同じ道具でも、選ぶ数を間違えれば、また別の問題が生まれます」
なぜ問題が消えるのか
マスターが指を三本立てた。
「3つの問題がどう変わるか確認しましょう」
「まず、認知的負荷と変更の二重コスト。中間者そのものを取り除けば、読む人は OrderService を直接開くだけで済みます。迷路から空部屋が消え、変更も一箇所で完結します」
「そして偽の安心感。選択的委譲で OrderManager を残す場合——残ったメソッドにはバリデーションが入っています。鍵がかかっている。残ったものには、存在理由があるのです」
マネージャーさんが目を閉じた。考えを整理しているようだった。やがて目を開けて、静かに言った。
「つまり——中間者がいること自体が問題なんじゃなくて、何もしていない中間者が問題なんですね」
マスターがうなずいた。
「ええ。中間者に価値があるかどうか。それが判断の軸でございます」
ラストオーダー——間に立つということ
マネージャーさんが立ち上がった。革の手帳を閉じる。来たときのテキパキした足取りが、少しだけゆっくりになっていた。
「考えてみれば、PMの仕事もそうです。ただ右から左に伝えるだけなら、自分がいる意味がない。自分だから付けられる価値があるから——間に立つ意味がある」
独り言のようだった。小さく会釈をして、扉に向かう。
その背中に、マスターが静かに声をかけた。
「炭酸の量を見極めることも、ブレンダーの大切な仕事でございます」
マネージャーさんが一瞬だけ振り返って、小さくうなずいた。そして扉の向こうに消えていった。
マスターがカウンターの上のグラスを下げた。マネージャーさんのジンソーダと、あの薄まったハイボール。
帰り支度をして扉に向かう。路地裏に出ると、初夏の風がぬるい。歩きながら、さっき自分が言った言葉を反芻した。
「取引先とエンジニアの間に立って仲介するの」
取引先の要望をそのままエンジニアに伝えて、エンジニアの状況をそのまま取引先に返して。私は——右から左に流しているだけじゃないだろうか。
考えて、やめた。考えたところで今夜は答えが出ない。でも考えたこと自体が、たぶん何かの変化なのだ。
ふと、口をついて出た。
「まあ、回ってるんだから大丈夫か」
でもその言葉は妙に軽かった。ハイボールの炭酸みたいに、するっと抜けていった。
🥃 マスターのテイスティングノート
本日の銘柄: 白州ハイボール
お客さまの症状: 中間者(Middle Man)
ノージング(香り)── 問題の検知
クラスのメソッドの大半が、別のクラスの同名メソッドにそのまま転送されていたら、Middle Man を疑いましょう。引数の変換もバリデーションもログもない——ただ右から左に流しているだけのメソッドが並んでいたら、そのクラスは中身が消えかけています。
パレット(味わい)── 問題の本質
Middle Man は3つの問題を引き起こします。コードを読む人に余計な一段を掘らせる認知的負荷、委譲元への変更が二箇所に波及する二重コスト、そして「Manager を通しているから安全」という偽の安心感です。何もチェックしていないクラスは、安全を担保していません。
フィニッシュ(余韻)── 解決の方針
シンプルな解決策は Remove Middle Man——中間者を取り除いて直接呼び出しに戻すこと。中間者に一部固有のロジックがある場合は、handles で転送メソッドを自動化し、手書きで残すのは付加価値のあるメソッドだけに絞ります。handles で全メソッドを委譲すれば、それはまた Middle Man の再現です。
ペアリング(相性の良いパターン)
- Facade パターン(複数サービスの統合が目的なら Middle Man ではない)
- Law of Demeter(過度なメソッドチェーン回避と Middle Man のバランス)
- Refused Bequest(前回。委譲の「量」を見極める対の問題)
「炭酸の量を見極めることも、ブレンダーの大切な仕事でございます」
