類似バグを効率的に見つけ出すための観点

品質を上げる上では、レビューやテストにてあるプログラムのバグを1つ見つけた場合、「他にも同じようなバグが潜んでいないか」という視点で追加でレビューやテストを入れるのが定石です。
類似バグが発生しやすいポイントを押さえて追加レビュー・追加テストを行うことで、少ない工数で品質を上げることができます。

類似バグが潜んでいないかどうかのチェックをIT業界の用語で「横展開」や「水平展開」と呼ぶのですが、このチェックを行うポイントの見極めにはいくつかのコツがあります。
今回の記事では、そのコツについて挙げていきたいと思います。

1.業務ロジックが類似している処理に目をつける

これが基本中の基本です。
「横展開」や「水平展開」と呼ばれるチェックは、多くの場合は業務ロジックが類似している処理のチェックになります。

例えば、小売店のシステムについて、新たな割引制度を導入するシステム対応を行っているとします。
そして、割引後の値段の算出について、端数の扱いの誤りに起因するバグが見つかったとします。
もし、割引後の値段を算出する記述が複数個所にあるのだとしたら、他の記述についても同じ誤りをしている可能性が高いので、それらの記述については全て追加レビューや追加テストをするべきです。
また、割引後の値段を算出するロジックを考える際に参考にしたロジックがあるのであれば、例え既存ロジックだとしてもその記述をチェックするべきです(本番運用でまだ見つかっていないバグが既存ロジック中に潜んでいる場合があります)。

2.特定の担当者や会社に着目する

スキルや仕事の進め方の違いにより、特定の担当者や会社の成果物にバグが集中して発生することがあります。
そのようなケースだと考えられる場合、特定の担当者や会社の成果物について集中的にレビューやテストを行うことで、効率的にバグを見つけ出すことができます。

特定の担当者や会社の成果物にバグが集中していることを見つけるためには、客観的な指標としては、メトリクス(品質の高さを示す数値)が参考になります。
例えば、「単体試験バグ数/STEP数」はソースコードの品質を推し量るのに役に立ちますし、「単体試験で見つけるべきバグの発生頻度」を結合試験で測っているのであればそれは単体試験の品質を推し量るのに役立ちます。

また、品質チェックを行う側に十分なスキルがあるのであれば、メトリクスを取るまでもなく、ちょっとしたやりとりから主観的な観点で品質の高さを推し量ることも可能です。

3.低品質のモジュールに着目する

仮に同程度のスキルで同じような仕事の進め方をする担当者・会社が集まっていたとしても、バグが集中的に潜んでいるモジュール(部品)とそうではないモジュールに分かれることが多いです。
一般的に、業務ロジックが複雑なモジュールや、多くの他モジュール・他システムと連携するモジュールは、バグが発生しやすいです。

バグが発生しやすいモジュールに対しても、集中的にレビューやテストを行うことで、効率的にバグを見つけ出すことができます。
注意点として、業務ロジックや連携が複雑なモジュールに関しては、そのモジュールを作成した担当者や管理者がどれだけレビュー・テストを行っても知識不足により十分にバグを見つけ出せない場合があります。
そのため、業務のスペシャリストや、連携先のモジュール・システムの担当者の力を借りることも重要になります。

低品質なモジュールについても、メトリクスのような客観的な指標を用いると見つけやすいです。
また、複雑性が高くバグを埋め込みやすいモジュールは設計段階で何となく気付くので、早い内から集中的にチェック・テストを行う計画を立てておくことも有効です。


いかがでしたでしょうか。

レビューやテストを完璧に行うことは時間的に不可能なので、バグを引き起こしやすい箇所に集中して行う必要があります。
(テストで境界値チェックが有効とされる理由もそこにあります)

今回は、バグを引き起こしやすい箇所の見分け方を、横展開という観点で書いてみました。
参考になれば幸いです。

O/Rマッピングの概要の説明

最近の現場では、SpringFrameworkの導入と共に、O/Rマッピングを取り入れた開発を行うことが増えてきました。
O/Rマッピングについて、背景にある考え方や必要な機能、問題点を簡単にまとめました。

【O/Rマッピングが生まれた背景】

O/Rマッピングは、RDBを用いたシステムにおいて、オブジェクト指向を実現するために用いられる手段の一つです。

