Featured image of post コードカーペンター【Effect Sketch】「測る前に、描くんですか」〜全部を測る前に、響く先を図で絞る〜

コードカーペンター【Effect Sketch】「測る前に、描くんですか」〜全部を測る前に、響く先を図で絞る〜

通り庭を抜ける注文の経路に手を入れたいが、変更の効果がどこまで届くのか分からない回。全部を測る前に、影響スケッチ(Effect Sketch)で響く先を図に描き、仕様化テストを置く場所を絞ります。

第1幕: 検分 ── 通り庭を抜ける、今日の頼まれごと

朝、素屋根の下に立つと、光の筋が帳場のほうから通り庭まで長く伸びているのが分かった。土間は昨夜の掃き掃除のあとで、まだ土の匂いが少し残っている。通り庭は、店先から奥の蔵まで一続きの、細長い土間だった。荷を担いだ人が通れるだけの幅しかない。三十年、私はここを何度も通ってきたが、床板の下がどうなっているかを気にしたことは、一度もなかった。

今日はいつもの帳場ではなく、この通り庭に手が入る番だった。ナギさんは床板の脇にしゃがみ、道具を並べている。金槌の頭と柄が擦れる、小さな音がした。クロベさんは通り庭の柱を見上げていた。帳場の柱よりも、こちらのほうが少し細い。表と奥を繋ぐだけの通路だから、そういう造りなのだろうと、私は勝手に思っていた。

私は野帳を手に、二人のところへ歩いていった。

「クロベさん。店主から頼まれごとがあります」

柱を見上げていた顔が、こちらへ向いた。

「なんでしょう」

「通り庭を抜ける注文の受け方に、確認したい項目を一つ足してほしい、と言われています。蔵の在庫が少ない品なら、注文を受けた時点で先に知らせてほしい、ということでした」

昨日、店主から直接聞いた話だった。近ごろ、蔵の在庫を切らしたまま注文を受けてしまい、後から断りの連絡を入れることが何度かあったらしい。だから、注文を受けたその場で分かるようにしたい、という頼みだった。

まだ細かいところは決まっていない。店主も、どう組み込むかまでは考えていないようだった。だから、まずはこちらで形を作ってから相談する、という段取りになっていた。

「前に仕様化テストを書いたのは、帳場のRegisterだけです。こちらの、注文が店から奥へ流れる経路には、まだ何もありません」

そう言ってから、少し考えた。ズレを見過ごしてきた三十年の重さとは違う、素直な期待だった。今度は最初から、自分の手で確かめられる範囲を持って始められる。そのつもりで、今日を迎えていた。

クロベさんは、しばらく黙っていた。通り庭を見渡し、それから床板のほうへ目を移した。

「近くだけ直せば済むものでしょうか」

私が訊いた。頼まれごとの中身を思うと、注文を受ける入口に近い場所を少し直すだけで済みそうに見えた。

「まだ分かりません」

クロベさんは、静かにそう言った。

「動かしてみないと、どこまで響くかは言えません」

原因の見当がついているわけでもなく、範囲の見当がついているわけでもない。ただ、そう言い切らないだけの慎重さが、いつものクロベさんだった。

近くだけ直せば済む、と私は思っていた。頼まれごとの内容自体は、さほど大きなものには聞こえなかった。だから、今日は半日もかからずに済むだろう、と勝手に見積もっていた。それが、そう単純ではないと知るのは、このすぐ後だった。

第2幕: 手が入らない ── 全部は、いちいち確かめられません

ナギさんが、確かめるために通り庭の床板を一枚、持ち上げた。

その瞬間、こつん、という物音が鳴った。通り庭から見て奥、離れた座敷のほうからだった。ナギさんの手が、床板を持ったまま止まった。板を上げる途中の、中途半端な高さのままだった。

私も、その音に驚いた。座敷には誰もいないはずだった。物が倒れたのかと思い、様子を見に行こうかと一瞬迷ったが、ナギさんが動かないので、その場に留まった。

「……今の、ここじゃないですよね」

クロベさんは何も言わず、床下を覗いた。灯りを持ってこさせ、床板を外した隙間から腕を差し込み、埃をかぶった梁を指の先でなぞっている。しばらくそうしてから、姿勢を変えずに言った。

「この床の梁は、そこの座敷の柱まで、一本、通っています」

