SGソフトウェアの開発日記

日々の開発に関するあれこれを書き散らかしています。

ブラックジョー問題(小変更すると今まで動いていた別の処理が動かなくなる件)

ご存知の通り(?)、JRA出走データ解析プロジェクト進行中です。
このプロジェクトでは、当日の予想のために、出走馬の過去走成績を加味した出馬表のExcelシートを生成しています。出馬表のExcelシートには、出走したレースの最高のクラスと、1着になったことがある最高のクラスを一覧として表示するようにしています。
この出馬表のデータ等を使ってレースを予想し、レース終了後の復習の際の参考にもしているのですが、10/15の東京12Rで1着になったブラックジョーのデータを見直していたところ、データに誤りがあることに気がつきました。
10/15の時点で、ブラックジョーが1着になった最高クラスは、正しくは500万下なのですが、表中では未勝利が最高クラスとして表示されてしまっています。

ブラックジョーの1着戦績が間違っている出馬表

f:id:yokotan:20161018115831j:plain


1着戦績が正しい出馬表

f:id:yokotan:20161018115825j:plain

このような不正確なデータを使っていては、正確な予想ができるはずがありません。急いで、原因の追究にとりかかりました。
このデータは、競走馬ごとの過去走を記録したExcelデータが元になっています。そこで、問題発生時のブラックジョーのデータを確認してみました。すると、500万下で1着になった前走(9/18)のレースのデータの行だけが欠落しており、2走前(8/20)のレース以前のデータは揃っていました。これが、データに誤りを生じた直接の原因です。


9/18のデータが欠落したブラックジョーの過去走成績

f:id:yokotan:20161018115821j:plain

9/18のデータを含め、欠損のないブラックジョーの過去走成績

f:id:yokotan:20161018115810j:plain

ではなぜ、このレースのデータが欠落していたのか。本来であれば、出馬表のExcelシートを作成する際に、あらかじめ、競走馬のExcelデータを更新しておく必要があったのですが、その更新が行われていなかったため、直近のデータが反映されていなかったということです。
でも、今回の問題発覚まで気がつかないぐらい、表面上はうまく動いているように見えました。どうも、最近おこなった、なんらかの修正が問題発生のきっかけになったとしか思えません。
落ち着いて考えてみると、思い当たる節がありました。ロジックをトレースしてみたところ、予想した原因が当たっているようです。
そもそも、出馬表のシートの生成処理では、競走馬のExcelシートを更新する処理はおこなっていませんでした。従って、出馬表のシートの生成処理を単体で実行している限り、まともに動くわけがないのです。にもかかわらず、たまたま、別の要因で正常に動いていたので問題視していませんでした。
たまたま動いていたロジックはこうです。
JRA出走データ解析では、当日のレースの出馬表生成処理以外に、終了したレースのレース結果生成処理をおこなうようにしています。このとき、新たなレースの着順が確定しているので、レースに出走した競走馬のExcelシートは、このレースの結果を反映するために更新されます。そのため、対象の競走馬が次のレースに出走する時点では、過去走すべてのデータが反映された競走馬のExcelシートの準備が整っており、次のレースの出馬表のシートの生成処理では、改めて、競走馬のExcelシートを更新する必要はなかったのです。
この一連の処理をそのままおこなっていれば、今回の問題は発生しなかったのですが、数週間前に、レース結果の生成処理を効率化しようと小変更を加えた結果、競走馬のExcelシートの更新処理まで外れてしまいました。その結果、一連の処理中に、どこにも競走馬のExcelシートの更新処理がないという事態に陥ったのです。
レース結果の生成処理の効率化自体は必要な修正だったのでそちらを元に戻すことはせず、出馬表の生成処理に競走馬のExcelシートの更新処理を含めるように変更して解決しました。他にも別のケアレスミスが発覚したりして修正に少し時間がかかりましたが、プログラム自体は処理済みです。
残っている問題は、今までに作成した出馬表データの解析結果が、現時点では信用できないということで、今まで作成した出馬表データをレース結果のデータと共に、再生成する必要が出てきました。1日分のデータの解析に3~5時間かかるので、次の開催に間に合わないことは確実ですが、今までのデータが全く使えないわけではないので、地道にデータの再生成を積み重ねて、徐々にデータを入れ替えていきます。
いずれにせよ、自分用のシステムでやらかしただけなので、今回は、(自分以外には)迷惑をかけていないことが不幸中の幸いです。
一般的なシステム開発では、こういうミスは、あってはならないことですが、開発の終盤(しかも予定納期ぎりぎりか、とっくに過ぎてる)では、よくある話です。「いや、うちのプロジェクトではありえない!」という方もいらっしゃると思いますが、うらやましい限りです。
なにが厄介かといって、今回のようなミスは、システムのリリース時点では露見せず、一見関係のない別の変更を行ったときに時限爆弾のように発生するタイプの問題なんですね。責任を問われるのはミスを仕込んだ時のリーダーではなく、本来は功労者であるはずの、問題が発生して解決した時のリーダーなのが、理不尽な話です。せめて、自分では、こういうミスを仕込まないように注意して開発を進めたいと思います。もっとも、仕込んだからこそ、今回こうなったんですが...。