RDBは、データ中心アプローチを実現するのに向いています。
「データ中心アプローチ」とは、「データやそれに付随する手続きは変化しにくい」という前提の元、テーブル定義やクエリ、ストアドプロシージャ等に機能を集中させることで、変化に強いシステムを作るアプローチです。

オブジェクト指向はデータ中心アプローチの後に広まった概念です。
システムを責務(クラス)に分解し、その責務同士の関係性をプログラミングで表現することで、変化に強いシステムを作るアプローチです。
仮にデータの持たせ方が変わるようなシステム更改を行う場合、データ中心アプローチよりも変更が容易になります。

先に述べた通り、RDBはデータ中心アプローチを実現するのに向いており、オブジェクト指向を実現するには向いていません。
そこで、SQLによるRDBの操作は最小限に止め、なるべくオブジェクト指向言語であるJava等で処理を実装する、という方針で実装されることが多くなりました。
(データ中心アプローチ/オブジェクト指向という面だけでなく、「カバレッジを取得しやすい」「静的解析をしやすい」といった言語の機能面からも、長いSQL文で実装するよりも短いSQL文+Javaで実装する方が好まれるようになりました)

O/Rマッピングはこの流れの中で生まれた考え方であり、オブジェクトとリレーション(RDB上のデータ)を対応付けようとする考え方です。
O/Rマッピングは、Java等のオブジェクト指向言語でRDBを扱いやすくする手段の一つとして使われることになります。

【O/Rマッピングの実現に必要な機能】

ざっくり言うと、RDBの存在を意識することなくオブジェクト指向言語でデータを扱えるようにする機能が必要です。

イメージとしては以下です。

  • Dtoクラスを参照する時に裏側でRDBのテーブルの読み込みが行われる
  • Dtoクラスを更新する時に裏側でRDBのテーブルの更新が行われる

この時にRDBに発行されるSQLは、O/Rマッパーの機能により自動生成されます。

(なお、SQL文をXMLファイル等に開発者自身で事前定義することが可能なO/Rマッパーも存在します。SQL文を事前定義する場合は、後述するO/Rマッパーの問題点が解消されますが、その代わりにRDBの存在を意識せずに実装するという思想も実現できなくなります。)

【O/Rマッピングを実現するツール(O/Rマッパー)】

代表的なO/Rマッパーとしては以下のようなものがあります。

  • Hibernate(JPAを実装したツール)
  • MyBatis(2010年にiBatisから改名)

【O/Rマッパーの問題点】

O/Rマッパーの問題点としては、「どのようなSQL文がどのタイミングで発行されているか分かりにくい」という点に尽きると思います。

具体的には、性能面の調査・改善が難しくなるという問題点があります。
O/Rマッパー導入により、以下のような問題点が引き起こされがちです。

  • ループ内でのSQL発行(N+1問題)
  • インデックスが使用されないSQLの生成
  • 遅いSQLの特定が困難(ソースコードをSQL文で調べても出てこない)

O/Rマッパーの機能を使いこなせばこれらの問題点を解決できるのですが、導入初期の段階で意識する必要がある他、開発者に対する教育コストが必要になります。

あくまでもSIerの場合ですが、SQLの知識・スキルは基本情報処理技術者試験で最低限のレベルは身に付けているはずですし、開発作業や運用作業にてRDBをSQLで操作する機会も多いので、O/RマッパーよりもSQL直書きの方が馴染みやすいという開発者は多いと思います。
SQLを自由に書けるなら性能問題を解決できるのに、O/Rマッパーを使用すると思い通りにSQLを発行・検索できずに性能問題を解決できない、と感じてしまう点が、開発者の不満点になってしまっていると思います。


いかがでしたでしょうか?

SQLを書くことに慣れた技術者からはO/Rマッピングが嫌われがちなようなのですが、O/Rマッピングには単に「SQL文を書かなくて良い」以外のメリットも存在し、そのメリットを享受するためにはコーディングスタイルの見直しとO/Rマッパーの学習が必要になります。
(ただし、O/Rマッパーの学習については、O/Rマッパーの種類毎に使い方が変わる上、現場毎でルールも異なっているので、SESとして働くのであれば現場に入ってからの学習で十分です)

今は多くの現場でO/Rマッパーを使う流れになってきているので、上記のようなことを理解しながら、上手く付き合っていくのが良いと思います。

東証ArrowHeadの事例から見るシステム利用者に向けた理想的な障害報告

