Windows開発を、ハラハラドキドキのジェットコースターに乗っているようなスリリングなものだととらえている人は、ほとんどいないでしょう。実際、私たちソフトウェア開発者は、むしろそういったスリルを回避したいという行動原理で動いていると言っても、過言ではありません。 私たちの仕事は、平穏で、キーボードとマウスのクリック音だけが響くような静かなものでありたいと考えています。それでも時折、私たちがうっかり作成してしまったバグが、気まずい会話につながることもあります。そして時には、クライアントにコスト負担を強いるような深刻な事態に至ることもあるのです。この記事で、Delphi開発者のDavid Bolton氏が紹介しているエピソードは、正直それらの想定をはるかに超えるものです。そのバグが引き起こしたのは、なんと8億ドルという誤った情報でした。なんてことでしょう。そのプレッシャーたるは…
Table of Contents
Delphiが石油取引ソフトの開発を効率化
石油は、世界で最も多く取引されている商品です。私は、グローバルで6万人の従業員を抱える米国の大手銀行の、ロンドンのカナリーワーフを拠点とする商品ソフトウェア部門で働いていました。私たち4人のチームに与えられた任務は、石油取引ビジネスソフトウェアを稼働させ、ソフトウェアパッチの適用、バグ修正、新機能の追加を行うことでした。
特に、Delphiで記述された2つのトレーディングアプリケーションのメンテナンスが、私の主な業務でした。トレーダーのシステムは、取引入力用のもので、およそ160万行のコードで構成されていました。これらは主に現物の石油取引でしたが、先物やオプションなどのデリバティブも含まれていました。
このシステムは、MTS(Microsoft transaction Server)が稼働するサーバーと通信するメインのトレードエントリアプリケーションを含む、2層アプリケーションでした。30個のCOMサーバープログラムがすべてMTS上で実行され、トレーダーが取引を保存すると、それぞれが1種類の取引を呼び出します。すべてがDelphiで記述されており、通常は2万~3万行のコードになります。
MTS上で実行することで、高い復旧能力を提供しています。バグが発生しても、MTSは問題のあるCOMオブジェクトを強制終了し、必要に応じて別のCOMオブジェクトを再起動します。さらに、このアーキテクチャにより、一度に複数の取引を、並行して保存することが可能になりました。通常、20~30人のトレーダーが同時に取引に参加し、保存していました。
XMLが世界の金融を動かしている
取引はメインアプリケーションから、数百行にも及ぶ巨大なXMLファイルに保存されていました。これらは関連するCOMサーバーに渡され、そのCOMサーバーはXMLファイルを読み取って、複数のINSERT/UPDATEを伴う大規模なSQLトランザクションを生成します。これは、Sybase ASE 12に対して実行され、取引の保存が完了するとメインアプリケーションが更新されます。
データベース管理ツールの使用
こうしたエンタープライズ開発におけるメリットの1つは、エンタープライズツールが利用できることです。データベース管理には、すべてDBArtisanを使用しました。この業務では多くのSQLを書いてきましたが、DBArtisanでは操作ログを記録でき、そこで使用しているSQL文を保存しておくことができたので、作業がずっと簡単になりました。
私は、もともと1つだったコードが、2つのコードベースにこの10年で分岐してしまったものを、再びマージするように依頼されていました。これは、それぞれに約800個のファイルがある2つのフォルダーツリー間で差分を作成し、その相違点を特定して対応するという作業です。Araxis Merge(COMサーバーとして使用できるエンタープライズファイル比較ユーティリティ)を使用して、すべてのフォルダーとファイルを比較するDelphiアプリケーションを作成し、作業時間を数週間分節約することができました。
石油取引は、極めて複雑化しがちです。タンカーが原油を製油所に降ろす作業は数日かかることもあります。この期間中にも石油価値は変動します。原油を降ろす作業が完了するまでは、毎終了時に合意された市場価格で価格設定され、作業が完了すると所有者の変更が行われます。そしてそれ以降は、契約価格を使用して評価されるのです。
他に取り組んだアプリケーション開発
私たちがサポートした2番目のDelphiアプリケーションはPLServerで、それは約120万行の Delphiコードで構成されていました。さまざまな各オイルデスクが、PLServerを使用して1日のすべての取引を実行し、すべての評価を行った後に利益と損失の数値を計算します。これらの処理は、毎日午後6時から午後8時までトレーダーによって実行されますが、取引量が多いため実行に1時間かかるものもありました。
1日の終わりの損益計算書は財務管理者に渡され、翌日、銀行の取締役会に提出されます。従って、これらの数値が作成できないことは許されません。「8億ドルのバグ」が見つかるまでの数年間、すべてがうまくいっていました。
8億ドルのバグ
私は、PLServerのメンテナンスを行っていました。そこには、あらゆる種類のログ機能が組み込まれており、通常は極めて迅速にバグを検出し、修正することができていました。99.9%以上の稼働率で、完全な運用が行われていたのです。しかし、ある日、特定のデスクのPLServerが、前夜の予想よりも8億ドル多い利益を上げたというメッセージを受け取りました。これは、銀行の取締役会レベルが直ちに知ることとなり、迅速に解決すべしと、強い要請を受けたのです。システムが提示した利益はすばらしい金額に見えましたが、それは完全に誤った数値です。財務管理者は、手動でこれを修正しなければならなかったので、直ちにシステムを修正するように要請されました。
翌日の夜から、トレーダーの了解を得てすぐに、私のデスクトップコンピュータでそのデスクのPLServerを、直接Delphi IDEから実行してみました。そのように、本番環境で稼働させてみることは、少しイレギュラーな措置でしたが、必要な緊急対応でした。実際、この処理は、毎日1回しか実行できなかったため、問題箇所を見つけるのに数日かかってしまいました。私は分割統治法を使用して、問題を絞り込んでいきました。
バグの追跡
最終的に私は、問題のバグを発見しました。非常に重要なコードをスキップしていたのは、ゼロ除算例外が原因でした。同社が評価していたこの特定の取引は、日本円を使用しており、ドルに変換するには除算を行う必要がありました。為替レートはおよそ1ドル=140 円でした。
例えば、取引価格が10,000円だったとします。ドル価格は、value := Value_in_Yen/Yen_rate;
で、71.25ドルにならなければいけなかったのです。しかし、ゼロ除算例外がキャッチされずに、そのまま処理されました。その結果、為替変換処理はスキップされ、その価格はそのままドルに、つまり10,000ドルとして扱われたのです。その結果、実際の値よりも140倍も大きな価格になってしまったのです。
ゼロ除算は、発生してはならない種類のバグです。その後、新しいタイプの取引が私たちに通知されることなく、トレーダーによって導入されたことが判明しました。この取引の取引期間はゼロ日であり、それが例外の原因でした。それ以前は、日の長さがゼロになる取引はなかったので、日の長さで割った除算をゼロで割るチェックは行っていなかったのです。この箇所に同チェックを追加し、修正コードをテストして、翌日には本番環境にリリースすることができました。
8億ドルのバグ追跡におけるDelphiの活躍
Delphiは、デバッグ作業を簡単にしてくれました。このような大規模なアプリケーションでも、コードを変更してコンパイルし、1分以内に再実行できるのは大変役立つ能力です。私の同僚はC++でプログラミングしていましたが、編集、コンパイル、再実行に少なくとも 5~10分はかかっていました。彼は、Delphiの短いコンパイル時間をうらやましく思っていました。
COMサーバーとDelphiでのMicrosoft DVCの使用
これまで、COM(Windows Component Object Model)を使用するアプリケーションの開発は C++で行ってきましたが、これはかなり高度な処理で、その構文はひどいものです。Delphi は、COMサーバーやオートメーションサーバーなど、COMを使用して複雑なアプリケーションを作成できる、C++以外では唯一のプログラミング言語です。 そして、それはC++よりもとってもシンプルに記述できます。
3つのインターフェイスを実装するマルチスレッドのCOMサーバーの作成を含む、Microsoft DVC(Dynamic Virtual Channels)の実装も実現できました(DVCについては、こちらを参照)。これにより、RDPセッションで実行されているプログラムが、デスクトップコンピュータで稼働するプログラムと通信可能になりました。これらは、すべてDelphiで記述され、正常に稼働しています。
この記事は、Enterprise Article Showcaseへ投稿されたものです。RAD Studio、Delphi、C++Builderと関連技術を用いて構築した開発プロジェクトの成功事例をお持ちの方は、ぜひご連絡ください。詳細はこちらをご覧ください。