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

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


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

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