住所の検証と正規化は、どちらも住所データを整える作業に見えますが、目的がはっきり違います。混同したまま実装すると、正しい住所を弾いたり、誤った住所をそのまま通したりします。この記事では、二つの処理の役割を分け、どちらを先に行うか、どこで失敗しやすいかを確認します。
検証と正規化は何が違うのか
検証は、その値が使えるものかを判定する処理です。合格か不合格かを返し、値そのものは変えません。必須の欄が埋まっているか、桁数や文字種が想定の形に収まっているか、存在する国や行政区の符号かを確かめます。
正規化は、表記をそろえる処理です。値は変わり得ますが、合格か不合格かは判定しません。全角と半角の統一、余分な空白の除去、大文字小文字の寄せ、旧い表記から現在の表記への言い換えを行います。
この違いを一文にすると、検証は問い合わせ、正規化は整形です。同じ関数のなかで両方をやると、どちらの理由で失敗したのかが分からなくなり、利用者に出せる案内も作れなくなります。
二つの処理の違いを観点ごとに並べると、次のようになります。
| 観点 | 検証 | 正規化 |
|---|---|---|
| 返すもの | 合否の判定 | 整えた値 |
| 値の変化 | 変えない | 変わり得る |
| 主な内容 | 必須欄の充足と符号の確認 | 表記の統一と空白の除去 |
どちらを先に実行すべきか?
正規化を先に行います。表記がそろっていない状態で検証すると、本来通るはずの値が形の違いだけで落ちます。たとえば、余分な空白が末尾に付いているだけの値や、国名が小文字で書かれた値は、内容としては正しくても、そろっていないという理由で不合格になります。
順序を逆にして、まず検証で弾き、通ったものだけを正規化する実装も見かけます。この形は、利用者に何度も入力を求めることになりかねません。一度の入力で、形の違いだけの誤りまで直してあげるほうが親切です。
ただし、正規化の結果を検証の代わりにしてはいけません。正規化は通すための処理であって、正しさを保証しません。存在しない郵便番号も、表記をそろえれば整った形になります。
完全な住所かどうかは検証できるのか?
できません。ここは期待されやすいところです。桁数と文字種、符号の存在、必須欄の充足を確かめても、その住所が現実に存在するかは判定できません。
国によっては、住所を一意に特定するための公式な照合の仕組みが提供されています。しかし、それをすべての国について用意することは現実的ではありません。多くの国には、住所を一括して突き合わせられる公開の台帳が存在しないためです。
したがって、実装で約束できるのは、書式として妥当であることまでです。存在確認ができない以上、検証の結果を「実在する住所」と表現しないよう、メッセージにも注意します。利用者に誤解を与えると、不正なデータが正しいものとして流通します。
開発者向け: 二つの処理を分ける実装
まず、関数を分けます。検証の関数は真偽値か、失敗の理由の一覧を返します。正規化の関数は、整えた値と、何を変更したかの記録を返します。両方を一つの関数にまとめないでください。
次に、失敗の理由を区別して返します。形が違うのか、必須が欠けているのか、存在しない符号なのかで、利用者に出す案内が変わります。一つの汎用な文言にまとめると、利用者は何を直せばよいか分かりません。
三つめは、正規化の前後を両方残すかどうかです。照合や検索には整えた値を使い、表示には入力された値を使うのが基本です。ただし、入力値と整形値の差が大きい場合は、どの値で保存したのかが分からなくなるため、変更の記録を残します。
四つめは、国ごとの規則を表として外に出します。桁数、必須の欄、許容する文字は国ごとに違います。コードに直接書き込むと、追加のたびに修正が広がります。国ごとの書式は郵便番号の書式に、行政区の符号はISO 国家コードと行政区コードに整理しています。
テストで両者を分けて確かめる
検証のテストでは、通るべき値と弾かれるべき値を分けて用意します。桁数違い、文字種違い、存在しない符号、必須欄の欠落をそれぞれ一件ずつです。
正規化のテストでは、入力と期待する整形結果を組にします。空白の付いた値、全角で入力された値、小文字で書かれた符号、旧い表記の値です。変更が起きない値も一件入れておくと、意図しない書き換えを検出できます。
このとき、正規化のテストに検証の期待を混ぜないでください。整形の結果が整った形になることと、その値が実在することは別の話です。テストデータのまとめ方はテスト固定装置の住所データを参照してください。
次のステップ
まず、自分のコードで検証と正規化が同じ関数に入っていないかを確認してください。入っていたら、失敗の理由が取り出せるかを試します。次に、末尾に空白を足しただけの値を投入し、合格するかを確かめます。落ちるなら、正規化が検証より後ろにあります。形の違うサンプルが必要なときはランダム住所生成で生成した値を加工すると、意図した違いを持つテスト値を手早く作れます。