私も横から覗いたが、暗くてよく見えなかった。継ぎ目らしきものが、奥のほうに一つあるだけで、そこから先がどこまで続いているのかは、私の目では分からなかった。ただ、クロベさんの言葉だけで、床下でどう繋がっているかが伝わった。

「一本、というのは、途中で切れていない、ということですか」

私が訊いた。

「切れていません。この床を踏んだ力の一部が、そのまま座敷の柱まで運ばれます。だから、さっきの音が鳴りました」

「今、どう繋がっているかは分かりますが、なぜそう組んだかは、今は言いません」

その言い方に、私は少し引っかかった。誰が、いつ、という話に興味がないわけではない。ただ、クロベさんはいつも、そこには踏み込まなかった。今、何を支えているか。それだけを言う人だった。

ナギさんが、床板を戻しながら言った。

「近くだけ直せば済むと思ってました」

自分に言い聞かせるような声だった。手を止められたわけではない。ただ、床板一枚のつもりで手を入れて、離れた座敷まで音が届いたことに、驚いていた。

「わしも、いつもそうとは限らんと思っています」

クロベさんが言った。

「床がそうだとして、あの注文の仕組みも同じかどうかは、まだ分かりません」

私は、その言葉を聞いて、頼まれごとのことを思い出した。

「近くだけ直せば済むと思っていましたが、そうでもないんですか」

「まだ分かりません」

クロベさんは、床から手を離し、立ち上がった。

「どこまで確かめれば、次の工程に渡せるんでしょうか」

私が訊いた。引き受ける側として、どこまで自分の手が及ぶのかを知っておきたかった。

「それを、今は言えません」

クロベさんは、通り庭の柱を一本、軽く手で叩いた。乾いた、低い音がした。

「ただ、柱を一本ずつ、いちいち押して確かめるわけにはいきません。この通り庭だけで、柱は八本あります。座敷まで含めれば、もっとあります」

私は、床の下の梁が奥の座敷までひと続きだったことを思い出していた。柱も、同じように、どこかで思いがけない先まで繋がっているのかもしれない。だとしたら、一本ずつ確かめていくのは、この工事が終わるまでかかりそうだった。

全部は確かめられない、とクロベさんは言った。けれど、確かめずに進めるとも言わなかった。

第3幕: 手立て ── 荷重の見立て図

帳場に移り、三人で画面の前に座った。通り庭から帳場までは、ほんの十数歩の距離だが、床下を覗いた直後だと、その短い距離が今日はいつもより長く感じられた。表示されているのは、通り庭の注文の流れを担う、三つの短いコードだった。

「なぜ、一つにまとめずに、三つに分けてあるんですか」

私が訊いた。帳場のRegisterは一つのファイルにまとまっていたのに、今日のコードは三つに分かれている。

「店の造りと同じです」

クロベさんが答えた。

「店先で注文を受ける所、蔵で在庫を確保する所、配達に出す所。この店の中でも、場所も、担う人も違います。コードのほうも、それに合わせて分けてあります」

分かれていることに、意味がある。三十年、この店を見てきて、そんなふうにコードを見たことは、一度もなかった。

「今回は、blessもnewも無いんですか」

ナギさんが、画面を見て言った。前回のRegisterとは違う書き方に気づいたようだった。

「入れ物を分けるだけで十分です」

クロベさんが答えた。

「今日は、そこに何を作るかより、届く先を見るのが仕事です」

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package Toriniwa;

use strict;
use warnings;

our $pending_item;    # 通り庭を今通っている注文の品書き(パッケージ変数)

sub accept_order {
    my ($item) = @_;
    $pending_item = $item;
    Kura::stage();
    return;
}

1;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package Kura;

use strict;
use warnings;

our $staged_item;    # 蔵で確保された注文

sub stage {
    $staged_item = "在庫より確保: $Toriniwa::pending_item";
    Delivery::prepare_slip();
    return;
}

1;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package Delivery;

use strict;
use warnings;

our $slip;    # 配達に持たせる控え

sub prepare_slip {
    $slip = "配達控え: $Kura::staged_item";
    return;
}

1;

「accept_orderが注文を受けて、Toriniwaという入れ物に書く。Kuraがそれを読んで、蔵で確保したという記録を残す。Deliveryがそれを読んで、配達の控えを作る」

