みなさん、こんにちは。
今回はデバッガを簡単に紹介して ブレークポイントの概念と
Pharo での色々なブレークポイントを 説明します。
システムは生きていて
システムや
システム中のオブジェクトと 対話することを学びます。
ソースコードを扱うのではなく オブジェクトを扱います。
オブジェクトには状態があり メッセージを送ったり受けたりします。
デバッガを使うことを 怖がらないでください。
デバッガでコードを書いたり 動いているプログラムをインスペクトしたり
強力で本当に「使える」ツールです。
デバッガ上で直接開発する開発者を
自分も含め何人も知っています。
コードブラウザ以外にも 膨大な量のコードが
デバッガ上で書かれています。
その利点は コードを書いている時に
メソッドのコンテキストや オブジェクトや変数にアクセスできる点です。
そういったことを見たり 試行したりすることができます。
コードを書いている時に 全てのデータを渡して
テストすることができるのです。
デバッガはこんな表示になっています。
タイトルバーがあって エラーメッセージを表示しています。
スタックがあります。コールスタックです。
メソッドを呼ぶスタックです。 ここを見ると
この performTest メソッドは testSumming メソッドを呼んでいて
それが + メソッドを呼んでいます。
その + メソッドが doesNotUnderstand:を発生させています。
ここで選ばれたメソッドの コードがここに表示されます。
ここで DiceHandle クラスの + メソッドが選択されています。
それでそのコードが下側に表示されています。
一番下の部分には 色々な変数があります。
この実行中のコンテキストで
アクセス可能な変数全てです。
変数を変更したり
そのオブジェクトをインスペクトしたり できます。
ここに一連のアクションがあります。
メソッドの再実行をしたり 呼び出し先に潜り込んだり
何が起こっているのか1行ずつ見たり することができます。
デバッガが開いた時 それを閉じても何も解決しません。
デバッガを開いて
何が問題を起こしているのか 詳しく中を見る方がずっと簡単です。
デバッガでコールスタックや
オブジェクトを精査して 問題を修正するほうが
デバッガを閉じてから原因を 推測するよりずっと簡単です。
デバッガはともだちです。
デバッガを使ってコンテキスト中の オブジェクトや
インスタンス変数などと対話します。
変数の状態をチェックしたり あるいは修正してしまったりします。
オブジェクトの状態をチェックするために メッセージを送ったり
どう反応するのかをチェックします。
もちろんコールスタック上のメソッドを 修正してセーブして
新しいコードで実行を継続できます。
最初から再実行することなく。
メソッドが失敗した時に そのメソッドを修正して
そのメソッドを再実行して プログラムは実行継続します。
とてもよく使われる
デバッグ手法に
コンソールに表示する というものがあります。
それは実際には
デバッグ手法としてはとても残念なもので
トレースしたい全てのメソッドを修正して 問題が修正されたら再び
全てのトレースを取り除かなければなりません。
その上、問題がどこにありそうか
どこから問題が入り込んでくるのか およその見当がついていなければ
トレースとしてどこで何を表示するか 決められません。
もう1つの方法にブレークポイントがあります。
ブレークポントは次に通過する時に
実行を停止するように Pharo に 指示するコードです。
最も簡単なブレークポントは Halt now です。
Halt クラスに now メッセージを 送ります。
すると直ちに実行を停止します。
ここからデバッガが開きます。
何が起こるのか1行ずつプログラムの状態を 見ていくことができます。
つまり Halt now はプログラムを 一時停止させます。
再実行することもできますが 当面は一時停止しています。
そしてアプリケーションの現状態で デバッガを開きます。
Halt now はとても良いのですが
システムにより実行されるものも含めて
定常的に実行されるメソッドに置いてしまうと
デバッガが何十個も開いてしまう ことになります。
Halt now をデバッガを開く時に
使われるコードに置いてしまうと
デバッガを開こうとした時に
それ自身が Halt now を実行してしまい また別のデバッガを開くことになり
ということが繰り返され システムを止めてしまいます。
この場合、 Halt once を使います。
Halt once は一度実行されたら 実行を停止しますが
それ以降は何度実行されても 実行を停止しません。
Halt once はコードのどこにでも 置くことができます。
一度だけ実行されて
デバッガーを開いて
すぐに無効になります。
もう1つの方法は一定の回数の実行後に 停止することです。
例えば 10 回繰り返された後で停止すれば
あるコレクションの10個目の要素に 何かある場合に
それまでの 9 回は
デバッガを開いても無駄なわけです。
なので 10 回目に停止したいわけです。
あるいは特定の条件を満たす時だけ
停止することも考えられます。
Halt if: は
メソッド名のシンボルが引数の場合には
コールスタック上にそのメソッドが ある場合にデバッガを開きます。
つまり、Dice>>faces のコードに Halt if: #printString を入れると
Dice>>faces が
printString メソッドから 呼ばれている時だけ
ブレークポイントが
働いて、プログラムを一時停止させます。
if: は引数としてブロックを取ることもできます。
ブロック内のコードが
true の場合だけプログラムを一時停止して
デバッガを開きます。
Pharo ではテストもコールスタック中の メソッドなので
テストから実行された時だけ
一時停止することができます。
now、once、onCount:、if: といったメソッドはどれも
Halt クラスのメソッドです。
コードを勉強して どうやって実装されているか見ることができます。
そして自分のメソッドを追加して
自分にとって必要な独自の ブレークポイントを作ることもできます。
下の例では
between:and: というブレークポイントを 実装しました。
minTime から maxTime までの間だけ
プログラムを停止させるものです。
つまり正子から午前2時までの間だけ
プログラムを停止させて デバッガを開きます。
デバッガはとても強力なツールです。
システムで沢山のブレークポイントを 定義していますが
必要なだけ追加することができます。
ブレークポイントを使うと メソッドを変更してデバッガを開いて
何が起きているのか1行ごとに 見ていくことができます。
ブレークポイントは本当に強力です。
ブレークポイントやデバッガを使う ことを躊躇しないでください。