トラブルシューティングの極意―達人に訊く問題解決のヒント

第9回[ソフトウェア開発編][実例満載]現場での対応と改善の手段

トラブルへの対応には多くの困難が伴います。プロダクション機の情報が取得できず原因追及に着手できない、発生条件が特定できない、予想もしない個所のコードに問題がある、などなど。くだらないミスが原因であることがほとんどですが、設計時の考慮不足・知識不足によりもたらされるものもあります。今回は、筆者がこれまで体験したトラブルからいくつか「何が起こったのか」⁠どう対応したのか」を具体的に紹介し、考察します。

トラブルと真正面から向き合う+調べる

障害発生時にすべきこととは

ソフトウェア開発においてバグや作業ミスによるトラブルはつきものです。トラブルに遭遇したときは焦ってしまいがちですが、まず落ち着くこと。浮足立っているとよけいに事態を悪化させてしまいかねません。そして何より誠意を持って対応するというのが大切です。関係各所に連絡を取り、回避策があれば暫定的に適用していただき、データが壊れている場合、直せるものは直し、ダメなら業務側での再作成をお願いする。そのうえで、できるだけ早期にバグフィクス版をリリース、システムを復旧させなければなりません。

[事例1]納品先で固まるプログラム

新人のころ、周辺機器からシリアルポート経由でデータを受信し処理するプログラムを作成する仕事をしました。納品日、お客様の環境にインストールして動かしたところ、プログラムがハングアップして応答しなくなってしまいました。

会社の開発マシンでは問題なく動いていたので非常に焦りました。お客様にお詫びして検収を延ばしてもらい、会社に引き返して必死にプログラムを見直しました。すると、データ受信処理で固定バイトずつデータを読み出しており、指定バイト数のデータが読み取れなかった場合の考慮がないことに気づきました。そこで、読み出しのたびにバイト数を保持して、指定バイト数に達したらデータを処理[1]するように修正しました図1⁠。

図1 納品先で固まるプログラムをどのように直したか
図1 納品先で固まるプログラムをどのように直したか

お客様と同一機種のマシンがなかったので、バグフィクスの確証は持てなかったのですが、翌朝一番に訪問して動作を確認し、無事検収いただくことができました。経験が浅い筆者には入力待ちによるブロッキングの可能性を想像できていませんでした。

開発環境と実行環境の差でプログラムが動作しないというのはよくあります。サーバサイドのプログラムでは、本番機(あるいは本番機相当のステージング環境)でリハーサルを行うのは常識になっていますが、特定のマシンがターゲットの場合、開発時に調達するか、お客様に借りるなどして検証機会を設けたいものです。

[事例2]起動しないWeb App Server

筆者がかかわっていた業務アプリ開発現場での話です。Webアプリケーションサーバが起動途中にクラッシュしてしまうという現象が何日も解決できず、プロダクション機の構築担当チームが途方に暮れていました。筆者ら開発者も支援に入りましたが、はじめて使用するプロダクトというのもあってログを見ても原因がわかりません。スケジュール的に待てない状況だったので、プロダクト製造元のトラブルシュート専門技術者が召喚され、クラッシュ時のメモリダンプを解析しました。それでも原因特定できません。そこで、あらためて全員でパラメータシート[2]と設定ファイルの項目をひとつひとつ見比べていったところ、ある設定値が間違っていることに気づきました。ケアレスミスによる大幅な時間ロスでした図2⁠。そして、製品を疑うよりもまずは自分たちのミスを疑えという典型事例でもありました。

図2 製品よりも、自分たちを疑え!
図2 製品よりも、自分たちを疑え!

[事例3]終わらない移行作業で負け試合

