設計しよう
Insider.NET 掲示板で、投稿の分類わけをするお仕事をさせていただいている関係で、すべての投稿に目を通しています。週に70~80の新規投稿を読んでいて思うのですが、「設計していたら、問題になっていないんじゃない?」という質問があります。っていうか、設計の仕方を知らない?設計しましょうよ...
「設計」には、色々な設計があります。顧客の「こんなことがしたい」というのをまとめ、どんな機能が必要かを設計する、「システム設計」。その機能が、それぞれどんな働きをするのかを設計する、「機能設計」。場合によっては、各機能がどの様な画面を持っており、それぞれのエレメントがどの様なアクションを行うかを設計した、「詳細設計」。おおよそ、プログラマに渡ってくる設計は、ここまでではないでしょうか。しかし、この設計でプログラムを書く(ここでは、極狭く定義)ことができるかというと、まず不可能です。プログラムを書くためには、そのアクションを行うために何が必要で、どの様な順で、どの様なことを行うのか、設計する必要があります。
設計を行うのは、やらなければならないことを整理するためだけではありません。やらなければならないことが網羅されているか確認する、という目的もあります。また、不具合が発生した際、どこで何が間違っているのかを容易に発見する手がかりともなります。それだけではなく、設計が記録として残っていて、正しくメンテナンスされていれば、他の誰かが作ったプログラムをメンテナンスすることも容易になります。
コーディング工程に来る頃にはすでに遅延が生じていて、ドキュメントを作っている時間なんかない!!というのもわかります。でも、バグがでて、考え込んで、いつ返事が来るかアテに出来ない掲示板に書き込んでいる時間があるなら、ちょっと考え直してみませんか?問題が出てからでも遅くはありません。そこはどの様に動かなければならないのかを設計し、今どの様にコーディングされているのかを逆設計します。その2つの設計を見比べれば、問題解決へグッと近づくでしょう。
デバッグしよう
同じように、「デバッグしたらすぐに解決するんじゃない?」ってのも、しょっちゅう見かけます。というか、デバッグの仕方を知らない?デバッグしましょうよ...
デバッグ工程は、システム開発工程で、大変長い生存期間を持っています。というか、プログラムが出来たら、システムが破棄されるまで、ずっとデバッグ工程といってもいいかと思います(嫌だけど)。デバッグの仕方を憶えましょう。
以下、シングル スレッド アプリケーション(明示的なマルチ スレッド化をしていないアプリケーション)の場合における、デバッグのコツを記します。マルチ スレッドの場合はそのあとに記しますが、シングル スレッドの場合とほぼ同様です。マルチ スレッドの時に注意が必要なものについては、リスト マークを四角にします。
- エラー メッセージに注意する
比較的新しい処理系では、エラー メッセージには「エラーになった理由」と、「その対処方法」が書かれています。エラーになった(例外が発生した)事だけに注目せず、なぜエラーなのか、メッセージには何をするように書かれているか、よく注意しましょう。
- ブレーク ポイントを使う
適切な箇所にブレーク ポイントを設置します。適切な箇所とは、期待通りにならない値が変わる前後、例外が発生する1ステップ以上手前、ここまでは正常に実行されていると判断する最後のステップ、など、デバッグの対象がはっきりわかるところをいいます。最近のデバッガは、ブレーク ポイントで止まるタイミングを指定できます。100回ループの50回目だけがおかしいなどの場合、50回目の実行で停止する、という指定が出来ます。この機能には副作用があって、実行しようとするごとに条件チェックを行いますから、処理が非常に重くなります。
- ステップ実行を行う
たいていのデバッガには、1ステップ(1行)ずつ処理を実行する手段が提供されています。これを利用して、期待通りにならない箇所を特定します。このとき、ステップ実行しながら「値の検査」を利用して、期待している値とどう違うのか、調べます。なお、ステップ実行には、ソース上の1命令ずつ実行するものと、メソッドの場合はそのメソッドのなかの次のステップで止まるものの2種類あるのが不通です。メソッドの前後できたい通りの結果が得られない場合は、メソッドのなかに入るを使用するなど、使い分けます。
- 値を検査する
ほとんどのデバッガで、停止中に変数の値を表示することが出来るようになっています。この機能を利用して、処理がどこまで期待通りに進んでいるか、確認します。ただし、この機能をメソッドに適用するときには、注意が必要です。メソッドが実行されることになるので、他の数値に影響を与えることがあります。
- 実行経路を確認する
プログラムは普通、上から下へ順番に実行されます。しかし、条件分岐やループ、gotoなどのジャンプ命令によって、実行される順番が変わります。これらの命令に与える判断文によっては、意図しない結果になることがあります。例えば、C 言語と VB 系を行ったり来たりしている人にとって、比較演算子はよく間違えるのではないでしょうか。ステップ実行や値を検査することで、意図通りに実行されているか、確認します。
- 呼び出し履歴を見る
実行経路を確認するのひとつですが、メソッドの呼び出し履歴も注意します。これは、メインメソッドから始まって、どのメソッドから呼び出されているかを確認できます。Windows プログラミングにおいて、イベント処理はなくてはならないものです。変更をきっかけとするイベントは、UI による変更だけがきっかけではありません。このことを失念し、プログラム上で書き換えた事によりイベントが励起し、予定外の結果を生み出すことがあります。この場合、呼び出し履歴を見ることで、何が原因で呼び出されたのかを確認することが出来ます。
- トレースログを仕込む
昔、デバッガを使えなかったり、GUI 環境でなかったとき、プログラム中に「どこまで実行したか」を書き出すトレースログを仕込み、エラーが発生する箇所を特定したり、条件を探ったりしました。9600bps のモデム経由で、DOS から UNIX へログインしてデバッグ、なんて事もあったんですよ。この方法は、マシンリソースが贅沢になった今でも有用です。
- 例外構文を使う
例外構文がサポートされている場合は、積極的に使いましょう。まず、ステップ実行でエラーになる箇所を特定します。次に、その箇所を例外構文で囲みます。例外を受けるブロックにブレークポイントを貼り、実行します。生成された例外情報から、何が発生しているのかを読み取ります。デバッグ作業が終わったら、例外構文は取り除いておきます。→NAL-6295の舌先三寸:「[.NET][ASP.NET]むやみにキャッチしないでね。ゴールキーパー以外はハンドで反則ですよ。」
- まず、自分を疑う
よく、「製品のバグでしょうか」という質問を見かけます。製品にもバグはあるでしょう。しかし、十分にテストされ、多くの人が使っている製品にバグがあることを疑うより先に、自分が今作ったプログラムにバグがあることを疑うべきではないでしょうか。「自分は間違っていない」という思いこみは、間違いを間違いとして見せてくれません。または、「このように動くはず」という思いこみが間違っているかもしれません。1ステップずつ丁寧に、「どの様になるか」を考えながら、追いかけていきます。
マルチ スレッド アプリケーションにおける、デバッグのコツを記します。
ほとんどの場合、シングル スレッドと同じですが、「同時に同じような処理が複数実行されている」ことに、注意する必要があります。また、処理系やデバッガによっては、特定のスレッドだけをデバッグの対象と出来る場合(他のスレッドは処理が続行する)と、すべてのスレッドが止まる場合、あるいはその両方を切り替えられる場合があります。VisualStudio.NET で Web アプリケーションをデバッグする場合、通常Web アプリケーションはマルチスレッドで実行されますが、設定によってシングルスレッドで実行されるように出来ます。
- シングル スレッドで十分に検査する
マルチ スレッド アプリケーションは、同じ処理を複数のスレッドに分けて行うものと、別々の処理を並列に分けて行うもの(実行スレッドと ユーザを待たせる表示をするなど)、に大別できます。どちらの場合でも、それぞれの処理が単独で実行できることを十分に確認します。単独で実行できないものが、複数で実行できるわけがないからです。ここで、チャット プログラムなど、複数が実行されていないと意味をなさないものもありますが、少なくとも単独で実行される部分は、チェックしておきます。
- ロック期間を検証する
データベースへのアクセスや、シングル インスタンスの変更など、他のスレッドの実行に干渉するようなロックを行っている場合、そのロックが出来る短時間かつ少ない回数になるように設計されているか、検証します。ロックする箇所が分散していると、デッドロックを起こす可能性があります。また、ロック期間が長くなると、全体的なパフォーマンスが低下します。ロックしなければならない機能を検証し、短い時間で効率よく行います。
- トレース ログを仕込む
トレース ログを仕込む場合、どの様な処理をしているスレッドなのかを、ログに記録します。データ処理プログラムの場合、特異なデータを処理できないでエラーが発生する場合がほとんどです。どの様なデータを処理していたのかがわかれば、それに絞ってデバッグ対象に出来ます。わからなければ、いつまでもデータを眺めていることになります。
- ブレーク ポイントを使う
トレース ログで、対象となるべきデータを特定したら、ブレーク ポイントを設定します。このとき、1スレッドのなかで何度も止まるところにブレーク ポイントを設定するのではなく、1回しか実行されないところに設定するようにします。デバッグ対象のスレッドを絞り込めるなら、絞り込みます。
2006/02/11 マルチスレッドのデバッグを追加
投稿日時 : 2006年2月2日 21:17