クロベさんが、三つのファイルを順に指した。Kuraの中に出てくる$Toriniwa::pending_itemという書き方は、Toriniwaという別の場所に置かれた、同じ入れ物を指す名前だという。パッケージの名前を先に付ければ、よそから覗きに行ける、ということだった。

「店主が頼んでいるのは、accept_orderのところに確認項目を足すことです。ですが、ここに手を入れたら、どこまで響くのか、まだ誰にも言えません」

クロベさんは、懐から紙とペンを取り出した。真新しい紙ではなく、何度か使った跡のある、少し柔らかくなった紙だった。

「……測る前に、描くんですか」

ナギさんが、意外そうに言った。てっきり、すぐにテストを書き始めるものだと思っていたようだった。手元には、すでにキーボードに触れる姿勢のまま止まっている。

「そうです」

クロベさんは、紙を机の上に広げた。ペンの先を紙に当てたまま、しばらく動かさなかった。

「これは、“影響スケッチ(Effect Sketch)“と呼ばれるやり方です。変更したい所から、値がどこまで届くかを、矢印で描きます」

クロベさんは、紙の上に丸を一つ描いた。accept_orderと書き入れる。

「描いてから確かめるのと、確かめながら描くのとでは、違うんですか」

ナギさんが訊いた。

「違います。頭の中だけで考えると、近い所で止まってしまいます。紙に矢印を引いていくと、次はどこへ届くか、そのたびに手が止まって、考えることになります」

しばらく間を置いてから、続けた。

「宮大工の言葉で言うなら、荷重の見立て図に近いです」

「見立て図……」

「はい。この柱を切ったら、どこの梁が煽りを食うか。それを、先に見立てておくのと同じことです」

「近いから響く、遠いから響かない、というものではありません」

クロベさんが、紙にペン先を置いたまま言った。

「この$Toriniwa::pending_itemという入れ物は、ourと書いてあろうがなかろうが、店のどこからでも覗ける場所に、元から置かれています。ourは、ここから呼ぶときの合鍵のようなものに過ぎません」

「合鍵……」

「はい。その場だけ違う声を通すlocalという道具もありますが、それはまた別の仕組みで、今日は使いません。今日図に描くのは、いつも通っている、本来の道筋です」

私は、ourという一言が、伝わりやすさそのものを作っているわけではないと知って、少し驚いた。伝わる先は、ourがあるからではなく、もともとそこに置かれている入れ物の性質そのものだった。

「では、ourと書かなくても、同じことが起きるんですか」

私が訊いた。

「起きます。ourが無くても、パッケージの名前を付けて呼べば、同じ入れ物に届きます。ourは、それを短く書けるようにするだけの、呼び名の道具です」

ナギさんが、画面のコードを指でなぞりながら言った。

「じゃあ、ourを消したら、安全になるわけじゃないんですね」

「なりません。入れ物そのものの置き場所は、変わりませんから」

クロベさんが、紙に矢印を引き始めた。accept_orderからToriniwa::$pending_itemへ。そこからKura::stageへ。Kura::$staged_itemへ。そこまで引いたところで、ペンが止まった。

「ここ、Deliveryまで、繋がっています」

クロベさんが指を止めた紙には、丸と矢印だけが並んでいた。accept_orderから伸びた線は、蔵の柱の先で止まってはいなかった。もう一本、配達の入れ物まで、まっすぐに伸びている。

影響スケッチ図: accept_orderがToriniwaの入れ物に書き込み、Kura::stageが読んでKuraの入れ物に書き、Delivery::prepare_slipが読んでDelivery::$slipまで届く三段の連鎖。破線はDeliveryに他から届く、今日は検分しない経路。

「隣の、蔵までだと思っていました」

私が言った。今日の頼まれごとを聞いたときから、直すのはaccept_orderの近く、せいぜいKuraまでだと思い込んでいた。あの物音を聞いたあとでも、コードのことになると、また近さで測ってしまっていた。

「わしも、最初はそう思いました。描いてみて、初めて分かりました」

「……さっきの、床の音と同じですか」

私が訊いた。離れた座敷まで届いた、あの物音のことを思い出していた。

「同じです」

クロベさんが言った。

「近いか遠いかは、繋がりとは関係ありません」

