チェックをシステムの境界へ移す
9月27日に公開されたプログラミングの論考が、Rustの視点から「検証するのではなく、パースせよ(parse, don't validate)」という格言を再検討している。中心にあるのは、条件を確認した後も制約の緩い値をプログラム内で引き回すのではなく、確認済みの性質を表現する型へ生の入力を変換すべきだという考え方だ。
筆者はRustでおなじみの例から説明を始める。通常のベクターは空である可能性があるため、その`first`メソッドは`Option`を返す。このAPIは汎用的な型に対しては正しい。問題が生じるのは、設定ファイルのパスを格納するベクターに少なくとも1項目があることを、別の関数がすでに確認している場合だ。返されたベクターを使うコードは、それでも空の場合を処理しなければならない。型そのものには、それ以前に得られた保証が記録されていないからだ。
この食い違いを解消するのが、このパターンの狙いだ。パースによって空ではないコレクション型が得られれば、後続の関数はその不変条件を直接頼りにできる。信頼できないデータや構造が曖昧なデータがシステムに入る箇所でチェックを行い、パースに成功すると、拒否された状態を表現できない値が得られる。これにより、繰り返される条件分岐を減らし、関数のシグネチャでプログラムの前提をより多く伝えられる可能性がある。
Rustでは明示性との兼ね合いが表れる
RustではAPIが値の不在や失敗を表すために`Option`や`Result`を日常的に使うため、この問題が見えやすい。これらの型は、他の言語では表に出ないこともある可能性を、呼び出し側が認識するよう求める。論考の趣旨は、そのような処理が不要だということではない。境界を越えた後なら、より強い型によって、ありうる状態を絞り込めるということだ。
この方法にもコストはある。プロジェクトにはラッパー型や、その型の規則を強制するコンストラクター、不変条件を失わずに一般的な操作を提供するメソッドが必要になるかもしれない。開発者は、その保証がこうした仕組みを設けるに足るほど重要で、安定したものかどうかを判断しなければならない。一度しか使わない値なら、その場でチェックする方が分かりやすい場合もある。システム内の広い範囲で受け渡す値なら、規則を型に組み込むことで、後続のコードが起こりえない状態に繰り返し備えるのを避けられる。
したがって、このパターンは入力処理だけでなく、API設計にも深く関わる。検証は、幅広い状態を取りうる値が、ある時点で受け入れ可能かどうかを伝える。パースは、より限定された値を返し、その形自体が結果を後続へ引き継ぐ。この違いはテストのあり方も変える。境界でコンストラクターをテストすれば、より強い型を受け取るコードは、入力条件を再び確かめるのではなく、本来の処理に集中できる。Rustでは、この区別によって、コメントや繰り返しのチェックをコンパイラーが認識できる構造へ置き換えられる。それまでプログラマーの記憶にしか存在しなかった前提を、コードの保守時にも維持しやすくなる。



