チュートリアル 14:
カプセル化

イントロダクション

このチュートリアルではMaxにおけるカプセル化の概念について説明します。カプセル化を行なうと、パッチのセクションを、patcher オブジェクトを使って作られるサブパッチの中に置くことができます。これにより、パッチの中でこれ以上触れる必要がないロジック(プログラムの中の論理構造)の部分を隠すことができるため、プロジェクトをより見やすく、簡潔なものにすることができます。ここでは、オブジェクトによるパッチの作成だけでなく、これ以上触れる必要がないパッチの一部をカプセル化するための編集ツールの使用についても調べます。

パッチファイルを簡潔で、読みやすく、容易にメンテナンスできるようにしておくためには、Max のロジックを適切にカプセル化することが重要です。カプセル化されたロジックは容易に編集することができます。また、これだけを切り離して別ファイルとして保存し、他のパッチで再利用することも可能です。

基本的なカプセル化

チュートリアルを開いて下さい。

チュートリアルの左上には、2つの小さなパッチがあります。この2つは、「入力された値に5 を加える」という同じ処理を行なっています。左側のパッチは、+ オブジェクトを使ってこれを実行しています。それに対し、右側のパッチでは patcher オブジェクトを使っています。patcher オブジェクト(このオブジェクト名は、"p" という形に省略することができます。trigger の多くが "t" という形に省略できることと全く同様です)は、文字通り、カレントのパッチに埋め込まれた別のパッチです。patcher オブジェクトの内容を見るためには、(パッチがロックされているときに)patcher オブジェクトをダブルクリックして、カプセル化されたパッチャーオブジェクトのウィンドウを開きます。

patcher add5 オブジェクトをダブルクリックすると、小さなパッチャーウィンドウにその内容が表示されます(このウィンドウには、サブパッチの名前 add5 が表示されます)。これは3つのオブジェクトしか持たない簡単なサブパッチです。中央にあるオブジェクトは、明らかに + オブジェクトで、これが加算を行なっています。+ オブジェクトの上下にあるオブジェクトは、それぞれ inlet、outlet というオブジェクトです。inlet オブジェクトは、これが置かれたpatcher オブジェクトにインレットを作ります。これに対し、outlet オブジェクトは、これが置かれた patcher オブジェクトにアウトレットを作ります。これを使うと、patcher オブジェクトに、Max に組み込まれているオブジェクトと非常に良く似た動作をさせることができます。複数のinlet、outlet オブジェクトを使った場合、置かれているpatcher オブジェクトに対応したインレット、アウトレットを作成します。patcherオブジェクトのインレット、アウトレットの配置は、サブパッチ内のinlet、outlet オブジェクトの空間的配置と関連づけられます(例えば、最も左にあるinlet オブジェクトは、patcherオブジェクトの左端のインレットに対応します)。

inlet、outlet オブジェクトを使用する場合、これにアシスタンスを追加すると便利です。これにより、サブパッチを持つ patcher は、インレットが予期しているメッセージ型や、アウトレットが出力するメッセージ型に関する有益な情報を表示することができます。inletやoutletを選択して、オブジェクトのインスペクタを開くと、利用可能なコメントフィールドがあることがわかります。このフィールドに入力したテキストはすべて、パッチの編集時に patcher オブジェクトのアシスタンスとして表示されます。

カプセル化の実行

時として、ロジックを配置してしまった後でサブパッチを作る必要が生じることがあります。あなたのパッチが当初考えていたものより大きくなってしまった場合、あるいは最初は考えていなかったロジックを追加してしまった場合、おそらく、パッチはより複雑で見にくいものになっていきます。このような場合、オブジェクトのグループを選択して、それを直ちに1つのカプセル化された patcher に変換することができると便利です。これは、Encapsulate というメニュー項目を使って実行することができます。

チュートリアルパッチでは、面白い描画アルゴリズムを使っています。パックを矩形領域の中で動かすと(pictslider というオブジェクトを使って)、パッチの下部にある lcd の中のほぼ同じ位置のあたりの領域で小さい円がランダムに描画されます。lcd をクリアする必要がある場合には、スペースバー(スペースバーのASCII値は32で、keyオブジェクトによってキャプチャされ、seletc オブジェクトによってclear メッセージがトリガされます)を押して下さい。このロジックはかなり乱雑になっています。そして、スクリーン上に広がっていますが、それで見やすいというわけではありません。このロジックの大部分を選択してサプパッチの中にカプセル化してみようと思います。

