デバッグ:
Max パッチのデバッグに関するTips

バグを捕える

Max でプログラムを書く場合、時としてミスを犯すことがあるかもしれません。その場合、なぜ意図したようにパッチが動かないかを見抜く必要があります。ある場合には、バグはプログラムの設計のコンセプトの中のエラーによって生じます。これは、コンピュータに行なわせたい動作に関する単純なミスかもしれません。別のバグは、オブジェクトの動作の誤解、オブジェクトが送受信するメッセージの予測のミス、メッセージが送信される順序の分析の誤りといったような Max に特有の構文のエラーかも知れません。Max はこのような構文エラーを極力防止するために、様々な分析やプログラムのデバッグに関する手段を提供します。この章では、Max パッチのバグを防ぎ、そして根絶するために、いくつかのアドバイス(そしていくつかのツール)を提供します。

プログラムの計画

Max の最も良い点の一つは、その場でプログラムを作ることができることです。結果について明確な考えを持たなくても、オブジェクトとオブジェクトを接続し、いろいろと試してみることができます。このことは、作業を行なう上で非常に有効な方法であり、結果として興味深く新しいアイデアをもたらす可能性を含んでいますが、一方で悪名高い Max の「スパゲッティ・パッチ」となってしまうこともしばしばあります。


パッチコードの「スパゲッティ」は、多くの場合、計画の無さを示すものです

このパッチは、きちんと組織化されたパッチとほとんど同様に動作しますが、ここで何がおこなわれているかを分析したり、このようなパッチの中のバグを探すことは、間違いなく困難です。パッチが正しく動作することを確認したいならば、Max で実行する前に、概念的な計画を立てておくことが最も良い方法です。

注意深い計画があり、プログラムに行なわせたいことが正確にわかっていると思えるような場合でも、Max でパッチを書き始めることによって、最初に考えたものより複雑な問題が発見されることがあります。例えば、1つの計画が、ある場合には適当なものであっても、他の場合には適当でないことがあります。次の例は、入力された MIDI ノートのベロシティを変更し、それを別のポートから送信するものですが、これには問題点があります。一見したところ、これは理にかなったパッチのように見えるかも知れません。しかし、これは多くの場合誤動作を起こします。この問題点を分析し、良い解決方法を考えられるでしょうか。


このパッチにはバグがあります

加算する値 が 0 の場合には、もちろん問題はありません。しかし、このパッチを誤動作させる方法が3つあります。最初の問題はそれほど深刻ではありません。それは、noteout オブジェクトが中央インレットにで受信したベロシティ値を0 〜 127 の有効な範囲に、自動的に制限するためです。2番目の問題は、+ オブジェクトから出力される値が常に 0 より大きくなるように制限することによって簡単に解決できます。これは、例えば maximum 1 オブジェクトを使えば可能です。実際、値がナンバーボックスを通過するようにしておき、ナンバーボックスの minimummaximum の値の両方を(ナンバーボックスを選択して、Object メニューから Get Info... コマンドを選んで)設定することによって、値の最大値と最小値を制限することができます。この方法は、実際にどのような値のベロシティが送信されているかを見ることができるという利点も持っています。


バグ No.2 を Fix したもの                         バグ No.1 とNo.2をFixしたもの

3番目の問題は、ベロシティ 0 を特別な場合として考えることを怠ったために起こるものです。このベロシティ 0 は、他のベロシティの値とは全く別に取り扱う必要があります。実際に、0 のベロシティ値は変更せずにそのままにしておく必要があります。次の例は0以外の値を持ったベロシティだけを + オブジェクトに送るという方法よってこれを実現する2つの可能性を示しています。


2通りのプログラムの正しいバージョン

ここで見てきたバグは Max の動作に関する誤解によって生じたものではありません。これらは、扱うタスクの計画を作る際のミスに関連したものです。Max はプログラムをこの種のエラーから完全に保護することはできません。ただ要求されたことを忠実に実行するだけです。このようなバグからプログラムを守る最も良い方法は、注意深くプログラム設計を行い、考えられる限りの可能性を試し、その後、Max で実装する中で設計が正しいかどうかを絶えずテストすることです。

開発中のテスト

