第1幕: 検分 ── 表の戸口
今朝の素屋根は、光が弱い。
薄曇りで、隙間から差す筋は細く、鉋屑が舞っても、光の中を降りてこない。表の戸口の土間には、夏のあいだ入れていた葦戸が外されて、壁に立てかけてあった。通りを人が行き来するので、戸口の半分には養生の板が渡してあり、店の人はその脇を通っていく。クロベさんとナギさんは、板の内側で、新しい板戸を敷居の溝へ入れようとしていた。板戸は、昨日の夕方に建具屋から届いたものだった。冬のあいだ、葦戸の代わりに立てる戸になる。
私は、通りがかりに足を止めた。
ナギさんが、板戸を下から支えて、溝へ滑らせた。戸は三分の二ほど進んで、止まった。さらに押しても動かない。木と木が当たる鈍い音がして、ナギさんは手を止め、戸を少し引き戻した。鉋には、手を伸ばさなかった。
クロベさんは、戸には触れなかった。溝の脇にしゃがんで、差し金の先を、敷居の溝へ当てた。
「九分」
それだけ言って、立ち上がらずに、ナギさんのほうを見た。ナギさんは、戸の下の桟に、差し金を当てた。
「九分五厘です」
五厘、戸のほうが厚い。ナギさんは鉋を取って、桟の下面を削りはじめた。削っては戸を溝に当て、また削る。何度か繰り返したあと、戸は、最後まで滑って溝に収まった。手を添えるだけで、開け閉めができる。
そのあいだ、私は、クロベさんの手元を見ていた。溝を測った差し金が、そのまま前掛けの隠しへ戻っていく。この溝の寸法を書いたものを、私は三十年のあいだ、一度も見たことがなかった。
クロベさんは、差し金を前掛けの隠しにしまった。戸口に、鉋屑の匂いだけが残っていた。
「帳場のほうも、今朝、替えたところです」
私が切り出すと、二人がこちらを向いた。
帳場の締めは、その日の売上を数えたあと、結果を一行にして、奥の間の知らせ板へ貼り出す。店主は朝と夕にそれを見る。月末の締めでは、貼り出したあとで、板を一か月分ひとまとめに閉じる。その貼り出す先を、店主は、月末を前に、板でなく書状に替えたいと言った。ナギさんが、今朝のうちに、書状の部品を書いてくれた。
「毎日の締めの検めは、通してあります」
ナギさんが言った。
「五本、緑です」
「月末の締めも、同じ替えで通りますか」
私が訊くと、ナギさんは、返事の前に、手拭いで手を拭いた。
「月末のほうは、まだ検めていません」
月末の締めは、二日後だった。毎日の締めは通っていて、月末の道は、一度も通っていない。
クロベさんは、土間の隅の桶で手を洗い、手拭いで拭いた。
「帳場へ」
三人で、戸口を離れた。戸は、背後で、開け閉めできる形のまま、溝に収まっていた。
第2幕: 手が入らない ── 月末の道
帳場の文机には、端末が開いてあった。
ナギさんが、書状の部品を画面に出した。書いたばかりの、短い部品だった。
| |
blessは、ハッシュを、そのクラスのオブジェクトにする組み込みだった。open_lineは書状の口を開けること、send_noticeは知らせを一件積むこと。ナギさんは、そう説明した。毎日の締めの検めは、この二つで通っている。
ナギさんは、誰にも言われないまま、月末の締めを、この書状で走らせた。抜けた版の書状を置いたフォルダを、先に指して読み込ませる。
| |
エラーは一行だった。
ナギさんは、打ったコマンドの一行を、端から端まで読み直した。手は、そこで止まった。私は、出力の下の二行を読んだ。知らせは、出ている。止まったのは、そのあとだった。月末の締めを済ませたという記録は、残っていない。
「知らせは出たのに、締めが済んだことになっていません」
私が言うと、ナギさんは小さくうなずいた。
クロベさんは、書状のファイルを開かなかった。代わりに、締めを担う部品のほうを、画面に出させた。
| |
「毎日の締めと、月末の締めです。どちらも、渡された一つの部品に、決まった名前を呼んで頼んでいます」
クロベさんは、この作りが今まで何を支えてきたかを、先に言った。
「頼む相手が、板でも書状でも、頼み方は一つです。この一つの頼み方が、板の時代から、毎日の締めを守ってきました。ここには、手を入れません」
それから、画面の端末に、コマンドを打たせた。
| |
部品に頼んでいる所を、上から拾った。クロベさんは、紙を一枚取って、鉛筆で表を書いた。
| 名前 | 呼ぶ所 |
|---|---|
| open_line | 毎日の締め・月末の締め |
| send_notice | 毎日の締め・月末の締め |
| close_line | 月末の締めだけ |
「三つです。月末の締めだけが、三つ目を呼んでいます」
書状には、二つしか無かった。close_lineの行は、月末の道でしか実行されない。毎日の締めは、その行まで届かないので、持っていない名前でも、落ちない。三つ目の名前が要るのは、月に一度、月末の道だけだった。
クロベさんは、もう一つ、端末に打たせた。今度は、本物の知らせ板のほうだった。
| |
newを除いて、名前は五つある。表の三つのほかに、historyとclearがあった。
「この二つを呼んでいる所は、ありますか」
クロベさんは、ナギさんに、探させた。historyとclearを、使う側のファイルも含めて、libとbinの全部から探す。
| |
出てきたのは、板のファイルの、定義の二行だけだった。呼んでいる所は、どこにも無かった。
ナギさんは、書状のファイルに戻って、一行足した。中身は何もしない、名前だけを満たす一行だった。
| |
月末の検めを、走らせ直した。
| |
緑になった。月末の締めも、書状で通るようになった。クロベさんは、書状のファイルを閉じた。
私は、野帳を膝に置いていた。月末の朝に、締めを押すのは、私だ。押したあと、替えがこの建物に合っているのかどうかを、私は、今のところ、自分では言えない。ナギさんが一行足して、緑になった。その緑が、次の替えでも続くのかどうか、確かめる手立てが、私の手元には無い。
戸の溝の九分は、書いたものが無かった。この替えに求められる名前の数と顔ぶれは、どこかに書いてあるのだろうか。
私は、野帳を閉じて、クロベさんの顔を見た。
「替えの寸法は、どこに書いてあるんですか」
クロベさんは、机の上の表を、上から順に目で追った。
「どこにも、ありません。この表にしか」
第3幕: 手立て ── 寸法を先に書く
クロベさんは、表の紙を、机の真ん中へ寄せた。
「この表は、紙の上にしかありません。機械には、読めない。使う側が呼んでいる名前だけを取り出して、替えの部品が満たすべき形として、一か所に書いておく。その技法を、インタフェースの抽出、Extract Interface と呼びます」
形、というのは、この三つの名前のことです、とクロベさんは言い足した。以降、形も、名前の一覧も、同じものを指す。
Michael Feathers の『Working Effectively with Legacy Code』に載っている技法だった。Java のように、interfaceを書ける言語が前提になっている。本の例では、描画の部品が使う側に必要なのは、点を打つ一つだけだった。だから、インタフェースにも、その一つだけを書く。使う側が必要としない名前は、入れない。私は、この二文を野帳に書いた。手順そのものは、本の言い回しではなく、今日の Perl での形で見せる、とクロベさんは言った。
「他の言語には、満たすべき形を書く場所があります。Perl には、その場所がありません」
Perl は、型を宣言しない。部品が、呼ばれた名前のメソッドを持っていれば、動く。持っていなければ、呼ばれたその場で止まる。この動き方は、前に印字の部品を替えたときに見たものと同じだった。今日はそれを、説明し直さない、とクロベさんは言った。
「場所が無いなら、場所を作ります。ただの名前の一覧を、一つのファイルに書きます」
ナギさんが、新しいファイルに、その一覧を書いた。
| |
「ここでいう寸法は、この名前の一覧のことです」
クロベさんは、パッケージの名前を指した。Sunpo。戸口の九分とは別のもので、同じ言葉で呼んでいる。以降、コードの話では、この言葉は、名前の一覧のほうを指す。戸口の話をするときは、戸口の、と付ける。
qw(...)は、空白で区切った文字列の並びを作る書き方だった。ourは、パッケージ変数に、この場所からも名前で届くようにする宣言で、前に使ったものと同じ。新しいのは、次の二つだった。
「canは、オブジェクトやクラスの名前に、->can('名前')と続けて呼ぶと、その名前のメソッドを持っていれば、そのメソッドへの参照を返し、持っていなければ、何も返さない組み込みです。親から受け継いだ名前も、持っているものに数えます」
返ってくる「メソッドへの参照」は、その名前の処理を、あとから呼べる形にしたものだった。ここでは、あるかないかの判定にだけ使う。
もう一つのgrepは、条件に合う要素だけを、並びから取り出す組み込みだった。ここのgrep { ... }は、さっき端末で打ったgrepコマンドとは、名前が同じだけの、別のものだ。一覧の名前を一つずつ取り、canで持っていない名前だけを残して返す。canは持っていなければ何も返さず、それは偽として扱われる。!で逆にするので、持っていない名前だけが残る。返ってくるのは、欠けている名前の並びになる。
「三つの部品に、同じ検めを通します」
ナギさんが、検めのファイルを書いた。本物の知らせ板、書状、それに、前に使った検め用の代役。検めのあいだだけ本物の代わりを務める、あの部品だった。
| |
検めのファイルには、このほかに、一覧そのものと、欠けた名前を言えることを確かめる検めも書いてある。ここに出したのは、本物・替え・代役を通す部分だけだ。
refは、オブジェクトを渡すと、それが属するクラスの名前を返す組み込みだった。ここでは、検めの名前に、部品の名前を入れるためだけに使っている。
ナギさんは、まず、抜けた版の書状を先に指して、検めを走らせた。朝のうちに書いた、close_lineの無い版だ。
| |
月末の締めを走らせなくても、書状にclose_lineが無いことが、名前つきで出た。ナギさんは、直した版の書状へ戻して、もう一度走らせた。
| |
「一覧に、板の持っている名前を、全部入れないのは、なぜですか」
私が訊くと、クロベさんは、板の側の二つの名前を指した。
「板の五つを全部入れれば、書状も代役も、historyとclearが無くて、検めで落ちます。一覧が、使う側の必要でなく、板の持ち物になる。一覧は、使う側が呼んでいる名前だけです」
私は、検めの一行目を見た。一覧は三つだけだと、検めの側でも確かめてある。
次に、手を入れた範囲を確かめた。使う側のファイルは、一字も変えていない。一覧を読んでいるのは、検めだけだった。
| |
libとbinの中で、Sunpoという名前が出てくるのは、そのファイル自身だけだった。使う側も、本番の組み立ても、この一覧を知らない。この技法のために足したのは、一覧のファイルと、検めのファイルだけだ。
本番の組み立ては、これまでと同じ書き方だった。替えの部品に取り替えるとき、変わるのは、一か所だけだった。
| |
| |
組み立てる場所は、消えていない。一覧が加わっても、そこに誰かが部品を渡す仕事は、これまでと同じ場所にある。
野帳を開いて、今日手を入れた所と入れなかった所を、一枚に写してみた。一覧のファイルと検めのファイルは、墨の実線で描いた。使う側と本物の知らせ板と本番の組み立ては、一字も変えていないので、薄い墨の破線にした。一覧から検めへ、検めから三つの部品へ引いた線は太くして、使う側へは、一本も引かなかった。