2つのコメントボックス("encapsulate from here" と "to here")があるので、これを使ってカプセル化するロジックを選択しましょう。パッチをアンロックして、その後、(ドラッグによって)2つのコメントボックスの間にあるオブジェクとその右側にあるオブジェクトをすべて選択して下さい。15個のオブジェクトが選択されます。Edit メニューから Encapsulate を選ぶと、先ほどのロジックがすべて、1つの名前を持たないpatcher オブジェクトに包み込まれることがわかるでしょう。パッチをロックして、このpatcher オブジェクトをダブルクリック(あるいは、アンロック状態のパッチでは [Command] + ダブルクリック)すると、サブパッチが開き、再びすべてのオブジェクトを見ることができます。このサブパッチは4個のinlet オブジェクトと1個のoutler オブジェクトによってサブパッチの外の世界と結ばれています。何らかの理由で、後になってからこの処理を元に戻す必要がある場合には、Edit メニューの De-encupsulate コマンドを使うと、サブパッチをメインパッチに戻し、すべてを元の通りに正しく再接続します。

多くの場合、patcher オブジェクトに名前をつけておくと便利です。これにより、特にパッチに値が付け加えられるわけではありませんが、あなた(または他のユーザ)がオブジェクトの中にカプセル化されているロジックを理解する手助けとなります。名前を付けるためには、オブジェクトの中でクリックして、任意の名前を最初のアーギュメントとして追加します。この例の場合、draw_logic というような名前ならば、とても役に立ちます。

独自のサブパッチの作成

サブパッチの中で行ないたい処理が先にわかっている場合、patcher オブジェクトを作って、そのエディタウィンドウの中で作業をすることは簡単です。左下には、どこにも接続されていない2個のナンバーボックスがあります。ここにサブパッチを作り、そのサブパッチを使って1つの値を、他の値に変換してみましょう。

2つのナンバーボックスの間の何もない場所をダブルクリックし、オブジェクトボックス(パレットの左上にあります)を選んで、新しい空白のオブジェクトを作って下さい。この新しいオブジェクトボックスの中に、p mycalc と入力して下さい。これで mycalc という名前の新しい patcher オブジェクトが作成されます。patcher オブジェクトを作ると、このサブパッチを編集するための、新しいウィンドウが現れます。まず、inlet と outlet を配置します(どちらもオブジェクトパレットから選ぶことができます)。サブパッチに inlet と outlet を追加すると、メインウィンドウの patcher オブジェクトにインレットとアウトレットが追加される点に注目して下さい。次にinlet と outlet を直接接続します。これによって、入力されたメッセージをそのままアウトレットから出力する以外何も行なわない "thru"(通過させるだけの)オブジェクトが作成されます。このカプセル化をメインパッチウィンドウでテストしてみましょう。

mycalc という patcherオブジェクトにはインレットとアウトレットができたので、これをナンバーボックスと接続することができます。上のナンバーボックスを patcher のインレットに、patcher のアウトレットを下のナンバーボックスに接続して下さい。パッチをロックして、上のナンバーボックスの値を変更して下さい。下のナンバーボックスの値も変化することがわかるはずです。これは驚くにはあたりません。このpatcher オブジェクトは2つのボックスの間の直線(パッチコード)をカプセル化したものです!

patcher 編集ウィンドウに戻って、ロジックを追加しましょう。ウィンドウが閉じていたら、patcher オブジェクトをダブルクリックして再度ウィンドウを開き、このウィンドウをアンロックして下さい。最初に、inlet と outlet を接続しているパッチコードを選択し、削除します。計算部分を追加しましょう。2つの新しいオブジェクト + 50 オブジェクトと / 7 オブジェクトを作って下さい。inlet を + オブジェクトに、+ オブジェクトを / オブジェクトに、/ オブジェクトの出力を outletに、それぞれ接続して下さい。これで mycalc というカプセル化は無意味なサブパッチから 「(入力 + 50)/ 7 」という計算を実行するパッチに変わりました。このように、カプセル化された中で作業を行うことの優れた点は、トップレベルのパッチを何も変更しないで済むということです。すべての接続はそのままになっています。メインパッチでは、特別な変更を行なわなくても、上のナンバーボックスの値を変えると新しい計算結果が出力されます。

結び

パッチのロジックのカプセル化によって、2つのことが行なえます。
1. カプセル化によって、その中のすべてのオブジェクトと接することなく(または、見ることさえなく)、高レベルでの作業を行うことができます。さらに、
2. カプセル化によって、高レベルのプログラミングを全く変更することなく、低レベルのロジックを変更することができます。
patcher オブジェクトを扱う場合、通常のオブジェクトと同様に手動でpatcher オブジェクトを作り、それを編集する方法と、パッチにある既存のロジックを選択し、Encapsulate というメニュー項目を使って自動的にサブパッチを作る方法のどちらを使うこともできます。どちらの場合でも、高レベルのパッチに何も変更を行なわずに、サブパッチをさらに検討したり、パッチコードの変更を行ったりすることができます。

参照

patcher サブパッチを作ります
inlet サブパッチへのアクセスを可能にします
outlet サブパッチ内部からの送信を可能にします
pictslider 外観をカスタマイズできる1次元および2次元のスライダ