steps to phantasien

現場のフォーム

Form

このごろ仕事の進みが悪く、しかもまったくの自業自得で肩を落としている。 今日はそれをふりかえり明日への糧としたい。反省文。

仕事の進みは「遅い」だけ。動いてはいる。一歩一歩は正しい。 でも一歩を踏み出すまでが遅い。正しい一歩を踏み出せる、正しい姿勢をとるのが遅い。 背中を丸め足を引きずる。たとえばこんなふうに…

Bisection

ある昼下がりにバグ修正を頼まれた。リグレッション。ここ三ヶ月くらいで壊れたらしい。 リグレッションを直す「正しい」一歩目は、二分探索で原因のリビジョンを探す bisection 作業だ。 でもこのバグ、bisection が面倒そう。なんとなく原因の想像はつくからあたりをつけて直してしまおう・・・

・・・半日たち、結局あたりはつかない。日が暮れてしょんぼり帰宅。 翌朝気を取り直し bisection をしたら 2 時間でリビジョンの特定がおわる。あらら。 しかも 30 分は bisection ツールの準備。バグの原因は凡ミス。さっさとなおしておしまい。

プロトタイピング

ある機能を作ることになった。締め切り近め。仕様はまだ曖昧で、動かさないと決められない。 このとき「正しい」一歩目は・・・リグレッションの時ほど断言はできないけどたぶん・・・動くハックをでっちあげること、だろう。 でもこの機能、今のコードの想定からはずいぶん外れてるなあ。汚いコードをまき散らすのは気が重い。まずリファクタリングしよう・・・

・・・一週間後、わき出す山羊の群れを前にリファクタリングのおわる気配はない。締め切りがやばそうなので方針変更、ハックをつっこむ。 要望していた相手に見せると、なんか違うね。やっぱりこうしようとバリエーションが提案される。 あらら。これならリファクタリングいらないじゃん。ハックを巻き戻し新バージョンを実装。リリース。

リバート

ブランチ前日にクラッシュバグがやってきた。今度は bisection 済。私の(クラッシュではない)バグ修正がまずかった。 クラッシュは何より深刻だから、このときの「正しい」一歩目はリバートだ。でも元のバグ修正も次のリリースに入れたい。 今リバートするとブランチカットに間に合わない。Cherrypicking は作業も交渉も面倒だ。ここはリバートせずに直そう・・・

・・・数日後、おまえのクラッシュ修正が新たなクラッシュを引き起こしているぞとつつかれる。 あらら。失敗したクラッシュ修正と、もともとのしょぼいバグ修正を慌ててリバート。 そしてそのリバートたちをリリースブランチにマージ。クラッシュは消える。

可視化デバッグ

ある高速化を実装してみた。速くはなったもののテストが失敗している。 新しく足したデータ構造に不整合があるのだろう。「正しい」一歩は、この推測を確認すること。 データ構造をダンプするコードを書き何カ所かに差し込めばわかりそう。 でもダンプを書くのはちょっと手間だしビルドしなおしも遅い。 とりあえずデバッガで変数をながめよう・・・

・・・一時間後、ブレイクとコンティニューをぼんやり繰り返す自分に気づき我に返る。あらら。 おもむろにダンプ関数をつけたし、表示内容を調整しつつ結果を睨む。 あ、ここで不思議なノードができてるな、とかつぶやきつつ原因を特定し修正。

Deflake

翌日、先の高速化で足したテストが五回に一回くらい失敗すると知らされた。 テストのタイミングに依存したバグ。このときの「正しい」一歩は、テストから flakiness, 不確実性を取り除くこと。 でもタイミング調整はサーバにコードを足さねばならず、静的なデータだけに閉じたテストを諦めないといけない。 サーバが挟まるとデバッグも面倒だ。とりあえず思い当たる節を直してみよう・・・

・・・数時間後、試みた修正で直ったと思ったら十回に一回は失敗する、を繰り返す自分に気づき我に返る。 あらら。現実を受け入れテストを書き直す。ここで 0.5 秒 sleep() 。こっちは 1 秒。 確実にバグを暴きはじめたテストを動かしつつ先に追加したダンプを有効にして眺める。 不思議なノードがみつかる。原因を特定し修正。

開発環境

OS 固有のコードをもつモジュールに手を入れたい。 Linux と Mac は手元にある。でも Windows がない。「正しい」一歩は Windows マシンを手に入れること(VM は遅すぎてだめ)。 でも最近の Windows はよくわからないし環境をつくるのも面倒だ。さいわい Windows 固有部分のコードは単純そう。 テストは try サーバ (CI) でも動かせるから、最悪そのログを見ながら直そう・・・