ひと通り見せ終えると、クロベさんは席を立った。何も告げずに、戸口のほうへ出ていった。しばらくして戻ってきて、席に着いた。
「宮大工の言い方では、寸法を定める、です」
「使う側は、毎日の締めを支えています。だから手を入れずに、替えのほうを合わせます。戸口の戸は削って合わせられて、溝は建物です。入る寸法は、受ける側で、先に決めておきます」
墨差しを、机の端に置いた。
私は、野帳に、定める、と書いた。戸口の九分と、今日の三つの名前は、同じことをしている。受ける側が、入るものの寸法を、先に言葉にしておくこと。
第4幕: 検め ── 一覧が古くなるとき
「使う側に、呼ぶ名前を、一つ足してみてください」
クロベさんが言った。
ナギさんは、使う側のファイルを別の場所へ写して、その写しの毎日の締めに、一行足した。本体には、触れていない。
| |
retryという名前を、部品に頼む。一覧は、そのままだ。検めを走らせて、続けて、実際に毎日の締めを呼んだ。
| |
検めは、緑のままだった。実際に呼ぶと、板でも書状でも止まる。本物の知らせ板もretryを持っていないので、これは、替えの落ち度ではない。
「使う側が変わったときは、一覧は、誰が直すんですか」
私が訊くと、クロベさんは、短く答えた。
「人です。この検めは、一覧に書いてある名前を見ているだけで、使う側を見てはいません。一覧は、使う側の写しです。写しは、元が変われば、古くなります」
私は、野帳を開いた。一覧を直すのが人なら、その人は、使う側が変わったと、いつ知るのだろう。
「使う側に、呼ぶ名前を足す話は、私のところにも来ます。そのときは、一覧のことを、私から先に訊きます」
クロベさんは、うなずいた。私は、その一行を、野帳に書いた。
戸口の溝を彫り直したのに、墨で書いた九分が古いまま。そういう古さが、ここにも起こりうる。
クロベさんは、この手立てで言えることを、先に三つ言った。
「使う側と本物は、一字も変えていません。使う側が呼ぶ三つの名前が、本物にも、替えにも、代役にも揃っています。月末を待たずに、欠けた名前を、名前で言えます」
それから、言えないことを、一つずつ見せた。ナギさんが、canの見えないものを、実際に動かして並べた。
| |
Wrongは、渡された知らせを捨てて、意味のない文字列を返すsend_noticeと、呼ばれたら必ずdieするclose_lineを持つ部品で、名前の有無だけを見る検めは「欠けなし」と答えた。Childは、三つの名前を全部、親から受け継いでいる。名前の有無だけを見る検めは、これも「欠けなし」とする。AutoLineは、持っていない名前の呼び出しを、まとめて自分で受ける仕組みを持つ部品で、実際には、呼べる。それなのに、検めは、三つとも欠けと答えた。canは、その仕組みで受ける名前が見えない。四行目は、bless されていない参照を渡したときで、canの呼び出し自体が止まる。最後の行は、AutoLineのclose_lineを、実際に呼んだ結果だった。
「見えるのは、名前の有無だけです」
クロベさんは、ナギさんの出力の脇に、七つの行を書いた。
| 言えないこと | わけ |
|---|---|
| 引数や中身が合っているか | canは名前の有無だけを見る。Wrongを動かした結果 |
| 受け継いだ名前の中身が合っているか | 持っている名前に数える。Childを動かした結果 |
| 持っていない名前をまとめて受ける部品 | 見えず、欠けと出る。AutoLineを動かした結果 |
| 一覧と使う側のずれ | 検めは使う側を見ない。retryを動かした結果 |
| bless されていない参照 | 検めに渡せない。止まる |
| 書状が店主の手に届くか | 見ていない。今日見たのは、一度動かした範囲 |
| 知らせの中身が正しいか | 見ていない |
「最後の二つは、今日の検めの外です」
クロベさんは、鉛筆を置いた。
「今日の検めは、一度動かした話です。毎月、届き続ける保証では、ありません。もう一つ、入れていないことがあります。組み立ての時点で、欠けた名前を止める仕掛けです。入れると、これまで動いていた毎日の締めまで、止まる日が出ます。振る舞いが、変わってしまいます」
日が、午後に傾いていた。ナギさんが、自分の机から、紙を一枚持ってきた。
「シオリさん、これを通してください」
紙には、部品の名前だけが書いてあった。Omote::Fusen。ナギさんが、さっき、自分で書いた替えだった。何が抜けているかは、書いていなかった。私にも、聞かされていなかった。
私は、検めのファイルを開いた。三つの部品を並べた行の最後に、その名前を足した。useの行も一つ足して、走らせた。
| |
赤い行は、五つ目だった。欠けた名前の行を、私は、声に出して読んだ。
「open_lineが、ありません」
ナギさんは、うなずいた。
「合っています。open_lineを抜きました」
今朝、直したのはclose_lineだった。今日、私が読んだのは、別の名前だった。クロベさんは、何も言わなかった。ナギさんは、Omote::Fusenのファイルを開いて、open_lineを一行、足しはじめた。
夕方、私は、表の戸を閉めに出た。
朝に入れた板戸を、溝に沿って滑らせる。戸は、最後まで滑って、溝に収まった。軽く手を添えると、音も立てずに閉まる。戸の下をのぞくと、敷居の内側に、墨で小さく、九分、と書いてあるのが見えた。
通りの人の足音が、戸の向こうで、遠ざかっていった。
普請控
- 見立て: 知らせ先を板から書状に替えたところ、毎日の締めは通ったが、月末の締めだけが、書状に無い名前を呼んで止まった。使う側がどの名前を呼んでいるのかは、どこにも書かれておらず、替えを書く人は、使う側を読み取るほかなかった
- 手を入れた所: インタフェースの抽出(Extract Interface)を使った。使う側が呼ぶ三つの名前を
Omote::Sunpoに一覧として書き、本物の知らせ板・書状・検め用の代役に、同じ検めを通して、欠けた名前を名前で言えるようにした。書状には、欠けていたclose_lineを一行足した - 触っていない所: 使う側の
Omote::Shirase(毎日の締めと月末の締めの呼び方)、本物の知らせ板Omote::Ita(historyとclearは使う側が呼ばないので、一覧に入れていない)、本番の組み立ての書き方(line =>の右側だけが替えの違い)は、一字も変えていない。canが区別できない所(引数と中身・受け継いだ名前の中身・まとめて受ける仕組みの名前)、一覧と使う側の呼び出しを突き合わせる仕掛け、書状が店主に実際に届くかどうかは、見ていない - 次の工程へ送ること: 組み立ての時点で、欠けた名前を止める仕掛けと、一覧と使う側の呼び出しを突き合わせる検めは、今日は置かない。前者は、これまで動いていた毎日の締めまで止めてしまい、振る舞いが変わるため。後者は、使う側の呼び出しが決まった書き方のうちは拾えても、名前を組み立てて呼ぶ所は見落とすため、呼び出しがどこに集まっているかを見てからにする
- 私が引き受けたこと: 替えが寸法に合うかどうかを、私が自分の検めで確かめられる。ナギさんが用意した、何が抜けているかを聞かされていない替えに検めを通し、欠けた名前を読んで返した。使う側に呼ぶ名前を足す話を聞いたら、一覧のことを私から先に訊く、と決めて、野帳に控えた