少し古い事例ですが、2020年10月01日の東証ArrowHead障害の会見から、システム利用者に向けた理想的な障害報告を見て行きたいと思います。
https://www.youtube.com/watch?v=Sokp32qOvyE
この会見は、障害報告のお手本と言える会見だと思います。

ビジネスを理解している者とシステムを理解している者を会見に同席させ、様々な観点の質問に的確に回答している点も素晴らしいですが、システム利用者に説明するべきことを冒頭で簡潔に報告していることも素晴らしいです。
この会見では以下の1~4のことが報告されており、これらのことは東証ArrowHead以外のシステムの障害発生時にも報告するべきことです。

システム利用者からすれば、1と2は現状を把握する上で必要な情報です。
また、今後の対応を行う上で、3も必要な情報です。
4は、サービス品質を保つ努力を示すために報告するべき情報です(もし障害対策に落ち度があれば、品質強化策や再発防止策を策定し、後日報告するのが望ましいです)。


【報告事項の概要】

1.障害の発生日時の報告

  • 2020/10/01の9時前(取引開始前)に、東証ArrowHeadの相場情報システムで障害発生。

2.意思決定も含めた障害対応の経緯と、利用者への影響

  • 原因は機器のハード障害である。
  • 障害により、株価等の相場情報を正常に配信することができなくなった。
  • システム全体の整合性を保つことを優先し、当日中の障害復旧は行わなかった。(復旧による二次障害を防ぐことを優先した)
  • 主要プレイヤー(証券会社等)からヒアリングを行った上で上記の決定となった。
  • 障害復旧を行わなかったことで、終日売買停止となった。
  • 障害発生当日は、市場は開いていたが全銘柄注文が付かなかった、という扱いとした。

3.今後の対応予定

  • ハードウェア交換作業を行い、翌日より通常通り取引可能な状態とすることとした。
  • 翌日の早朝(恐らく7時頃)、ホームページや広報を通してシステム状況を通知する。

4.障害対策を行ったのにも関わらずにユーザー影響に至った理由

  • 機器は多重化されており、フェールオーバー(機器切り替え)も想定されていた。
  • フェールオーバーのテストも事前に行っていた。
  • ハード障害は、自動でフェールオーバーすることができないという現象も起こした。
  • 手動でのフェールオーバーは可能であり、手順も用意されていた。(ただし、2にて前述した理由により、当日中のフェールオーバーは行わなかった)

いかがでしたでしょうか。

東証ArrowHead障害の会見については個人的にメモしていたのですが、今回はそのメモを一般的な知見として吸収できるようにブラッシュアップし、公開しました。
業界関係者であれば感動を覚えるような綺麗な会見なので、見たことがないという方は今からでも見ることをお勧めします。

プログラミング言語のスキルチェンジで役に立った共通スキル

私は元々COBOLやC言語を主に扱っていたエンジニアでしたが、3年前からJavaやC#を中心的に扱う現場で仕事をするようになり、現在ではJavaScriptを使うフロントエンド業務にも従事するようになりました。
プログラミング言語に依らない共通のスキルを有していたため、経験の浅い言語や未経験の言語の仕事を頂くことができました。
また、キャッチアップもこれまで経験してきた言語との違いに着目するだけで良かったため、難しいものではありませんでした。
この記事では、私の経験を元に、役に立った共通スキルを紹介していこうと思います。
プログラミング言語のスキルチェンジを考えている方の参考になれば幸いです。

【役に立った共通スキル】

・アルゴリズムの知識

例えば、誤差が許されない金額計算で用いられるアルゴリズムは、言語に依らず様々なシステムで使われています。
また、コントロールブレイクやマッチングといったファイル操作のアルゴリズムは、メインフレームの基幹システムで使われることが多いアルゴリズムですが、基幹システムの中には脱メインフレームを果たしたシステムもあり、そのようなシステムではCOBOL以外の言語でそのアルゴリズムが書かれます。
これらのようなアルゴリズムの知識があれば、言語の知識が無くとも設計を担当することができますし、キャッチアップを図る際も重点的に勉強するべきポイントを掴むことができます。

・メモリに関する知識