・・・一週間後、書き上げた第一稿を CI に投げると案の定 Windows 上だけでテストが失敗する。 山勘で直そうとするも赤いまま。数時間のターンアラウンドをもつ CI 相手にようやくバグを直したら、 今度はライブラリの構成に問題があるとレビュアの指摘をうける。直して CI 再挑戦。今度はコンパイルすら通らない。 エラーメッセージは意味不明。ようやく挫けて Windows マシンを注文する。え、在庫ないから届くのは一週間後?あらら。

リマインド

ある素朴なリファクタリングを済ませた。 素朴とはいえ依存グラフの根元近くをさわったせいで変更範囲は広い。 遠く離れたモジュールを仕切るよく知らない人にレビューを提出。 忙しい人らしく反応がない。「正しい」一歩はたぶん隙を見て直談判。 でも席が遠いしちょっと強面なんだよな。まあ順番に見てるよきっと。ほっとこう・・・

・・・関係ないバグ修正に追われるうち週が明ける。あれどうなった?私の作業を待つ相手から問い合わせ。あらら。しまった。 深呼吸してレビュアを訪問、すみませんけどレビューしてと頼む。 「ああごめん見落としていた。だいぶ放置していたようで申し訳ない。次からはもっと強くリマインドしてくれよな。」LGTM. 案外いいひとじゃんよ。

ブランチワーク

リファクタリングは続く。肝心の変更までたぶんあと 3 コミットくらい。 準備コミットを 1 つ書いてみるも、これだけでは狙いが伝わらない雰囲気。 「正しい」一歩はまず全体像を書き上げ、最初のコミットと全体の WIP の両方を相手に渡すこと。 でもローカルコミットをため込むと序盤のレビュー指摘をとりこむのが面倒だなあ。 rebase がコンフリクトしまくる。 まあいいやこのコミットだけ渡して別の仕事をしよう。あのひとがレビュアならわかってくれるよね・・・

・・・翌朝レビューの返事が届く。「なんか不必要に複雑だけど何がしたいの?」あらら。ですよね・・・ 続きのコードを書きながら収まりの悪さに手を加えるうち最初のコミットは大げさすぎたと気づく。 彼は正しかった。簡素になった一歩目と全体の WIP を投稿。即座に LGTM.

フォームの乱れ

暗い記憶はどこまでも続くけれどこのへんにしておこう。 もたつく自分を直視し続けるのは精神衛生によくない。

正しい一歩が何かはわかっている。でも踏み出せず脇に逸れて時間を無駄にする。同じ無駄を繰り返す。 部屋の掃除や宿題を後回しにする小学生みたい。

「正しい一歩」を踏み出せないのはたぶん、その中に苦手なものが混じっているからだと思う。 苦手な環境、苦手なツール、苦手なコンポーネント、苦手なコーディング技法、苦手な人、苦手な会話。 「苦手な」が大げさなら「面倒な」でもいい。苦手なもの、面倒なもの、 手間がかかるものを前に足がふらつき、無駄骨の餌食になる。

仕事を通じ克服した苦手もある。でも苦手の増える量に負けている。 腕が悪いのか仕事が難しいのか、いずれにせよなんとかしたい。雇用が危ぶまれる。

以前プログラマの体力について書いた事がある。 この比喩を頼るなら、苦手を前に腰が引けるのは筋力不足で姿勢が崩れるようなものだろうか。 重力にや水圧に負けフォームが乱れる。 そういえば Code Kata なんてのもあったね。

コード書き本体だけでなく、それをとりまくプラクティスにも同じ事が言える。 たとえば Git を使い倒す体力、複数 OS を行き来する体力、レビュアをつつく体力。 仕事の種類によって中身は色々だろうけれど、 あえておおざっぱにこれを会社員プログラマの体力、現場のフォームと呼んでみたい。 たりないと足下がふらつく、そんな何か。 ”習慣” とはよくいうけれど、 フォームを正すのは習慣よりもがんばりのいる営みな気がするよ。

何かを得意にするのは長い道程だ。でも苦手でなくすだけならそこまでの労はない。 低いはずの敷居を前に苦手意識をこじらせてしまうのはたぶん、 余裕のない場面で実践を強いられたからだろう。 締め切り前、休暇の前、上司の前。忙しい緊張の中で面倒はおこる。 皮下脂肪を抱え準備運動もなくゲームに放り込まれるこの感じ、ちょっとトラウマになる。

一方で、このストレスや後悔はフォームの乱れを脳裏に焼き付ける強いシグナルともなる。 あとから見落とさずにすむのは不幸中の幸い。暴かれた弱点を少しずつ直して行こう。

・・・捻ったその足首の、腫れが引いたらね。