矢印は、Delivery::$slipまで一本に繋がっていた。近くのつもりで手を入れても、配達の控えまで届いてしまう。

「Deliveryには、他からも声がかかっている経路があるようですが、それは今日、私たちが動かす経路ではありません」

クロベさんが、紙の隅を軽く手で示した。他にも矢印が集まっていそうな気配はあったが、そこまでは描かなかった。

「今日はここまでにします」

「全部の入れ物に、あらかじめテストを置いておけば、こんなふうに描かなくても済むんじゃないですか」

ナギさんが訊いた。手を動かすほうが早い、という気持ちが、まだ少し残っているようだった。

「置けます。ですが、この店の中を通っている入れ物は、ToriniwaとKuraとDeliveryだけではありません。全部に置いたら、今日中には終わりません」

クロベさんが、紙の上の三つの矢印を指でなぞった。

「今日、直したいのはaccept_orderの一箇所です。だから、その一箇所から届く先だけを描けば、それで足ります。届いていない所にまで、先回りしてテストを置く必要はありません」

私は、その言葉で、今描いている図の意味がようやく分かった気がした。全部を測るのではなく、今日動かす分だけを描いて、そこにだけ手を掛ける。狭い範囲のようで、今の頼まれごとには、それでちゃんと足りていた。

第4幕: 検め(けんめ)と引き受け ── 図を、自分で読む

クロベさんが、ナギさんにテストの雛形を用意させた。t/order_reaches_delivery.tという名前だった。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
use strict;
use warnings;
use Test::More;
use lib 'lib';
use Toriniwa;
use Kura;
use Delivery;

Toriniwa::accept_order('うなぎ弁当');

is(
    $Delivery::slip,
    'PLACEHOLDER',
    'まだ仮の期待値'
);

done_testing;

accept_orderに、具体的な品を渡す。今日は「うなぎ弁当」だった。動かすと、落ちた。

1
2
3
4
5
not ok 1 - まだ仮の期待値
#   Failed test 'まだ仮の期待値'
#   at t/order_reaches_delivery.t line 12.
#          got: '配達控え: 在庫より確保: うなぎ弁当'
#     expected: 'PLACEHOLDER'

「got:のところに出ている値を、そのまま書き写します」

その手順は、前回帳場で見たものと同じだった。書き写した値でテストの名前を改める。

1
2
3
4
5
is(
    $Delivery::slip,
    '配達控え: 在庫より確保: うなぎ弁当',
    'accept_order の効果が Kura::stage を経て Delivery::$slip まで届く'
);

動かすと、通った。

1
2
ok 1 - accept_order の効果が Kura::stage を経て Delivery::$slip まで届く
1..1

「もう、大丈夫ですよね」

ナギさんが訊いた。

「まだです」

クロベさんが答えた。

「近くだけ直したつもりで、遠くの分が動かなくなっていても、このテストが気づくかどうか、確かめていません」

ナギさんが、Kura.pmの中のDelivery::prepare_slip();という一行を、一時的にコメントアウトした。蔵での確保は動くが、配達への引き渡しだけが止まる、という状態だった。

動かすと、落ちた。

1
2
3
4
5
not ok 1 - accept_order の効果が Kura::stage を経て Delivery::$slip まで届く
#   Failed test 'accept_order の効果が Kura::stage を経て Delivery::$slip まで届く'
#   at t/order_reaches_delivery.t line 12.
#          got: undef
#     expected: '配達控え: 在庫より確保: うなぎ弁当'

「……ここだけ直しても、落ちるんですね」

ナギさんが言った。

「近くだけ直したつもりで、遠くの分が止まっている。今のテストは、そこに気づきます」

ナギさんが、コメントアウトを外して元に戻す。動かすと、再び通った。okの一行が戻ってくるのを確かめて、ナギさんが息をついた。

「今の一手間で、何が変わったんですか」

私が訊いた。落ちて、戻っただけに見えた。

「今のテストが、Deliveryまで本当に見ているということが、これで言えます。何もせずに通るだけの紙だったら、意味がありません」

クロベさんの言葉に、私はうなずいた。ただ通るだけでは足りない、というのは、前回帳場で教わったのと同じ考え方だった。今日は、その考え方を、離れた場所まで届く経路に対して確かめたことになる。

