見出し画像

排他を知らないエンジニア

案外多い…ということをご存じですか?

ちなみに私が解決してきたプロジェクトの中にもこの「排他」が原因でニュース沙汰になるようなトラブルを起こしているものを含め、いくつかのプロジェクトが存在していました。

大手SIerも含め、それくらいこの排他を知らないまま開発に従事してきたエンジニアというのは存在しているんです。

 排他制御

ソフトウェア開発の中では決して珍しくもなく、ひょっとすると30年以上前から存在しているいアーキテクチャだと思われますが、これを明確に理解している、あるいは説明できるエンジニアは多くありません。

ファイル、メモリ、データベース、etc.…プログラムが「プログラム外の領域(外部リソース)」を操作しようした際に、そこにはある重大な観点が必要になります。それが

 「同時にアクセスすることがあるか?」

です。

 プログラム vs プログラム
 プログラム vs 他プログラム
 プログラム vs OS等
 プログラム vs 人の操作

同一のものを複数の人で共有する場合、それは日常生活においてもブッキングしないように注意するはずで、これと同じことがプログラミングの世界で起こらないと思う方がおかしいわけです。

相手が何であれ、同時にアクセスし、変更や削除をされていると参照中の情報は最新ではなくなってしまいます。こうしたことによって起こる事故を防ぐために、あるいは事故が起きたことを知らせるために用いられるアーキテクチャを『排他制御』と言います。

例 悲観排他

プロセスを排他するために用いられる『mutex』
ファイルを排他するために用いられる『semaphore』
データベースを排他するために用いられる『lock』

ここに挙げられたものは、一般的には悲観(的)排他と呼ばれるものですが、他にも楽観(的)排他と言うプログラムでモニタリングするような概念もあり、それぞれの用途に適した様々な排他技法が用意されています。

しかし、せっかく用意されていても利用する側…つまりこれからソフトウェアを作成しようとするエンジニア自身がただしく理解していなければ宝の持ち腐れです。

結局、重大なトラブルを起こすと言うことに変わりはありません。
メジャーなところでは、以前こんなことがありましたね。

情報処理推進機構が主催するIT試験の会員サイトから個人情報が漏洩しました。団体受験した企業が自社の受験者リストをダウンロードすると、他社の受験者情報が混入するトラブルが起こったのです。排他制御をかけ忘れるという初歩的なミスが原因でした。複数の企業がほぼ同時に操作した時に限って表面化するバグが原因だったのです。

「誰だろう、この松橋竹夫(仮称)という人は。当社の従業員ではないようだが」―。
 従業員のITスキル向上に力を入れている、ある企業(仮にA社とする)の担当者は首をかしげた。「ITパスポート試験」を受験する自社社員のリストを申し込み用のWebサイトからダウンロードしたところ、見慣れない名前が数十件混じっていたからだ。
 情報処理推進機構(IPA)は2018年3月13日、企業などの団体がITパスポート試験を申し込む際のWebサイトに不具合があり、個人情報が漏洩するトラブルが発生したと明らかにした。試験を申し込んだ企業はこのWebサイトから自社の受験者リストをダウンロードできる。そのリストに本来含まれているはずのない他の企業の受験者と思われる情報が混入していた。
 漏洩したのは名前や受験日、「チケット番号」と呼ぶ受験料の支払いを証明する番号などで構成する120件ほどのリストだ。住所や決済情報は含まれていなかった。
 漏洩したチケット番号を使うことで、受験料を支払わずに不正受験ができてしまう恐れがある。IPAによると現在までに不正受験の形跡は確認されていないという。