とあるバッチ処理を新方式に移行する作業をしていました。メインフレームから送られてきた固定長の販売データをRDBに格納します。新規開発したバッチプログラムを新規プロダクション機にデプロイし、数ヵ月分の販売データを投入、作業が完了したらお客様がデータを確認しリリース判定をします。金曜日の晩から作業を開始、土曜日にデータ確認、日曜日は予備日です。失敗したらリリースを延期して翌週末に再チャレンジ。思ったより処理時間がかかり、土曜昼過ぎまでかかって半分ぐらいのデータをローディング。お客様も週末返上で確認しています。最後の数ヵ月分の数字が合わないと、土曜の夕方に連絡が。土曜の泊まりを覚悟します。プログラムを見直し、数ヵ月分を再ローディング、日曜の昼に再確認してもらいましたが、まだ合わない個所がありました。もうこの週の移行は無理なのですが、日曜深夜までデータ調査とプログラム修正・データローディングを繰り返し、月曜朝3日ぶりに自宅にたどり着きました。翌週末も泊り込みでようやく移行終了図3⁠。

図3 移行作業はループする(過労はどんどん蓄積する)
図3 移行作業はループする(過労はどんどん蓄積する)

なぜ、このような負け試合になってしまったのでしょうか。じつは、筆者らはお客様が見ている最終の帳票を見ていませんでした。お客様には作業手順、データ処理方式を提示し事前合意していたのですが、最終結果をどのようなビューで見るのかという確認はしていなかったのです。結局、日次処理の計算式にいくつかの仕様齟齬(そご)があったのですが、お客様から指摘を受ける機会のないまま、設計・実装・移行が進んでいたのです。

処理方式だけでなく、エンドユーザが確認するアウトプットを開発者も確認できるように調整することは重要です。そうしないと隠れた仕様に気づかないまま進むリスクがあります。

旧システムと新システムの出力の差異はよくトラブルになります。旧システムの実装を確認せずに進めると、端数処理や計算式の違いが大幅な差異となることが多いのです。

[事例4]突如、激遅になったOLAP

業務システムに負荷をかけず、自由自在にデータを取り出し意思決定をすることができる便利なOLAPシステム。業務データの形式が変更されると、当然OLAPのデータ形式も変更する必要があります。ある商品のコード体系が数字から英数字に変更になりました。そこで、OLAP側の定義も追従して修正、データの取り込みを終え、変更作業終了しました図4⁠。

図4 なぜか激遅になったOLAP
図4 なぜか激遅になったOLAP

