前号: No 307 / 次号: No 309 / 一覧に戻る
2023年の3月あたりから、コンビニなどで住民票などの交付サービスでのトラブルが相次いでいます。 他人の証明書を交付してしまう深刻なトラブルが、この数ヶ月で4度も発生しているようです。 証明書交付システムですので、他人の証明書を交付することが厳禁であることは開発側も十分に承知していたはずですが、あまりにお粗末と言わざるをえません。 どうしてこんな事態に陥ってしまったのか?という視点でこのトラブルについて筆者の考えを述べたいと思います。"1. お客さんのやりたいことはお客さんしか知らない
前回の繰り返しを含みますが、システム開発のやっかいな点を最初に書いておきます。 システム開発というと、プログラマがコンピュータに向かい、謎の呪文を次々と入力してプログラムなるものを作り続けているイメージを持つ方が多いと思います。 ですが、実際には上記のようにプログラムを作る作業(プログラミングや製造などと言います)は全体の作業のほんの一部(感覚的には10〜20%)でしかありません。 それよりも多くの時間を「要件定義」や「設計作業」や「テスト」に費やします。 要件定義はお客さんが欲しいものを整理し、予算に合わせて実施範囲を選んでもらう作業、設計作業はそれをどんな風に作るかを決める作業、テスト作業は作ったプログラムが要件定義で決めた通りに動くことを確認する作業です。 ここで作成する資料は「要件定義書」や「システム設計書」「テスト仕様書」といった名称のもので、いずれも日本語で作成します。 要件定義書やシステム設計書には、お客さんがやって欲しいコトが全て記載されているはずです。 ところが、実際にはこれが難しいのです。 一般論ですが、新人のバイト君を雇うことを考えてください。 新人バイト君には最初に一通りのことを教え「わからなかったら聞いてね」としますよね。 実際、一通り聞いていた内容と違っていたら、バイト君は質問をしてきます。 そうやって実際の仕事を覚えていくわけです。 ですが、システム開発でこのやり方を取るとひどいことになります。 システム開発者は実業務でどんな例外事象が起きるかなんて知りません。 なので、システム開発者は「確実に○○はあるんですね?」とか「△△が受理されないケースは他にないですか?」などとしつこくお客さんに確認をするわけです。 これが甘い状態でプログラムを作ってしまうと、稼動後に「思っていた動きになっていない」とお客さんが青い顔(まっ赤な場合も...)で飛び込んでこられるわけです。2. レビュー
こういった認識の不一致を避けるために、システム開発では頻繁に「レビュー(見直し)」作業を行います。 要件定義書(暫定版)を作成したら要件定義レビュー、基本設計書を作成したら基本設計書レビュー、機能仕様書を作成したら機能仕様書レビューという具合です。 レビューは言い間違い、聞き間違い、伝え忘れ、誤解といったコミュニケーション不足による誤記や記述不足を補うために行います。 レビューをしなかったからといって、必ずしも失敗プロジェクトになるわけではありません。また、レビューをしても、コミュニケーションがぎくしゃくしていれば、あまり効果はありません。 お客さんと開発者が、遠慮せずに討議できる素地ができていれば、レビューは濃密なものになり、たくさんの指摘が行われます。 レビューでの指摘が多いことは、システム開発を成功に導く大きな要因です。3. 証明書交付サービスでのトラブル
地方自治体などで、コンビニなどで住民票などの証明書を交付(印刷)できるサービスがあります。今回のトラブルは、その住民票交付時に誤って他人の証明書が印刷されるというものでした。 コンビニ交付では、コンビニにあるマルチコピー機(以下、コンビニコピー機)で証明書交付を依頼すると、その地方自治体にある証明書交付サーバ(以下、交付サーバ)に交付依頼をします。交付サーバは依頼された印刷用データを作成してコンビニコピー機に送り返し、コンビニコピー機でその印刷を行っています。 箇条書きにすると、正常時の動きはこんな感じです。 1) コンビニコピー機から証明書交付依頼 2) 交付サーバで証明書データを作成 3) 交付サーバがデータをコンビニコピー機に返送 4) コンビニコピー機で印刷 5) 証明書交付完了 今回のトラブルが起きた時はほぼ同時刻に2つの依頼が行われ、そのうち片方がエラーとなり、さらにバグが重なり、結果として、他人の証明書を交付してしまったのです。 (この原因については後述します) 住民票などの証明書にはマイナンバーなど、他人に知られるとマズい情報が掲載されています。実際、マイナンバーは自治体から勝手に提供することはできないように法の制約を受けています。 これに違反するわけにはいきませんから、発注側(自治体など)から受注側(システム開発元)に対しては、「他人の証明書が間違って交付されないこと」は重要な条件として伝えられているはずです。 このメルマガを書いている時点(2023年5月21日)で、同様のトラブルが4件も発生しています。開発元によると、いずれもプログラムのバグが原因なのですが、それぞれに違った理由で起きていたというのです。 上記の事情は容易に想像できることですので、今回のトラブルを始めて聞いた時、にわかに信じがたい思いでした。4. 発生原因はプログラムミスなのか?
プログラムが意図しない動作をする場合はバグと呼びます。 ですが、バグが生まれる要因は様々です。 まず、要件定義時点での誤解が原因となる場合があります。 依頼側の依頼内容を開発側が誤解したら、要件定義書は誤解した通りの内容になります。 それを元に設計書を作れば、当然その誤解は残ったままです。 その設計書を元にプログラムを書けば、誤解したままのプログラムが作られます。 また、テストを行う時も最初の要件定義書からテストすべき機能や内容を決めますから、同じように誤解したままでテストを行います。 また、設計時点での誤解や間違いが原因となる場合もあります。 今度は、要件定義は正しいのにシステム検討段階である設計で間違うパターンです。 「1秒以内に○○すること」という要件を「10秒以内に○○すること」と読み違えてしまうと、採用する技術や方式が違ってきたりします。 この間違った設計書から、プログラムを作ると、当然ながら間違ったプログラムになります。 ただし、要件定義での誤解とはその後がちょっと違います。 要件定義書は正しいのですから、そこからテスト内容を決めていれば、誤りが検出できるのです。もっとも、テスト内容からそれが洩れていればそれまでですが。 次に来るのがプログラムを作る時のミスです。 皆さんが思い浮かべるバグはだいたいこのパターンだと思います。 例えば、プログラムが突然落ちる(終了する)、計算結果が期待値と違う、日本語が文字化けする、といったものの多くがプログラム作成時のミスによるものです。 補足: 上記の全てがプログラムミスとは限りません。 設計ミスや要件ミスもあり得ます。 設計書に書かれた計算式が間違っている場合もありますから。 バグの発生要因について3パターンを書きました。 ここで着目いただきたいのは「全てがシステム開発元のミスとは限らない」点です。5. レビューは伝家の宝刀
例えば要件定義書の誤りは誰が訂正すべきでしょうか? 「そんなの開発元に決まってる」ですか? 開発元は誤解しているのです。 その誤解に自ら気付くことを期待するのは「望み薄」だと思いませんか? これを避けるには上述のレビューが絶大な効果を発揮します。 要件定義書をレビューする主体は依頼側です。実現して欲しい機能を正しくイメージしているのは依頼側なのですから当然と言えば当然です。 次に設計書をレビューする主体はシステム開発側ですが、筆者は依頼側も積極的に参加すべきだと考えています。 確かに実現方式の詳細は技術的な話が多くなるのですが、依頼側の意図を汲んだ設計になっているかどうかは依頼側が参加してチェックをすべきだと思うからです。 「なんでこんな方式にしているの?ウチがお願いしてる○○はちゃんと担保できるの?」といった質問をされるのは、システム開発元にとっては実にありがたい話なんです。 こういった質問に答えるには依頼側がわかるような説明資料を作る必要があるなど、コスト面では不利になります。 また、「システムなんてわからないから、そっちで判断してよ」と難色を示す方も多いです。確かに、よく知らないことを理解するのは時間も労力もかかりますから、設計書レビューに参加するのに負荷がかかるのは事実です。 ですが、視点を変えれば多くのメリットが見えてきます。 設計レビューに参加すれば、設計書に潜んでいる誤解に気付く可能性が高くなります。 もちろん設計書での誤解は開発元が見つけるべきです。ですが、それでも見落としは発生します。それを防ぐことで後の面倒が避けられるのなら、むしろ安上がりではないでしょうか。 また、せっかくお金をかけて作ってもらうのに、その内容が全くわかってない、知らないというのは良くない、というかもったいない話です。 ちょっと例が良くないですが、住宅を建てる時には施主が頻繁に現場を見に行くのが良いそうです。大工さんとしては張り合いが出ますし、手抜きをしにくくなるそうです。 システム屋だって人間なんですから、相手が興味を持ってくれればより良いものを作りますし、コミュニケーションも良くなります。 レビューというのは、資料をベースにして互いの意思疎通にとても便利な道具ですから積極的に活用していただきたいと思います。6. 交付サービスのトラブルの分析
今回の一連のトラブルでは他人の証明書が交付されてしまった要因と思われるものが二つありました。 1) 逐次処理形式で実現 2) 同じファイル名 まず、逐次処理についてです。 逐次処理というのは、複数の依頼が来ても、同時には1つの処理しか動かないようにコントロールする方式です。 そのためには、一般的にはキュー(queue:待ち行列)と呼ばれる仕組みを使います。 ファミリーレストランなど混雑する店では順番待ちの紙がありますよね。あれがキューです。 順番待ちへの書き込みはお客さんが来たタイミングで書き込み、席が空くとウェイター/ウェイトレスさんが、その紙を見て次のお客さんを席に誘導し、誘導したお客さんの名前を消し込みます。 キューも同じことを行います。 コンビニコピー機からの交付依頼は交付サーバのキューに入り、交付サーバが空くと、キューの最初を調べて交付処理を実行する、という仕組みです。 キューを使った仕組みは、処理順序が重要な場合にはよく採用されます。(チケットの席取りシステムなんかは早い者勝ちですから典型的ですね) ですが、このシステムでは依頼順序によって処理が変わるといった判断はないように思います。筆者には逐次処理にする必要がよくわかりません。 コンビニコピー機は勝手なタイミングで依頼がくるのですから、来る度に並行して処理をしても問題ないように思います。 次に、ファイル名についてです。 このサービスの交付サーバ側の処理だけに着目すると次のような処理になっていたと思われます。(筆者の推測) 1) コンビニコピー機から交付依頼を受け付ける。 2) 対象の利用者情報をデータベースから抽出する。 3) 利用者情報を使って交付ファイル(印刷依頼できる形式のファイル)に保管する。 4) 交付ファイルの内容をコンビニコピー機に送り返す。 一方で、エラーが発生した時には次のような流れとなるのですが、ここでファイル名が同一であることが、今回の被害のトリガーとなってしまっています。 1) コンビニコピー機(A)から証明書交付依頼 2) コンビニコピー機(B)から証明書交付依頼 (別店舗) 3) 交付サーバで証明書データ(A)を作成 4) 交付サーバでエラー発生後、バグ発生(後述) 5) 交付サーバで証明書データ(B)を作成 6) 交付サーバがデータ(B)をコンビニコピー機(A)に返送 7) コンビニコピー機(A)で印刷 8) 証明書(B)交付完了 手順4で、エラーが発生した時はコンビニコピー機(A)にエラーを返して、A用の処理は終了するはずでした。 ところが、そこにバグがありエラーを返さずにコンビニコピー機(B)のデータ作成処理を動かしてしまいます。 その結果、コンビニコピー機(A)にB用のデータを返してしまったというのです。 バグの多くはエラー処理で発生します。エラーのパターンを網羅してテストを行うことが難しい(考慮すべきパターンがやたらと多い)ためです。 ぶっちゃけ、バグはまぎれこみます。 それでもシステムの動作に影響がないようにするには、バグが残っていても致命的な動作にならないような設計にするのが定石です。 設計書に「同じファイル名とならないように留意する」とか「ファイル名は○○機能で得られたものを使用する」といった留意事項が書かれていてしかるべき内容です。 自社の後輩がこのケースで同じファイル名を使うプログラムを書いてきたら、筆者はプログラムレビュー(コードレビュー)でボロカスに言います。7. まとめ
今回のトラブルでは依頼側とシステム開発側のコミュニケーションに問題があったのではないかと思われるフシがあります。 本システムでは「他人の証明書が間違って交付されないこと」が非常に重要な条件だったはずです。 それにも関わらず上述の設計となってしまったのが不思議でなりません。 依頼側は要件定義でも言ったはずですし、設計レビューに参加していれば、このような設計とした意図を確認しているはずです。 開発元では、上で筆者が指摘した二点は問題ではなく、(テストで)バグを抽出できなかった点が問題だったという発言をしていますが、全く同意できません。 テストで全てのバグなど取れるはずがないのです。 今回は設計での考慮不足が主要因と思いますが、開発にかかわった参加者の多くにそれを呼び寄せる根本原因があるように感じました。 依頼側は、要件定義や設計時のレビューに熱心に取り組んだか? 開発側のマネージャは、依頼側にレビュー参加を強く呼びかけたか? 開発側の設計チームは、十分な考慮を行っていたか? 開発側のプログラマチームは、設計方式を鵜呑みにしなかったか? これを見ますると、システム開発に「全員参加」が必要なことを改めて感じます。 今回は、証明書交付サービスのトラブルについて筆者の考えを述べました。 次回もお楽しみに。 (本稿は 2023年5月に作成しました)