COBOLでは16進数の文字コードを扱う機会が少なくありません。
そのため、文字列やバイナリ文字を見たまま理解するのではなく、16進コードを想像しながら読む癖が身に付きます。
モダンなシステムでは16進コードを意識する機会は多くありませんが、それでも文字コードの違いや入力禁止文字を考える機会はあるため、そのような場面で16進コードで考える癖が役に立ちます。
(モダンな技術者は16進コードに慣れていないので、このスキルはレア度高いです)
また、C言語ではポインタ変数やメモリ確保・解放といったことを意識します。
C言語経験者がJavaを学ぶ際、ポインタ変数の知識は参照型変数(代表例はインスタンス変数)、メモリ確保・解放の知識はJVMのメモリ管理の理解に役立ちます。

・RDBMSの知識

レガシーシステムでもモダンなシステムでも、データの管理にはRDBMSを使うのが主流です。
そのため、SQLやテーブル設計やチューニングといった技術は多くの現場で通用し、これらの技術を有しているだけでも現場で重宝され、仕事を頂くことができます。
筆者はデータベーススペシャリストを所持していますが、この資格では製品に依らない体系的な知識を問われるので、個人的にはこの資格の勉強をするとスムーズに知識を習得できると思います。

・保守や運用の知識や経験

COBOLを使用しているレガシーなシステムに携わると、システムの保守や運用に関する豊富な知識や経験を得られます。
障害が発生しにくい改修作業、障害の検知、障害発生時のリカバリー、といったことを、設計段階から考えられるようになります。
このようなスキルは、システムを安定的に運用したい全ての現場で求められ、プログラミング言語をキャッチアップする前から設計やレビューで活躍できます。

・リーダー経験

システム開発はチーム戦であるため、10名程度のチームをまとめた経験があるとその経験自体も活きます。
設計スキルにリーダー経験が加わると、チーム外との仕様調整で外部仕様を固め、それに基づいて内部仕様の概要を決め、内部の詳細仕様と製造を特定言語に詳しいメンバーに割り振る、という立ち回りができるようになります。
仮に、現場で使われるプログラミング言語の知識に乏しかったとしても、この立ち回りができるだけでチームの中心人物として扱われるようになりますし、メンバーからプログラミング言語の知識を教えてもらうこともできます。


あけましておめでとうございます!

今回は、スキルチェンジをする上で役に立った共通スキルを紹介してみました。
このような、実体験ベースの話も、今後書いていきたいと思います。

本番障害発生時に元請けSIerで発生する作業とその影響

社会インフラを支えるシステム、例えば金融システムや公共システムについては、高い信頼性が求められます。
このようなシステムの本番運用で障害が発生した場合、その結果は重大なものになります。
一般的なイメージとして、その「重大なもの」として、以下のようなものをイメージすると思います。

  • 信頼が失墜する(最悪の場合は報道される)
  • 経営者がお客様に怒られて、責任者が経営者に怒られて、技術者が責任者に怒られる
  • 技術者や責任者が缶詰になる

この記事では、本番運用で障害が発生した場合に、元請けSIerで一体何が発生するのか、元請けSIerのプロパーであった私の経験を交えて、より具体的に書いていこうと思います。
そして、具体的に何が起こるのかを知ることで、品質向上の意識を高めていただければと思います。


【障害の検知】

障害を検知する契機として、「お客様に指摘される」という契機で見つかるのは最悪です。
事前にSIer側で障害を発見できなかったためにお客様の心象が悪くなることで、その後の要求(障害対応、再発防止、補償)が厳しいものになるためです。
また、お客様に指摘されているということは、既にデータが作成されて、「画面」「帳票」といった形でお客様の目に触れているので、そのデータを補正しなければならないということで障害対応の作業内容の難易度も上がります。

そのため、お客様に見つかる前に障害を検知する努力を惜しまず行うべきです。
異常なデータが発生した時点でその箇所の処理を停止させれば、運用作業でその箇所だけ補正して対応することができます。
エラーハンドルが重要であるとされるのはこのような理由からです。
また、この運用作業は人手で行うこととなりミスが発生しやすいので、システムを構築する場合は、運用作業を予め計画して手順化することでミスの発生を抑える努力も重要になります。
システム改修直後は障害が発生する可能性が高いので、すぐに障害対応できるように、改修直後の監視体制を敷くことも重要です。

なお、システム改修の結果、思いもよらぬ箇所に影響が発生し、重点的に監視していない箇所で障害が発生しお客様に指摘されるというのも良くあることです。
影響調査を抜け漏れなく行うことも重要になります。

【障害の対応方針の検討】

障害が発生した場合、どのような障害が発生したのか、その事象内容と原因をお客様に報告する必要があります。
そして、システムの都合の観点と、お客様の業務の継続の観点から、対応方針をすり合わせることになります。
検討している間にも障害は発生し続けているので、検討は迅速に行う必要があります。

