第1幕: 検分 ── 表の格子戸、ナギさんはもう手を動かしていた
表の格子戸のあたりに、朝の光が縞になって落ちていた。格子戸を透かして通りの明るさがそのまま入り込んでくる、素屋根の下の薄暗さとも蔵の土壁の冷たさとも違う場所だった。通りを人が歩くたびに下駄の音が響き、暖簾がひとつ、ふたつと揺れて、そのたび光の縞がわずかに動いた。表は、この店でいちばん人の出入りが多い場所だった。客が買った品を持って出ていく。配達の人が荷を運んでくる。仕入れの品も、たいていはこの戸をくぐる。奥の勘定場からは見えない、店の顔にあたる場所だ。
用があって表へ回ると、ナギさんがしゃがみ込んでいるのが見えた。格子戸の敷居のすぐ内側、通りからの光がいちばんよく当たる場所に座り込んで、手元には開いた端末があった。眉間に少し皺を寄せて、何かを書き足しているようだった。近づいても、こちらに気づく様子はなかった。
「おはようございます」
声をかけると、ナギさんは顔を上げて、少し慌てたように会釈した。
「あ、シオリさん。おはようございます」
覗き込むと、画面には見覚えのある形のコードが二つ並んでいた。片方はShop::Sales.pm――客が品物を持って表から出ていくときに動く処理、もう片方はShop::Delivery.pm――配達の品を受け取るときに動く処理。どちらも、末尾に同じような形の三行が書き足されていた。
| |
「旦那様が、出入りは全部帳面に付けろって仰ったので」
ナギさんが、手を止めずに答えた。
「格子戸を通る出入りを扱っている箇所を、一つずつ見つけて、記帳の処理を足しています。今のところ、ここと――」
lib/Shop/Delivery.pmの方を指す。そちらにも、directionが'in'に変わっているだけの、よく似た三行が入りかけていた。
「あとは、仕入れの受け入れの分がまだです」
三箇所目のlib/Shop/Supplier.pmは、まだ手つかずのまま開かれていた。
私は、二つのファイルを見比べた。技術的なことはよく分からないが、ファイルを開いて、書いて、閉じる――その三行が、ほとんど同じ形で二回繰り返されているのは、素人目にも分かった。表の格子戸は一つしかないのに、コードの上では、出入りを扱っている場所がいくつもあるらしい。ナギさんは、そのひとつひとつに、同じ形の目印を付けて回っているように見えた。
「全部の戸口に、同じ札を下げるんですか」
思ったままを口にした。ナギさんが、手を止めた。
「……そう言われると、そうですね」
答えながらも、次の一手は決めかねている様子だった。まだ三箇所目に取りかかっていない指が、宙で止まっていた。
第2幕: 手が入らない ── 数えても、今日数えた数が全部とは言えない
そこへ、クロベさんが通りかかった。ナギさんの手元をひと目見て、すぐには何も言わなかった。しばらく画面を眺めてから、口を開いた。
「それ、いくつある」
ナギさんが顔を上げた。
「今のところ、この二箇所と、仕入れの分と……あと、探せばもっとあるかもしれません」
「では、探しましょう」
クロベさんは、ナギさんの端末を借りて、Kido::pass_throughという名前で検索をかけた。呼んでいる箇所を、片端から拾っていく作業だった。
| |
出てきたのは二つだけだった。ナギさんがまだ手を付けていないShop::Supplierの分は、まだ書きかけですらないため、この検索には引っかからなかった。
「これで全部、ってことにはならないんですか」
私が訊ねると、クロベさんは首を振った。
「この探し方は、今あるファイルの中を見ているだけです。まだ書かれていない場所や、この店の外から動かす別の仕組みがあれば、そこは拾えません。それに、明日また新しい呼び先が増えるかもしれない――今日の数が、明日も同じだという保証はどこにもありません」
「今日探して二つ」
クロベさんが、画面を見たまま言った。
「だが、探したのが今日だけの分だとしたら、明日また増えていないと誰が言えますか」
ナギさんが、少し間を置いてから答えた。
「……言えません」
私は、そのやり取りを黙って見ていた。数を数えるという、いちばん確実に思える手立てが、確実ではないと分かった瞬間だった。今日見つけた二つに、明日三つ目が増えても、それに気づく仕組みは今のところどこにもない。
クロベさんが、端末を置いた。
「だから、数える方をやめます」
その言い方は、あきらめたようには聞こえなかった。むしろ、次の手をもう決めたときの声のように聞こえた。
ナギさんが、画面に残ったままの検索結果を覗き込んで言った。
「さっきの検索、二つとも呼んでいた名前は同じでしたね」
言われてみれば、たしかにどちらもKido::pass_throughという、まったく同じ名前だった。クロベさんがうなずく。
「呼ぶ側がいくつあっても、呼ばれている名前は一つです。その名前の中身を書き換えれば、呼んでいる数に関わらず効きます」
「戸は一つです。通る場所ごとに札を作らんでも、戸に札を下げればそれで足ります」
ナギさんが、少し面食らったような顔をした。私も、正直に言えば同じだった。呼んでいる箇所がいくつあるか分からないという話をしていたのに、その数を数えるのをやめると言う。矛盾しているようにも聞こえたが、クロベさんの顔には迷いがなかった。
数を数えることをやめる――それが、こんなに軽い言い方で済むとは思っていなかった。私は黙ってうなずいた。クロベさんも、それ以上は説明せずに、格子戸の方へ向き直った。
第3幕: 手立て ── 名前の中身だけを差し替える
クロベさんが、Kido.pmというファイルを開いた。Kidoというのは、表の格子戸を通る出入りを扱っているパッケージの名前だった。
| |
「これは、出入りの情報を組み立てて返しているだけです」
クロベさんが、画面の文字を目だけで追いながら言った。手は動かさなかった。
「誰が、何を、どちらの向きで通ったか――それを一つにまとめて返す。記帳は、まだしていません」
「じゃあ、ここに記帳を足せばいいんですか」
ナギさんが訊いた。クロベさんが首を横に振った。
「足すのは足すんですが、足し方が違います」
名前を移して、名前を作り直す
「既存の関数を、別の名前に移します。そして、元の名前で、新しい関数を作ります。新しい方は、前か後ろに新しい仕事をしてから、移した先を呼ぶだけです」
クロベさんが、要点を繰り返した。
「呼ぶ側は、名前が変わったことにすら気づきません」
私には、まだぴんと来なかった。ナギさんが訊ねる。
「前に見た、別の箱で包むやり方と、何が違うんですか」
「別の箱で包むやり方――」
クロベさんが、少し考えてから答えた。
「あちらは、新しい箱を作って、渡す物をその箱に差し替えます。差し替える場所は、使う側が書き換えないといけません。新しい箱に、何を入れるかを、使う側が決めるからです」
クロベさんが、比べるように短い例を挙げた。
| |
「これだと、Kidoを作っている場所――今回で言えば、この店のどこかにある組み立ての箇所――を、使う側が見つけて書き換えないといけません。今回のは、箱を作りません。名前の中身だけを差し替えます。だから、使う側は何も書き換えずに済みます」
私には、まだ半分くらいしか分からなかったが、ナギさんは何か腑に落ちた顔をしていた。
「呼ぶ場所を変えるか、呼ばれる場所を変えるか――そこが違うんですね」
「そうです」
クロベさんが、ようやく技法の名前を口にした。
「新しい戸を作るんじゃありません。今の戸に、化粧材を一枚足すだけです」
名前を移すときの注意
クロベさんが、実際にKido.pmを書き換え始めた。
「名前をまるごと写すと、危ういことになります。中身だけを写すのが安全です」
私には、それがどう危ういのか、すぐには分からなかった。クロベさんが、短く付け加えた。
「名前をまるごと写すと、古い方の名前も新しい方の名前も、同じ中身を指したままになります。あとで新しい方の中身だけを書き換えたつもりでも、古い方まで一緒に書き換わってしまう。呼び出すたびに、自分で自分を呼び続けることになります」
ナギさんが、少し顔をしかめた。
「止まらなくなる、ってことですか」
「そうです。だから、中身だけを写します」
一言だけ添えて、_pass_through_rawという名前で、元のpass_throughをそのまま移す。
「戻ってこない呼び方もありますが、それだと後の記帳が書けません。今回は前も後ろも要るので、ふつうに呼びます」
書き上がったKido.pmは、次の形だった。
| |
「pass_throughという名前は、変わっていません」
クロベさんが、書いたばかりのコードを指して言った。
「中身だけが、退避した先を呼んでから記帳する、という形に変わりました」
私は、少し戸惑った。
「記帳する先は、どこから来るんですか」
「そこです」
クロベさんが、build_recordingという関数を指した。
「pass_throughそのものには、記帳先を渡す引数を増やしません。増やすと、呼ぶ側全員が、記帳先という新しい引数を知らないといけなくなります。代わりに、別の入り口を一つ作って、そこで記帳先を組み立てます」
「元の関数の形は、変えない――ってことですか」
ナギさんが確かめる。
「そうです。呼ばれ方が同じなら、呼ぶ側は何も知らずに済みます」
「絵に描いてみてもいいですか」
私が訊ねると、クロベさんはうなずいた。野帳を開いて、今聞いたばかりの道筋を線でたどってみた。