翌日から、OLAPから結果が返ってこないというクレームがユーザから続々と。これまで長くても数十秒で取得できていた問い合わせ結果が、数分から数十分待ってやっと返ってくる状態です。業務が止まってしまうので、本番機は修正前の状態に戻し、ステージング 環境で性能を調査。OLAP製品の仕様書やマニュアルを見てもコード体系とパフォーマンスの記載はなく、メーカに問い合わせても数字→英数字のコード変更で遅くなることはあり得ないとのこと。データの再ローディングとかパーティション見直しなど、いろいろやっても復旧せず。そのOLAP製品を提案したのは我々だったので、製品開発担当者を召喚してもらいました。件(くだん)の担当者は「その修正で遅 くなるはずがない。元から遅かったんじゃないのか」などと驚愕の発言をして、その場を凍りつかせ、お客様の逆鱗に触れてしまいました(ホントに人間性を疑います⁠⁠。我々は針の筵(むしろ)のような状況で調査を続行。試しに変更されたコードのデータをソートして投入してみたところ、これまで通りの応答時間で結果が返ってくるではありませんか。2日かかってようやく解決、新鮮なデータでOLAPを使ってもらえるようになりました。

製品選定、方式検討のときには見えていないことはたくさんあります。アンドキュメンテッドな製品の仕様、ふるまいに泣かされることもあるのです。

ソフトウェアのテストこそ切り札か? ―製造工程で品質を作り込め!

難易度が高い保守フェーズの仕事

ソフトウェアの保守フェーズになると開発チームが縮退し、属人的な知識は霧散します。残った保守メンバーは担当したことのない個所のコードを修正し、やったことのない作業を実施することになります。開発時に十分なドキュメントが整備されコードが共有されていれば、迅速に障害対応できデグレードも防げるでしょう。しかし、現実にはスケジュールに追われ十分な知識伝搬ができていないケースがほとんどです。時間に追われて書かれたコードはバグを含んでいたり、修正が難しい形になっていることがままあります。保守チームは少ない人数で膨大なコードに立ち向かい手探りで修正しなければなりません。業務が止まるような障害ならなおさら余裕はありません。保守というのはある意味で新規開発よりも難易度が高く厳しい作業です。

カットオーバー後に目を覆いたくなるような障害が頻発し、保守メンバーが日々の対応に消耗していく地獄のような現場はいくつも存在します。このような事態にいたる要因はいくつもありますが、典型的なものをあげてみましょう。

仕様レス

何が正しい仕様かわからない。ユーザがバグと言っているけどプログラムのロジックをどう修正すべきかわからない。仕様はコードに表現されているという考えもありますが、コードには実装都合のロジックも入ります。ドキュメントが多すぎるのも考えものですが、保守のために必要な仕様書は整備されているべきです。

コードが汚くて複雑

forやifが深く深くネストした、長い長い巻物のようなメソッド、ローカル変数に何度も再代入を行う……そんなコードを平気で書けるプログラマ……を大量に雇って何十万行ものコードを納品する開発ベンダー。オブジェクト指向とか、ドメインモデルとか、いやこれからは関数型だとか……それ以前の構造化すらできない人たちが寄ってたかって作り上げたプロダクトコードからはもはや腐臭しかしません。

データモデルがいけてない

業務システムは、データのライフサイクルや整合性が命です。項目のまとまりや状態遷移を塾考してデータモデルを構築していないとソースコードの複雑化を招き、保守不能に陥ります。

CRUD情報もドキュメントとして整備しておきましょう。データがどの画面の処理で更新されているのか全然わからない……と思ったら、夜間バッチでしれっと更新されていた……こういうのは気づくのに時間がかかります。

実行時の情報が少ない

キー項目など常識的に考えて必要なログを出力していない、どこかで例外を握りつぶしているなど。障害調査上深刻な障壁となります。

アーキテクチャ違反

そもそもアーキテクチャがないっていうケースもままありますが……。アーキテクチャ、コーディング規約の遵守というのは、規模が大きくなるほど効いてきます。大量のコードの森を彷徨う保守メンバーにとってこれらは大切な地図なのです。業務ロジックがプレゼンテーション層に大量に書かれている、変数名が意味不明……そんなコードで動いているシステムはいくらでもあります。⁠動けばいいじゃん」という考えの人はプロダクトコードを書いてはいけません。

おわりに

ソフトウェア開発では、発生したバグをつぶすだけでなく再発防止が求められます。原因分析、作業手順見直し、ログの見直し、プログラム構造の見直し、インシデント管理ツール[3]への登録などが必要となるでしょう。

トラブル発生後の対応はもちろん大切ですが、発生リスクをコントロールすることの方が効果大です。ソフトウェアの複雑性を軽減するためのモジュール化、モジュール間の依存関係の単純化、複雑な対象を分割して統治すること。これを日々の開発・保守で実践していくことでリスクが軽減され、迅速な対応が可能になります。

ソフトウェアの要件が高度化し開発スピードが求められる昨今、テストフェーズで品質を担保するという考え方から、製造工程で品質を作り込むというマインドに切り替えるべきなのです。

本稿はケースの羅列になった感がありますが、これからソフトウェア開発・保守をしていくみなさんにとって少しでも参考になれば幸いです。

Software Design

本誌最新号をチェック!
Software Design 2022年9月号

2022年8月18日発売
B5判/192ページ
定価1,342円
(本体1,220円+税10%)

  • 第1特集
    MySQL アプリ開発者の必修5科目
    不意なトラブルに困らないためのRDB基礎知識
  • 第2特集
    「知りたい」⁠使いたい」⁠発信したい」をかなえる
    OSSソースコードリーディングのススメ
  • 特別企画
    企業のシステムを支えるOSとエコシステムの全貌
    [特別企画]Red Hat Enterprise Linux 9最新ガイド
  • 短期連載
    今さら聞けないSSH
    [前編]リモートログインとコマンドの実行
  • 短期連載
    MySQLで学ぶ文字コード
    [最終回]文字コードのハマりどころTips集
  • 短期連載
    新生「Ansible」徹底解説
    [4]Playbookの実行環境(基礎編)

おすすめ記事

記事・ニュース一覧