他社情報が見えるなら自社情報も
 ITパスポート試験はIPAが主催する代表的な資格試験の1つだ。ITに関する基礎的知識を問うもので、2009年に開始。ITを業務で活用する非エンジニア職のほか、商業高校、IT系コースを専攻する学生などに受験者層を広げ、2017年度の受験者数は9万4298人と昨年より8000人ほど増えた。企業や学校法人が団体で申し込むことも多い。
 受験申込者用のWebサイトは試験情報の発信に加えて、受験の申し込みや支払い手続き、合否確認などがオンラインでできる機能を提供している。団体が一括で申し込んだり、受験状況などをリストとして一括ダウンロードしたりする機能も備える。
 A社の担当者も社員の受験状況を確認するためリストをダウンロードした。2月26日午前9時ごろのことだ。この日はリストの内容が明らかにおかしかったため、内容を印刷して確認。そのうえでもう一度Webサイトから同じ手順でリストをダウンロードしてみた。
 すると先ほどの知らない名前は消えていた。ファイルは一時的なエラーだったようだ。担当者は当初、この現象を深く追及する気はなかった。
 しかし、印刷していた最初のリストを見返すと、疑問が頭をもたげてきた。「この知らない名前は他社の受験者情報ではないか」。A社の担当者はサポート担当のコールセンターに電話をかけ、印刷したリストを手にこの問題を訴えた。「別の会社の受験者リストが漏洩している可能性がある」。受験者リストに自社とは無関係な個人情報が混入していたこと、同じ現象は2度目からは再現していないことを伝えた。
 同じ頃、別の企業(仮にB社とする)も同じ問題に突き当たっていた。B社の担当者がダウンロードしたファイルに知らない個人名などが混入していたのだ。再度ダウンロードすると今度は正しい一覧だった。A社と同じ事象である。同様のエラーが再び起こるかもしれないと考え、コールセンターに連絡を取り、問題を報告した。
 A社とB社の報告はコールセンターを経てシステムの構築・運用を担当している日立製作所に伝えられた。日立はIPAに対し、情報流出の可能性があるとただちに報告。その日のうちにIPAが原因究明に動いた。
 IPAはA社とB社に連絡を取り、訪問の約束を取り付けた。2社ともに最初のファイルは上書きしたか削除したかして手元に残っていなかった。ただし、その内容は印刷していた。IPAの担当者は2月26日にA社、翌27日にB社を訪問して、印刷物からファイルの内容を確認した。するとA社とB社の一部受験者の情報が互いのリストに混入していると分かった。印刷はリストの一部だったため断定はできないものの、2社の受験者情報が混在した同一のファイルをそれぞれダウンロードした公算が高い。A社とB社がほぼ同時刻にサイトから自社の受験者一覧をダウンロードしていた事実も判明した。

日経×TECHより

データベースアクセスに関しては、

 「排他が正しく機能しているかどうか」
 「排他制御のアーキテクチャを導入するべきポイントはどこか」

あるいは、こうした問題が起きた時に

「他に排他制御の抜け漏れを起こしているアクセスは存在するか」

を即時に見極めるために有効なツールとして、個人的によく用いたのは

 CRUD図

でした。というか、データベースに限らず、ファイルでもメモリでもバグを修正する際の影響調査においてもこのCRUD図を応用していました。それほどCRUD図というのは非常に便利な設計書だったりします。

例 CRUD図

けれども、昨今の開発専門のエンジニアのなかではその重要性を理解している人はごくわずかしかいないように感じます。保守・運用を経験したことのある人であれば多少は重要であることの意味を理解している人もいらっしゃるでしょうが、延々と開発ばかり繰り返している方のなかでは『率先して準備している』と言っている人を未だに見たことがありません。

私の中では、外部リソースへのアクセスが存在するソフトウェアあるいはシステムにおいて、CRUD図を作成することはほぼ必須であると認識しています。

すくなくとも『排他』が原因で起きたトラブルを解決するために参画すれば、必ずと言っていいほど全SQLを分解し、衝突タイミングを調査し、各テーブルごとどころか、各カラムごとのCRUD図を作成しました。

そこまでしないと、お客さまに対して

 「他に〇ヶ所ほど問題となる可能性があるポイントを検知しました」
 「本当に問題があるのはこれだけしかありません」
 「他に問題はありません」

と説明し、証明し、そして保証しきって見せることができないからです。

排他が実際に問題となるようなタイミングは0.1msあるかないかの今際で起きるものです。単体テストのようにbreakpointを作れるのであればまだしも、実動テストで検証しようと思ってもなかなか再現することが難しかったりもします。

だからこそ、論理的に100%証明しきって見せることが重要なのです。

排他制御におけるトラブルにおいて、あるいは排他制御回りのトラブルが起こらないことを証明する場において

 CRUD図抜きに品質保証を行うことは不可能

ですので知っておくと良いでしょう。

だからこそ、設計時の検討証明用にも必須となってくるのです。設計時に排他制御を盛り込む箇所の過不足がないかどうかは、CRUD図がなければ証明できないからです。

しかし、先ほども言いましたようにプロジェクトの現場ではまともに作られているプロジェクトをあまり見たことがありません。「必要だから作るように」と提言しても、だいたい「スケジュールに影響が出る」と難色を示されていました。本来はQAから言われることではなく計画時点で検討すべきことのはずなのですし、スケジュールに影響が出ないよう元々込みで工数見積もりをしていればスケジュールに影響が出ることもないはずのものですが…。