システムの都合の観点で言うと、障害対応でプログラム作成が必要なのであればその期間を見る必要がありますし、プログラムを実行・リリースするタイミングも計る必要があります(サービス停止日にしか実行・リリースできないことも多いです)。
それまでの間の暫定対応(運用作業)の計画も立てる必要があります。
そして、暫定対応はお客様の業務を継続する上で必要なレベルを満たす必要がありますし、恒久対応では元々求められていたレベルに戻す必要があります。暫定対応中に制約や機能制限が発生するのであれば、そのことについてもお客様の了承を得る必要があります。

なお、この時点で明らかに対応するべきことがあれば、責任者の許可を取った上で、技術者は検討中にも対応し続ける必要があります。
手順書に書かれた作業や、その他常識的に行うべき作業(例えばディスク容量オーバーでシステムが落ちたのであれば不要データの削除とシステム再起動)がそれに該当します。

【暫定対応の実施】

検討された方針に従って、暫定対応を行います。
この作業は基本的に手作業での運用になることが多いため、運用担当者を立てて体制を整える必要がありますし、運用作業でのミスが無いように手順書や簡易ツールを作成する必要もあります。
また、暫定対応中に制約や機能制限が発生するのであれば、そのことを説明する文書の作成と周知という事務作業も発生します。

【恒久対応の実施】

プログラムの作成が必要なのであれば、それを作成する担当者を用意して工数を割り振る必要があります。
そして、プログラムの本番環境での実行・リリースに向けた準備(手順書作成、社内手続き等)も必要になり、また実行・リリースに向けた出社体制を整える必要も出てきます。
お客様の立ち合いが必要なのであれば、お客様にも立ち合いを依頼する必要があります。

【再発防止策策定】

恒久対応が完了した後、お客様へ恒久対応完了の報告を行います。
しかしそこで終わりではなく、今後同じようなことが起こらないように、障害が発生した要因の報告と、再発防止策の策定を求められることが多いです。
社内での再発防止策の検討、そして再発防止策の説明にまた工数を取られることになります。
また、再発防止策は、チェック体制の強化に繋がることも多いので、それが積み重なると開発スピードの低下にも繋がりかねません。
(多くの開発者にとってストレスになるであろう、重厚長大なチェックリスト、煩雑な承認体制、頻繁なダブルチェック・トリプルチェックは、再発防止策が積み重なって出来上がるものです)

【障害に対する金銭的な補償】

障害が発生した場合、SIer側が金銭的な補償をしなければならない場合もあります。
システムのSLA(サービス内容に関する合意文書)に補償に関する項目があるなら、それに従って補償をしなければなりません。
重大な障害である場合は、裁判で損害賠償請求されることもあります。

仮に、直接的な補償がなかったとしても、障害を発生させたことでその後の交渉でSIer側が不利になり、システム継続利用時に値下げ要求をのまざるを得なくなることも少なくありません。
ニュースで報道された場合は、直接被害が発生していないお客様との交渉でも不利になりやすくなります。
当然、競合システムに離反されることもあり、この場合も収益の低下に繋がります。


以上のように、本番障害を発生させることで、SIer側には以下のような損害が発生します。

  • 障害対応や再発防止策のための工数の発生
  • 再発防止策による開発スピードの低下
  • 障害に伴う金銭的な補償

本番障害が頻発する現場では、不定期に発生する障害対応・再発防止策の工数と開発スピードの低下が原因で、次のシステム開発にも支障が発生し、QCD(品質・コスト・納期)のバランスを取ることが困難になります。
障害に伴う補償をしただけでなく次のシステム開発も予定通りに進めることができなくなるため、収益力が低下することになります。
頑張って長時間働いても、それに見合う収益を得ることができなくなってしまいます。

このように、本番障害を発生させることによる損害は誰にとっても大きいため、本番障害を発生させないように一人一人が意識する必要があります。
障害を発生させた経験から学ぶという姿勢ではなく、社内外の過去の障害事例から学ぶ姿勢が重要になります。


いかがでしたでしょうか。

2次請け以降の立場で案件に参画していると、本番障害発生時に何をしているのか伺い知れない所が出てきます。
この記事により、その情報を上手く共有できれば幸いです。

来年も、この調子でブログを更新していこうと思います。
では、良いお年を!