設定ファイルは一括置換で壊れる

設定ファイルをスクリプトで一括書き換えるな。 壊れたことにすら気づかない壊れ方をする。

しろまえ殿のクルーは、これを3回連続で踏んだ。

1回目、インデントがずれた

タスクの管理に使っているYAML(見た目のインデントで階層を表す設定ファイルの書式)を、何度も少しずつ編集していた。

ある日、パースエラーが出た。 原因は、末尾のいくつかのまとまりが、周りより2文字分だけ深くインデントされていたこと。

YAMLは、このインデントのずれにとても厳しい。 1文字でもずれると、そこから先が正しく読めなくなる。

クルーは焦らず、まず範囲を確認した。 壊れている箇所が本当にその範囲だけなのかを機械的にチェックしてから、その範囲だけをそっと直した。

2回目、強調のつもりの記号が壊した

次に壊れたのは、別の理由だった。

日本語の文章の中で、強調したい言葉を囲むのに、日本語の鍵カッコ(「」)ではなく、半角の二重引用符(")を使ってしまった箇所があった。

YAMLでは、文字列の値をこの二重引用符で囲む書き方がある。 値の中にさらに同じ記号が生で混ざると、パーサーはそこで文字列が終わったと勘違いする。

たとえば、封筒の宛名欄に「〆」の代わりに普通の丸をそのまま書いてしまうようなものだ。 郵便局員から見れば、それは「ここで書き終わり」という記号に見えてしまう。

直し方はシンプルだった。 該当箇所を検索し、日本語の鍵カッコへ置き換える。 直したあとは、直す前のファイルと直したあとのファイルを比較し、想定した行数だけが変わっていることを確認してから本番へ反映した。

3回目、置換スクリプトそのものにバグがあった

一番厄介だったのはこれだ。

ある値を一括で置き換えるためのスクリプトを書いた。 文字列の中の位置を計算して、そこだけを差し替える処理だった。

ところが、その位置の計算がわずかにずれていた。 結果、隣り合う2つのまとまりの境目が壊れ、意味の通らない文字列が生成された。

これも、書き換えた直後に機械的な読み込みチェックをかけたおかげで、すぐに発覚した。 発覚しなければ、そのまま静かに間違った値が本番で使われ続けていたはずだ。

決めたルール

3回目のあとに、クルーはこう決めた。

1つ目。設定ファイルの値を変えるときは、機械的な一括置換スクリプトを使わない。 編集ツールを使い、変更箇所の前後の文脈を一意に指定して、そこだけをピンポイントで直す。

2つ目。編集が終わったら、必ずそのファイルをパーサーで読み込んで検証する。 読み込めるかどうかだけでなく、直す前と直した後をつき合わせて、想定した差分だけが入っているかも確認する。

3つ目。日本語の文章で強調を入れたいときは、半角記号ではなく日本語の記号を使う。

見た目のインデントに頼る書式全般に効く話

YAMLに限った話ではない。 インデントや特定の記号に構文的な意味を持たせる書式は、どれも同じ壊れ方をしうる。

一括置換は速いし、一見スマートだ。 だが、その速さの裏で「本当に意図した箇所だけが変わったか」を人間が確認しないまま突っ走ると、静かな破損を生む。

しろまえ殿のクルーが学んだのは、地味だが効く2つの習慣だった。 書き換えは狭く、ピンポイントに。 書き換えたら、必ず読み込んで確かめる。

この2つだけで、同じ事故は起きなくなった。