また、仮に存在していたとしても初期設計時から改版されておらず、最新にされることもなくただの自己満足に陥っているケースが殆どでした。

CRUD図とは、外部リソースがどの機能で

 作成(Create)、参照(Read)、更新(Update)および削除(Delete)されるか

をマトリックス形式で表現したもの(設計書)のことです。

多くのプロジェクトで「存在しない」あるいは「作成しても最新管理しない」…と言うことは、そこに関わる多くの何万、何十万というエンジニアはそれだけCRUD図の作成意図や重要性を理解していないと言うことを意味します。

実際、みなさんはどれほどその重要性を理解していますでしょうか。

意味もないのに作ったって意味は生み出せません。
意味があるから作るのです。

でも、その"意味"すなわち『目的』を理解していないのでは、必要があっても作ろうという発想に辿り着きません。だから作らないし、作っても改版しないし、その結果として問題も絶えないわけです。

「なぜ必要なのか?」

と言う問題意識が理解できていれば、それがどれだけ重要な設計書なのかが自ずと自覚できるはずです。

CRUD図は

(初期設計時)
  それぞれの外部リソースに対して機能が過不足なく存在するか確認する
  それぞれの外部リソースに対して排他の必要性を確認する

(問題発生時)
  それぞれの外部リソースに対して、排他の有無が適切に実装されている
  ことを確認する

と言う目的のために作成します。
裏をかえせば他の目的には利用できません。そしてこれらの目的を達成するために最も有効な設計書はCRUD図以外にありません。他の設計書で代替できるのかもしれませんが、それでもCRUD図以上の効果を示すことはありません。

さらに、CRUD図は排他の要否や可否を検討する意味でももちろん重要な設計書ですが、それと同じくらい『それぞれのデータに対して、4機能が過不足なく存在するか確認する』ためにもとても重要な設計書な点についても、理解しておきましょう。

たとえば、あるテーブルのあるカラムに対して、
すべての機能に

 ①R(参照)があるのに、C(追加)も、U(更新)も存在しない
 ②D(削除)があるのに、C(追加)も、U(更新)も存在しない
 ③U(更新)があるのに、C(追加)が存在しない
 ④C(追加)やU(更新)があるのに、R(参照)が存在しない

設計となっていたとします。

…こんな設計に意味がありますか?

CもUもないと言うことは、そのカラムの値は一生変わらないと言うことです。初期値が null であれば一生 null であり続けると言うことです。そんなデータを参照する機能は、満足なデータが本当に得られるのでしょうか?

①②③はそれぞれ、データをインプットする機能が無いにもかかわらず、アウトプットする機能が存在するケースです。明らかに機能が不足しているか、機能要求が不足しているかのいずれかであることがわかります。

④はインプットする機能だけ存在しているにもかかわらず、アウトプットする機能が存在しないケースです。

ソフトウェア、あるいはシステムは、『データ(=情報)』を適切に取り扱ってナンボの代物です。冗長的なインプットやアウトプットは、無い方が良いのです。無駄に存在していると、

 ・トラフィックに多大な損害をもたらす
 ・ストレージ容量を圧迫する
 ・CPU処理に負担をかける
 ・メモリ消費量が増大する

といったごく当たり前の障害を生み出します。

SQL文の使いまわしや、旧システムの流用など、意味を理解しないままに正しく影響を調査することもなく、

 「あるものをそのまま使えば楽だから」
 「仕様さえ満たせば、多少ゴミが混ざっててもいいと思ったから」

という身勝手な判断で、最適化されないシステムができることも珍しくありません。


『排他』と言う概念については常に意識できるようにしておきましょう。

エンジニア1年生にはちょっと難しい内容かも知れませんが、2~3年生になっても知らないようではちょっとマズいかもしれません。そろそろ大きな問題を起こし始めてもおかしくない時期に差し掛かっています。

おそらくそれができないエンジニアやプロジェクトマネージャーは、日頃から排他に対する意識が疎かになっているせいで、自身のスケジュールなどにおいて適当に管理していて、当日に"予定がブッキングしていた"なんてことも簡単に起こしてしまっているかも知れませんね。


いただいたサポートは、全額本noteへの執筆…記載活動、およびそのための情報収集活動に使わせていただきます。