小さいパッチのデバッグは、大きく複雑なパッチのデバッグに比べ、非常に簡単に行なうことができます。また、パッチのある部分が正確に動作することが確認できている場合には、大きく複雑なパッチのデバッグも非常に簡単に行なうことができます。パッチ開発の進行の中で、そのすべての段階でテストを実行して下さい。通常期待されるようなメッセージだけでなく、極端な、通常はありえないようなメッセージを送信してみて、想像していない状況の中でもパッチが誤動作を起こさないかどうかを確認して下さい。プログラムの一部が正しく動作すると確認できたならば、その部分を別のファイルとして保存してカプセル化し、より大きなパッチのサブパッチとして使うこともできるでしょう。

メッセージの確認

プログラムのパッチコードをどのようなメッセージが通過しているかを確かめる良い方法がいくつかあります。これによって、思うような動作が行なわれているかどうかを確認することができます。メッセージを見る最も良い方法は、一時的にパッチ内に特別なオブジェクトを置き、それによって送信するメッセージを「インターセプト(傍受)」ことです。数値を見るためには、任意のパッチコードに対してある種の「盗聴」を行なうために、ナンバーボックスを使うことができます。ナンバーボックスを通過する数値は変更されませんが、通過時には数値がナンバーボックスに表示されます。

デバッグツールとしてのナンバーボックスには、いくつかの欠点があります。ナンバーボックスは単一の int や float を表示することはできますが、様々な値によるリストを表示することはできません。数値はそれを目視できないほどの速さで通過するかもしれません。同じ数値が続けて何回か通過した場合、ディスプレイ上でその変化を見ることはできません。さらに、新しい数値が表示されると、それまでの数値を見る方法はありません。

capture オブジェクトはこれらの問題をすべて解決してくれます。capture は数値と数値のリストを扱い、一度に任意の数の値を格納することができます。複数の数値を見たい場所の横に capute を接続し、そのオブジェクトボックスをダブルクリックすると、それまでに受信された数値が表示されたテキストエディット・ウィンドウが開きます。capture がデフォルトで保持する値の数は 512 ですが、このサイズはタイプイン・アーギュメントによって調整することができます。

他に考えられる capture の利点として、capture の編集ウィンドウから格納された数値をコピーし、他のファイルや table にペーストできるということが挙げられます。capture が数値の受信を続けている間であっても、編集ウィンドウに自動的に表示されるわけではありません。そのため、新しく受信した値が見たい場合には、編集ウィンドウを開きなおさなければなりません。

シンボル、数値、リストなどのあらゆるメッセージをを見るために、text オブジェクトを使うことができます。これは capture と同様な動作を行ないますが、利用できるメモリ容量はいくぶん制限されます。任意のメッセージを直接Max ウィンドウで見るためには、print を使います。print オブジェクトは受信したメッセージを理解しようとはせず、単にそのまま Max ウィンドウに表示するだけです。Max ウィンドウは新しいメッセージが表示される毎にスクロールし、前のメッセージを見るためにスクロールアップすることができます。 print の欠点は、メッセージの間隔に比べ、メッセージを表示してMax ウィンドウをスクロールするほうがより長い時間を必要とすることがよくあるため、表示が送れ、パッチのタイミングに影響を及ぼすということです。

いくつかのメッセージ、あるいは任意のメッセージが送られたかどうかを確かめることだけが必要な場合には、あらゆるメッセージを受信するたびに点滅する button を使います。

メッセージの順序

メッセージを誤った順序で送ることがバグの原因になることはよくあります。メッセージの順序の基本的な法則を覚えておくことは重要です。これは、パッチを正しく書く手助けとなります。

「右から左へ」という順序 (right-to-left order) を無視することは、次の例のうちの1つのようなバグをもたらします。ここでは、中央の C から上の音のベロシティの値を減らすことを意図しています。しかし、左のパッチでは、ピッチの値より前にベロシティの値が notein から出力され、/ オブジェクトは左インレットで受信するメッセージによってトリガされるため、ピッチの値が if オブジェクトをトリガするタイミングはあまりにも遅すぎます。

右のパッチでは、ピッチの値を受信するまで、ベロシティの値が if オブジェクトの右インレットに格納されます。このため、パッチは正しく動作します。


画面上のオブジェクトの位置がパッチの機能に影響を及ぼす可能性があります

左のパッチでは、>> 4 オブジェクトと & 15 オブジェクトは完全に垂直に整列しています。したがって、>> 4 オブジェクトが最初に入力値を受け取ります。その結果、packオブジェクトは右インレットに数値が送信される前にトリガされます。右の例では、このパッチは、単に & 15 オブジェクトを数ピクセル右に移動しただけでデバッグが行なわれています。Max メッセージが送信される場合、「右から左」(right-to-left)、そして「下から上」(bottom-to-top)という順序で行なわれることを知らなかった場合、オブジェクトを 1 ピクセル移動させることがパッチの動作を変えてしまう可能性があるという事実に悩まされるかもしれません。しかし、これらの順序づけの原則を覚えていれば、メッセージが送信される正確な順序がひと目でわかるでしょう。

