「唯一の基準」を作る二重実装が生む静かなズレ
同じ計算や判断が複数箇所に重複すると、片方だけ直して片方が古いまま、という静かなズレが必ず生まれる。NGWの開発で何度も立ち返った「唯一の基準」という設計原則を、集約の実務と落とし穴とともにまとめる。
静かに食い違っていく
システムを長く保守していると、あるパターンのバグに何度も出会う。バグと呼ぶには症状が地味で、しかし放っておくと信頼を確実に削っていく類のものだ。同じ職員なのに、帳票と画面で役職名が違う。同じ休暇を取ったのに、申請画面と残日数の集計で日数が合わない。同じ勤務なのに、命令簿と集計で時間外の区間が一致しない。
追いかけると、原因はいつも同じ構造をしている。「役職名を組み立てる」「時間を日数へ換算する」「勤務時間から時間外の区間を切り出す」といったひとつの判断が、コードの複数箇所に別々に実装されているのだ。書いた時点ではどれも正しかった。だが制度が変わり、片方だけを直す。もう片方は古い基準のまま残る。こうして二つの実装は静かに食い違っていく。誰も気づかないまま、数字だけが人を欺くようになる。
この連載で扱ってきた話題の多くは、突き詰めるとひとつの原則に行き着く。Single Source of Truth ── 唯一の基準を作る、ということだ。
派生値は一次データと単一の変換から導く
自治体向けのシステムは制度の細部が絡む。役職名の付け方には団体ごとの呼称の特例があり、休暇の単位換算には所定の割る数があり、時間外には「夕方の開始は定時終了時刻から」といった境界の決まりがある。こうした細部は、同じ判断が帳票・画面・集計へと自然に散らばりやすい。だからこそ、この原則がよく効く。
具体例を三つ挙げる。決裁欄の役職名を六箇所で別々に組み立てていたのを、ひとつの生成関数に集約した話。休暇の時間から日数への換算で、割る数を使う全箇所で同じ基準にそろえないと、保存される値そのものがズレてしまう話。時間外の区間を、集計でも帳票でも同じ一次データと同じ境界から導くようにした話。
三つに共通するのは、表示や派生値は、一次データと単一の変換関数から導く。各所で計算し直さないという姿勢である。役職名は職員データとひとつの生成関数から。日数は申請時間とひとつの換算関数から。区間は打刻や勤務データとひとつの切り出し関数から。派生値を各画面で「もう一度計算する」誘惑を断つことが、ズレを構造的に防ぐ。
集約するときの実務
とはいえ、散らばった実装をひとつにまとめる作業にはポイントがある。
まず、いきなり全部を差し替えない。正しい基準をひとつ決め、それを新しい関数として用意する。そのうえで、旧実装の結果と新実装の結果を実データで突き合わせ、差分がゼロであることを確認してから切り替える。制度の細部が絡む領域では、自分が「正しい」と思った基準が、実は既存の帳票が長年出してきた値と一致しないことがある。差分の一件一件が、忘れられていた特例を教えてくれる。差分ゼロは、集約が安全である証明書だ。
次に、集約先は純粋な関数にする。基準日、職種、団体の区分といった文脈を、グローバル変数や画面の状態から暗黙に拾うのではなく、引数として明示的に受け取る。入力が同じなら出力も同じ、という性質があって初めて、新旧の突き合わせが意味を持つし、後から呼び出す側も安心して使える。文脈を隠し持つ関数は、集約したつもりで新たな依存を生むだけだ。
落とし穴 ── 似ているだけの判断をひとつにしない
一方で、この原則を振りかざしすぎると別の負債を生む。過度な共通化だ。たまたま今は似ている二つの処理を、無理にひとつの関数へ押し込めると、やがて if と分岐で膨れ上がる。呼び出し側ごとにフラグを渡し、関数の内部はフラグごとの特例だらけになる。これは重複より始末が悪い。
見極めるべきは、それが同じ判断なのか、たまたま似ているだけなのかである。役職名の生成は、どの帳票から呼ばれても「同じ判断」だ。だからひとつに集約する価値がある。逆に、見た目が似ていても拠って立つ制度が別なら、それは別の判断であり、無理に束ねてはいけない。Single Source of Truth は「コードの見た目を似せる」原則ではなく、「ひとつの判断を一箇所に閉じ込める」原則なのだ。
AIとの協働作業での学び
重複したコードは、書いた瞬間はいちばん楽だ。手近な場所にコピーして少し直せば、その場は動く。しかしそのコードは、時間とともに必ずズレる。そして地味に、静かに、人を欺く数字を出し始める。
だから、唯一の基準を置く。派生値はそこを通してしか作らない、という規律を保つ。DRY(Don't Repeat Yourself)という原則は、しばしば「コード量を減らすため」と語られるが、本質はそこではない。判断を一箇所に閉じ込め、ズレを構造的に防ぐためにある。行を減らすのは結果にすぎない。守りたいのは、システムが同じ問いにいつも同じ答えを返す、という信頼のほうだ。