三つの戸口から伸びる線は、どれも同じ太さで、pass_throughという同じ名前へ向かっていた。変わったのは、その名前の奥に新しく引かれた、もう二本の線だけだった。
記帳先そのものも、新しく作る必要があった。クロベさんが、続けてlib/Kido/Ledger.pmとして書いたのが次のクラスだった。
| |
「これは、渡された出入りの情報を、ただ溜めるだけのものです」
クロベさんが言った。
「記帳した中身をどう使うかは、今日の話には入っていません。今日は、通った記録を残すところまでです」
ナギさんの書きかけを元に戻す
「じゃあ、これは……」
ナギさんが、自分が書きかけていたShop::Sales.pmとShop::Delivery.pmの三行を見た。
「もう要らないってことですね」
「はい」
クロベさんが短く答えた。ナギさんは、少し名残惜しそうな様子も見せず、三行――ファイルを開いて、書いて、閉じる――をそれぞれ削って、lib/Shop/Sales.pmを元の形に戻した。
| |
lib/Shop/Delivery.pmも、同じ形だった。
| |
lib/Shop/Supplier.pmも同様だった。
| |
三つとも、Kido::pass_through(...)という形で、パッケージの名前を付けて呼んでいる。クロベさんが、そこを指して念を押した。
「呼ぶときは、いつもこの形です。名前を短くして持ち込むような呼び方は、していません」
「それが、何か関係あるんですか」
私が訊くと、クロベさんはうなずいた。もし短くして持ち込む書き方をしていたら、次のような形になっていたはずだという。
| |
「短く持ち込むと、持ち込んだ側は、その時点の中身を手元に写し取ります。あとでKido.pmの方を書き換えても、手元に写した方は古いままです」
「じゃあ、記帳が効かないってことですか」
ナギさんが訊いた。
「効きません。しかも、警告も出ません。だから、呼ぶたびに名前を見に行く、今回の呼び方にしておく必要があります」
説明の半分は、私にはまだ難しかった。ただ、三つの呼び出しがどれも同じ形で書かれていることだけは、はっきり分かった。
「……これ、要らなくなるんですね」
ナギさんが、削り終えた画面を見ながらつぶやいた。安堵とも違う、素直な納得のような声だった。
第4幕: 検め ── 何も変わっていないことを、目で確かめる
クロベさんが、用意していた三本の検めを順に動かした。
まず、新しく作ったKido::Ledgerが、正しく記帳を積み上げるかどうか。
| |
次に、Kido::pass_throughが、これまでと変わらず情報を組み立てているかどうか。
| |
「これは、build_recordingを呼ばない状態でも動きます」
クロベさんが言った。
「記帳先を組み立てていない限り、pass_throughは今までと同じ振る舞いのままです」
実際に動かすと、記帳を有効にする前と後で、この検めの結果は一つも変わらなかった。
最後に、記帳を有効にしたうえで、三つの呼び出し元それぞれが記帳されるかどうかを確かめた。
| |
三本とも、通った。
| |
「記帳の仕組み自体は、一本目で確かめてあります」
クロベさんが言った。
「pass_throughが組み立てる情報の形も、二本目で変わっていません。三本目が確かめているのは、呼び出し元を一切書き換えずに、記帳が一律に効くこと――それだけです。だから、三つの呼び出し元それぞれ一回ずつの確認で足ります。四つ目、五つ目が増えても、記帳の仕組み自体を確かめ直す必要はありません」
そして、ナギさんが、書き換える前の三つのファイルを取っておいたコピーと、今の三つのファイルを見比べた。
| |
何も表示されなかった。差分がない、ということだった。
三回、同じことを確かめた。三回とも、画面には何も映らなかった。今朝、ナギさんがしゃがみ込んで書き足していた三行を思い出す。あの三行が、この三つのファイルのどこにも残っていない。かといって、記帳そのものは、先の検めで確かに動いていた。
「……本当に、何も変わっていない」
画面を見たまま、思わず声に出た。変わったのはKido.pmだけで、あとは何も触っていない。三箇所に散らばっていた呼び出し先が、今日は一つも書き換えられていない。数えることをあきらめたはずなのに、結果としては、数えなくてよかった、ということになっていた。
「今日確かめたのは、ここまでです」
クロベさんが、区切りを付けるように言った。
「呼び出し元を触らずに、記帳を一律に効かせられること――それは保証します。ただ、退避した方の名前は、外から見ると分かりにくいままです。それは直っていません。記帳先を引数で持ち回らずに済ませた代わりに、build_recordingを呼び忘れると、記帳は黙って効かないままになります。呼び出し元の数は増やせても、配線を呼ぶ順番だけは、どこかで一度気にしないといけません。それに、これから別の前後処理をもう一枚重ねたくなったとき、包みを何重にも重ねると、どこで何が起きているか追いにくくなります。今日はまだ一枚しか包んでいないので、その問題は起きていませんが」
「触ったのは、そこまでですか」
確かめると、クロベさんは短く「はい」とだけ答えた。
「Kido.pmの中身と、新しく起こしたKido::Ledger。それだけです。記帳した中身を、あとでどう使うかには触れていません」
私は、野帳を開いた。今日は、いつものように書き取る前に、しばらく手が止まった。書きかけては消していた三箇所の記帳の跡と、今、何も変わっていない三つのファイルとを、頭の中で見比べていた。
「触らずに済むなら、次からは何を見ればいいんですか」
クロベさんが答える。
「呼び方が、いつも同じ名前を見に行く形になっているかどうかです。今日みたいにパッケージの名前を付けて呼んでいれば、通る場所は一つのままです。短く持ち込んで呼んでいる所があれば、そこだけは今回の手が効きません」
その一言を、そのまま書き取った。
「既に使われている所に触らずに済む道を選べる」
書きながら、まだ自分でも分かりきっていない部分があることに気づいた。今日、クロベさんが「戸は一つです」と言い切れたのは、Kido::pass_throughという名前が、店じゅうどこから呼ばれても同じ実体を指しているからだった。だが、それがいつでも成り立つのかどうか――通る場所が一つと言えないときはどう見分けるのか――までは、まだ自分の言葉にできていない。それは、次に持ち越すことにした。
クロベさんが、道具をしまいながら言った。
「今日は、一枚包んだだけです。何枚も重ねれば、それも見通しを悪くします」
その言い方には、今日の仕事を誇るような響きはなかった。ただ、次に同じ手を使うときの注意を、先に置いておくような口ぶりだった。
野帳を閉じて顔を上げると、ナギさんはもう端末を片付けていた。朝しゃがみ込んでいた敷居のあたりに、もう書きかけのコードは残っていない。表の格子戸には、まだ光の縞が落ちていた。通りを人が行き交う音は変わらず、暖簾も同じように揺れていた。何も変わっていないように見えるその向こうで、今日、確かに何かが変わっていた。
普請控
- 見立て: 旦那様から、出入りは全部帳面に付けるようにという決まりが出た。表の格子戸を通る出入りを扱う
Kido::pass_throughを呼んでいる箇所が、Shop::Sales(客の会計)・Shop::Delivery(配達の受け取り)・Shop::Supplier(仕入れの荷受け)と複数のモジュールに散らばっていた - 手を入れた所: 包みメソッド(Wrap Method)を使い、
Kido::pass_throughをKido::_pass_through_rawへ退避し、新しいpass_throughが記帳をしてから退避先を呼ぶ形にした。記帳先の帳面を扱うKido::Ledgerを新設し、Kido::build_recordingで配線した - 触っていない所:
Shop::Sales.pm・Shop::Delivery.pm・Shop::Supplier.pmの3ファイルは一行も変更していない(diffで確認済み)。pass_throughが出入りの情報を組み立てる中身も変えていない - 次の工程へ送ること: 通る場所が本当に一つと言えるのはどんなときか――その見分け方は、まだ自分の言葉にできていない。次の課題として残す
- 私が引き受けたこと: 既に使われている所に触らずに済む道を選べる