私は、クロベさんが描いた紙の矢印を、指でなぞってみた。accept_orderから出発し、Toriniwaの入れ物、Kuraの入れ物、Deliveryの入れ物と、矢印の先を一つずつ辿る。品書きが確保の記録に変わり、配達控えに変わっていく。正しさを判定するための手つきではなかった。ただ、矢印の先で値が途切れていないか、それだけを見ていく。

途中、Kuraの入れ物のところで、少し指を止めた。「在庫より確保」という言葉が、思っていたより長い文字列になっていたからだった。おかしいわけではない。矢印の向きに沿って、次の入れ物へと目を移す。たどった先のどこにも、切れ目は見当たらなかった。

矢印を最後まで辿り終えたところで、クロベさんが話をまとめ始めた。

「保証できること。accept_orderを呼べば、Delivery::$slipが必ずこの値になります。この先、ToriniwaかKuraかDeliveryのいずれかに手が入って、この値が変わったら、このテストが気づきます」

「保証できないこと。Deliveryには、他からも届いている経路があるはずですが、そこは検めていません」

「途中のKuraが違う壊れ方をして、たまたまDeliveryまで届く値が今日と同じになったら、この紙は気づけません」

クロベさんは、紙から目を上げて、私を見た。

「店主が実際に足したい確認項目そのものは、まだ手を付けていません」

「在庫が少ないときに知らせる、というところは、今日の紙にはまだ出てきていませんね」

私が確かめるように言った。今日描いた矢印の中に、蔵の在庫を見る場面は無かった。

「出てきていません。今日は、accept_orderからDeliveryまで、今すでに繋がっている道筋を描いただけです。新しく足す確認項目が、この道筋のどこを通ることになるのかは、次の工程で見ます」

「今日は、まだ何も足していないんですね」

私が言った。

「はい」

クロベさんが答えた。

「今日は、届く先を描いて、そこにだけ紙を置きました」

作業が終わったころ、通り庭にも光が回っていた。ナギさんは、外した床板を元に戻し、道具を片付けている。クロベさんは、描いた紙を折らずに、そのまま道具箱の上に置いた。まだ描き足す先が残っている、とでも言うような置き方だった。

通り庭の陰から帳場へ移ると、野帳がいつもの場所で私を待っていた。開いて、まず見立てを書く。次に、手を入れた所。それから、触っていない所を書き終える。

欄が一つ残った。「私が引き受けたこと」。ペンを持ったまま、少し考えた。前回は、自分で書くことを引き受けた。今回は、書くことではなかった。

響く先を書き出した図を、自分で読める。

そう書いた。書いてしまえば短い一行だったが、この一行を書けるようになるまでに、床の下の梁と、コードの中の入れ物を、両方たどる必要があった。前回は、自分の手で書き取ることを覚えた。今回は、誰かが描いた図を、自分の目で追えるようになった。次に同じような頼まれごとが来たとき、私は今日のように、クロベさんの手元を覗きながら教わるのではなく、自分で紙とペンを持てるかもしれない。そこまでは、まだ分からなかった。ただ、今日描かれた図を、意味の分かる形で読めた、ということだけは、はっきりしていた。


普請控

  • 見立て: 通り庭を抜ける注文の経路(accept_order)に確認項目を足したいが、変更の効果がどこまで届くのかが分からず、どこを確かめれば足りるのかが決まらなかった
  • 手を入れた所: 影響スケッチ(Effect Sketch)を描き、accept_orderの効果がKura::stageを経てDelivery::prepare_slipまで届くことを確認した。到達点であるDelivery::$slipに仕様化テスト(t/order_reaches_delivery.t)を追加した。Toriniwa.pm・Kura.pm・Delivery.pmは一行も変えていない
  • 触っていない所: Toriniwa・Kura・Delivery各パッケージの中身の処理そのもの。Deliveryに他の依頼元から届いている別経路。localを使った一時的な差し替え(今回は説明のみで実装していない)
  • 次の工程へ送ること: 店主が実際に足したい確認項目そのものへの着手。Deliveryに集まっている他の経路の扱い
  • 私が引き受けたこと: 響く先を書き出した図を、自分で読める
comments powered by Disqus
システム開発・AIワークフローのご相談は Meetsource へ
Hugo で構築されています。
テーマ Stack は Jimmy によって設計されています。