メッセージのトレース

複雑なパッチを開発している場合、(それまでに起こったことを記憶し、サブパッチへ出入りするなどの必要があるため)一目でメッセージの順序を分析することは難しいかもしれません。幸いにも、Max にはメッセージのトレースを行なう機能があり、メッセージが送信されようとしているパッチコードを点滅させることによって、メッセージの順序を示してくれます。

Trace メニューから Enable コマンドを選ぶと、Max のメッセージトレース機能が有効になります

注:Options メニューで オーバードライブ(Overdrive)が使用可になっている場合、メッセージのトレースは使用できません。また、メッセージトレースがオンになっている場合には、オーバードライブを使用可にすることはできません。

その後、MIDI イベントや、コンピュータキーボードのキーストロークによる入力、マウスによるユーザインターフェイスオブジェクトのクリックなどにより、パッチをアクション状態(メッセージが送信される状態)に設定します。Max は、送信されようとしているメッセージが通過するパッチコードを点滅させ、送信されたメッセージとその送信元と受信先となるオブジェクトに関する情報をMax ウィンドウに報告します。

進行中の個々のポイントで Trace メニューから Step を選ぶたびに、Max は次の送信メッセージに移行し、それが通過しようとするパッチコードを光らせて、それを Max ウィンドウに報告します。この方法では、自分のペースで、段階を追ってパッチを動作させることができます。

別の方法として、Trace メニューから Auto Step を選ぶこともできます。これにより、Max は様々なメッセージを一定の適度な速さで段階的に送信し、その進行と共に報告を行ないます。Trace メニューから Continue を選んだ場合、Max はフルスピードでトレースを続行します。

メッセージのトレースを行なう前に、(パッチャーウィンドウがアンロック状態のときに) 1つ、あるいは複数の特定のパッチコードを選択し、Trace メニューから Set Breakpoint を選ぶことができます。これによって、指定されたパッチコードの 1 つをメッセージが通過するたびにトレースが一時停止されます。この方法では、Continue コマンドを使ってメッセージをフルスピードで通過させ、ブレークポイントとして設定したパッチコードをメッセージが通過しようとするときに Max が停止するため、その瞬間のパッチの状態を調べることができます。

エラーメッセージ

プログラミングエラーがあった場合、Max は通常そのエラーに関するメッセージを Max ウィンドウで示してくれます。パッチャーウィンドウを編集している間に多くのエラー(例えば、存在しないオブジェクトをパッチに置こうとした場合など)が報告されますが、他のエラー(例えば、特定のメッセージを理解できないインレットに対して、そのようなメッセージを送信している場合)は、実際にプログラムを実行するまで明白にはわかりません。エラーメッセージのリストや、それらのエラーメッセージが起こりそうな原因、その可能な解決方法については、Max チュートリアルや、Max トピックスマニュアルの 「エラー」の章に書かれています。

訳注:原文では "Tutorials and Topics Manual" となっていますが、現在のバージョンでは「チュートリアル」と「トピックス」は別マニュアルになっています。

コメント

プログラムにコメントが多すぎると文句を言うプログラマはいないでしょう。comment オブジェクトの中の注記は、パッチを理解しようとする場合の助けになり、また、後になってパッチを見た時に、パッチがどのようなことを行なっていたかを思い出すための助けになります。「なぜプログラムをそのように書いのか」という理由は、驚くほど早く忘れてしまうものです。自分自身への注記を書いておいたり、将来の参考のためにアイデアを書きとめておくために、テキストウィンドウを使用したいと思う場合さえあるかもしれません。

パッチコードやオブジェクトに色をつけることも、パッチに対する1つのコメントの形となりえます。例えば、パッチ全体を通してMIDI 情報が流れるオブジェクトや接続すべてに特徴的な色を使って目印をつけ、ユーザインターフェイスを扱うオブジェクトや接続から区別することができるでしょう。パッチコードやオブジェクト上で [Control] + クリックしてコンテキストメニューを表示させ、その Color サブメニューから色を選ぶことによって、簡単にパッチコードやオブジェクトに色をつけることができます。

参照

効率化 プログラミングスタイルの問題
カプセル化 パッチはどの程度のことを行なわなければならないか
エラー エラーメッセージの説明