English
The original english version of this page is newer and may contain information this translation does not have! Click
here to view the english version.
このテキストは Sebastian Oschatz と Nils Buhlert が行った Node13 でのワークショップ「Software Engineering Patterns with vvvv」の内容を文書化したものです。
以下のリストは、vvvv の保守性と理解しやすいパッチを作成するためのパターンについて説明しています。
これらはパッチの成長とともに起きる様々な障害(保守不能に成長したパッチ、おかしな変更要求、非常識な納期)を観察し、長年の経験から見つけられたものです。
- 一度に考える事は6つまで
- スクロールは遅い
- アクティブなパッチとパッシブなパッチを分離しよう
- パッシブなグラフ
- グローバルグラフィクス
- 定数を焼き込まない。関係を隠さない
- 早く勧告する。そして思い出させる
- DebuggingDelay のための Delay
- S と R は気をつけて使おう
- 1つのパッチに1つの役割
- 基盤から作ろう
- バージョン管理を使おう(例えばGit)
- Git の変則性 / S と R の利点
- ピンに名前をつけよう
ワークショップに参加してくれた皆さんありがとう。
特に忘れていた事を思い出させてくれた Sebl, Sunep, Zepi, それらの内容もここに含まれています。
catweasel がワークショップのラフなビデオも投稿しています。 - http://www.youtube.com/watch?v=NKAFhMjKnn8
一度に考える事は6つまで
人の脳というのは一度に処理できる物事の数というのが決まっています。
例えば、ある物が何個あるか数える時、数量によって数え方が変わるでしょう。
例えば5個の物を数えるのであれば、数え上げなくても即座に何個あるか識別できます。
一方、例えば17個の物を数えるためには1から17まで脳内で数え上げる事でしょう。
さらに多くの物を数える場合は、メモを取ったりしながら数えないと何個数えたか忘れてしまうでしょう。
このように物の数によって、脳の使い方は変わってきます。
物を見る時にパッと見で識別できる、というのは最速の方法です。
何をすればいい?
- ロジック内の独立した処理は最大で6つのクラスタにしよう。超覚醒状態、非常事態の時には6以上のものを一度に把握する事も可能ですが、逆に寝不足などだと、1つか2つまで落ちてしまうでしょう。
- たくさんの物を一度に把握しようとして時間を浪費するのはやめましょう。
- すぐにツールを使用しよう。もしくはリファクタリグしよう。独立した機能をクラスタ化するために見やすい配置にしよう。
- ピンに名前を付ける事の力を知ろう。(後述)
- 出来るだけ頻繁にリファクタリングをして、サブパッチ、Automata、C# プラグインなどを使おう。問題の最も簡潔な表現を見つけるために。
- もしアルゴリズムをシンプルにできるノードを見つけた場合はすぐ使用しよう。
- いらないノードは常に削除しよう。Git を使えば後から復旧できます。
- テストされない特殊なケースのためのロジックを消そう。
- 不適切な状況のための時期尚早な最適化は止めよう。
- パッチを3から4つだけの機能のクラスタにするように努力しよう。タッチスクリーンが壊れていたり USB ケーブルが抜けている事を気遣うだけの脳のキャパシティを残すために。
- ペアプログラミング。二人のプログラマによる警戒は最初から優れたコードを作る。
理由
- デバッグに必要な時間は、脳のキャパシティに合わないパッチの場合10倍かかります。
- 直感的に理解できない場合、テスト環境を用意したり、ペンと紙を使ったり、話す誰かを見つけたり、TTY レンダラの出力を書いたりなど、ムダな時間が必要になってしまいます。
- 当然:8時間の睡眠はデバッグ時間を10時間から6分に短縮できます。
スクロールは遅い
- パッチは急速に大きくなっていきます。無限のワークスペースは無限のノードを配置できますが、あなたが一度に見れる範囲はその一部でしかありません。
- 一度に6つの事しか考えられない事を思い出して下さい。
何をすればいい?
- スクロールせずに各クラスタのノードを確認できるようにしよう
- スクロールする前にノード群をクラスタリングしましょう。多くの場合、単にノードを再配置するだけで驚くほど小さくなります。
- スクロールする前に、ウィンドウを最大化しましょう。ウィンドウを簡単に切り替えられるようにタブにしましょう。
- 大きなモニタを使おう。
- スクロールしたくなるという衝動は、サブパッチを作れという合図です。スクロールしたくなったらサブパッチを今すぐ作ろう。
- もし長い一連の処理を行う場合(例えば大きな入力を取る処理、出力する処理)には実はスクロールした方がパッチを切り替えるより早いです。そういった場合はライン(線のコメント ---- )を入れてパッチ内のエリアを分割しましょう。
理由
- 複雑なパッチを作る時はあなたの目の動きは非常に遅くなる。一度に全ての物を見る事が出来ない場合は、一度に全てを理解できないという事と同じ。だからサブパッチにする事を考えよう。
- 一次元のスクロールは、マウスのホイールを回すだけでパッチ全体を見渡せます。
X方向に伸びるパッチはジグザグやぐるぐるとスクロールしてみないと見渡せません。
もしかすると変な所にノードが隠れてしまうかもしれません。
アクティブパッチとパッシブパッチを分離しよう
実はノードメニューには書かれていないカテゴリがあります。アクティブとパッシブの違いです。
- パッシブノードの出力は常に同じフレームの入力のみから出力を生成します。時に純粋関数、ステートレスノードとも呼ばれます。
- アクティブノードの出力は過去の状況に依存しています。
アクティブノードの例は、LFO, Damper, Automata, S+H, Flipflop, Framedelay など Animation カテゴリの全てのノードです。
パッシブノードの例は、Quad, Mouse, +, Transform, RandomSpread, Renderer などです。
アクティブノードはパッチ全体をアクティブにしてしまいます。
何をしたらいい?
- パッチがアクティブかパッシブかを決定しよう。
- アクティブなパッチは一連のロジックを集め、出力が前のステップに依存します。
- パッシブパッチは物事を抽象化してくれます。例えば、グラフィックのレイアウト、サウンドエンジン、数学アルゴリズム、外部システム、レンダリングエフェクトなど。
- アクティブなパッチ内で複雑なパッシブなロジックを避けよう。それはサブパッチにリファクタリングできます。
理由
- パッシブパッチはデバッグが非常に簡単です。
- インタフェースが明確なパッシブパッチはよく再利用されます。
- 一方アクティブなパッチはデバッグが難しいです。デバッグのイテレーションに長い時間がかかってしまいます。
- アクティブパッチの一時的な動きを見るのに極度の注意が必要です。一時的な挙動は議論する事が難しいです。
- あなたの周りにある、簡単で、信頼できて、テストされたパッシブパッチは、アクティブなパッチをデバッギングするのにも使えます。
- パッシブパッチに隠されたステートは全ての状況を観測する事は難しいし、テストシナリオを再現する事が難しいです。
パッシブグラフィクス
何をしたらいい?
- パッシブパッチでは Damper, LFO, Monoflop, Automata を避けよう。ビジュアル出力をするパッチは特に。
- 親パッチから全てのアニメーションをコントロールしよう。
理由
- グラフィクスはパッシブな場合とてもシンプルにテストできます。アニメーションエフェクトをテストすることは手動で親パッチから持ってくるか、単純なLFOに接続すると簡単です。
- グラフィクス周りはノードが集中しがちです。なので出来る限りサブパッチを作りましょう。
- 複数のサブパッチのタイミングや速度の一括調整や、同期は簡単にできます。
- グラフィックモジュールはより一般的にして再利用できるようにシンプルにしましょう。
- グラフィカルなセンスのある人やシェーダ職人の手によって、グラフィックモジュールは存在するロジックを壊さずに奇妙にも綺麗にもなる。
グローバルグラフィクス
何をしたらいい?
- 常に1つのグローバルな Transform をグラフィクスパッチに持ちましょう。そして更なる Transform はそれの上からかけよう。
- 正確なビルボードやデザインをこのグローバル Transformation から導くよう努力する事。
理由
- これはグラフィクスモジュールを再利用するために唯一の方法です。
- 異なる画面サイズへの適応も簡単です。
- 一画面でマルチモニタ用グラフィックのテストができます。
- VNC / TeamViewer を経由して、グラフィックのバグをデバッグできます。
- 拡大して詳細を見れば小さい画面でもピクセルエラーなどが分かります。
定数を焼き込むまない。関係を隠さない。
IOBox で直接式を評価する事はクールですが危ないです。
独立して数値を抽出出来ないような物は”焼き込まれている”と言います。
何をしたらいい?
- 本物のプログラマは -1, 0, 0.5, 1, 2 だけを使います。
- パッチ内の定数は弱さの現れです。
- π はCircularSpread を知らない人の為にあります。
- 誰もが 1 で十分
- 本物のプログラマが他の値を欲しくなった場合は、入力値を使用して計算したり、カウントします。
- デザイナのみが定数を使う事を許されます。意図的にデザインのために色やサイズなどを変更するために定数を使います。
- 定数を二つの独立したパッチ間でやり取りするために使わないでください。(例えば二つのオブジェクトを並べたり)
- 常に関係したスプレッドカウントは一緒に繋げる。そしていつも存在する数から導く。
理由
- 値を変えたりがシンプルでクールな間は、秘密の公式やパッチに含まれる前提から求まる定数を焼き込んでも大丈夫。
- 焼き込まれた数値は関係性を隠します。それはどこか一箇所を変えた時に他の場所でのバグになります。
- それらの依存関係はプログラマの脳内だけに存在し、誰か他の人がパッチ内で新しい事をしようとした時には無くなっています。何が関係しているか書いた人には明確に分かるとしても。
- なので、そのパッチが再利用できるか疑念を持ちましょう。
早く勧告する。そして思い出させる。
vvvv 使いは早くプロトタイプを作る事に関してすばらしいですが、プロトタイプフェーズが終わった時にはプログラミングのやり方を変えなくてはいけません。
何をしたらいい?
- ハックには常にコメントを付ける。制限を説明する。
- テストされてるかどうか記す。もしくはどうなりそうか記す。
理由
- 将来変なコードを取り除く事を奨励してくれる
- 今1分使う事によって、将来の1時間のムダを減らせる。
DebuggingDelay のための Delay
vvvv において Framedelay は二つの役割を持っている。
- 主要な役割はフィードバックループを構築して、データフロー内での状況を操作するため。
- もう1つの役割は、何かしらの理由で動かないものを微調整するため。
何をしたらいい?
- 状態を操作したいのであれば FrameDelay は閉じたフィードバックループで使おう。
- 何かを直すためにそこかしこに FrameDelay を置きたくなるのを我慢しよう。Renderer (TTY) を使って根本的に何が起きているのか理解しよう。
- さらに悪いのは時間ベースの遅延を直したいという欲求です。遅延はある秒数で常に同じフレーム数で動くというのは保障されない事を思い出してください。
- もし何かが動くようになったなら、良くパラメタ化されたサブパッチに入れてみて、テストして変更が必要ないか確認してください。そうしてデバッグが完了です。
理由
- VVVV は素晴らしい。なぜなら全ての事が同じフレーム、同じ時に発生するから。それはデバッグにとても良い。しかし FrameDelay は最短のタイミングで発生するのでトリッキーです。
- VVVV は素晴らしい。なぜなら"見る"事が出来る。しかし FrameDelay は観察する事をとても難しくしてしまって、デバッグを難しくさせます。
S と R ノードは気をつけて使おう
S と R ノードは構造や関係を隠してしまいます。
何をしたらいい?
- S と R ノードはパッシブパッチでは使わない事。入出力を使い、S と R ノードはアクティブパッチに移しましょう。
- アクティブパッチが "S&R クリーン" かどうか決めましょう。S&R クリーンなパッチを書いている時は S と R を使いたくなる誘惑に負けないように。
- 小さいグローバルなレシーバのセットを定義するのはOKです。(例えばデバッグの為の標準イベント、Transforms など)
理由
- 色んなパッチからレシーブ(R)するパッチをデバッグする時には、色々な他のパッチを一度に開かなければならない。
- S と R はパッチ間を密にしてしまいます。それだと独立した再利用可能なモジュールは作れません。
- S と R を含んだパッチはペアでしか再利用されません。
1つのパッチに1つの役割
複雑なプロジェクトでは複数のステークホルダがいます。サウンドデザイン、ライトデザイン、色々なインタフェース、モーショングラフィクス、などの専門家。
全てのステークホルダは異なる時にシステムを変更する傾向があり、特定の時間のみ変更が可能です。
サブパッチャーの仕事は設計を抽象化して、カプセル化してシステムの変更があった時のみ詳細を変更します。
何をしたらいい?
- 各チームメンバの役割は、システムの特定の一側面のみについて説明する事です。
- チームの構成員の役割ごとに1つのパッチを書く
- サウンドデザイナー:ファイル名、ボリューム、ファイル再生のパラメータ
- ライトデザイナー:DMXチャンネル
- メディアインテグレータ:マトリックススイッチャーチャンネル、入力
- ネットワーク管理者:IPアドレス
- デバイスのベンダ:プロトコルの詳細
- コーポレート·デザイナー:色、フォント、背景
- モーションデザイナー:ファイル名とディレクトリ
- 数学者:複雑なアルゴリズム
- パッチでコード化された詳細を提供するチームメンバーの役割を明確にする。
- 各チームメンバーは、パッチを"1つだけ"開いて変更を加えればいい事を確認してください。また各パッチは、"1人の"メンバーによって編集される必要があります。
- 親パッチとしてデバッグフレームワークを作りましょう。チームメンバーがそのフレームワークで自分のサブシステムをテストできるようにしましょう。
- 他の全てのロジックはコードの詳細から分離する事はとるに足りません。アクティブロジックを避けてみましょう。
理由
- 一人の人間がそれらのパッチを編集する事を求められるべき。誤って何かを壊すかもしれない。
- これは他の人のサブシステムをあなたのエラーで混乱させずに明確にデバッグするためのただ1つの方法
- 自信が持てるし他のメンバーの時間を節約できます
- 責任を明確に分ける事ができます。
基盤を先に作ろう
何をしたらいい?
- 必要なロジック、モジュール、物事を全て一緒に持ってくる。
- 全ての役割のパッチをセットアップし、誰が各パートを埋めていくか考える。
- 主要なロジックコンポーネントを全てサブパッチにする。
- 詳細に時間を浪費しないで。サブパッチを作るだけでいい。ロジックを出来る限り単純にしよう。直接アウトプットをインプットと繋ぎます。定数も使っていい。サブパッチを親パッチから使えるようにするだけでいい。
- グラフィクスのプレースホルダを使う。テキストをステートや数値の表示に使う。グラフィクスの詳細から離れよう。全てのインプットをシミュレートしよう。
- 一番難しい部分を実装し始める。たとえクライアントに感動を与えないとしても。
- クライアントが物を見る事から始めたいと望んだ時のみ、グラフィックパッチから作りはじめよう。
理由
- 早期に未知の問題を発見する。コンセプトの問題はコードでは修正できません。
- どこにリソースを最も割り当てるか決める前に、全ての問題を挙げ、アプリケーションのパートの違いと複雑さを確認します。
- メンバに課題を説明したり、作業を割り振るためにプロトタイプを使おう
バージョン管理ツールを使おう (例えば Git)
バージョン管理ツールを使うアドバンテージを知りましょう。
何をしたらいい?
- 必要なソフトをインストールして、使い方を学ぶ
- リバートの方法、ログファイルの読み方、diff の取り方を学びましょう。
- 大胆に
- なぜ?
- これは動いている物を破壊せずに変更するための唯一の手段だから。
- これは動いている物を破壊せず理解するための唯一の手段だから。(vvvv パッチを読んで理解するためには大抵変更を加えてしまいます)
- これは気を狂わせずにチームで開発していくための唯一の手段だから。
注意する事
vvvv でのバージョン管理は時々苦痛です。なぜなら…
- 今の所便利な視覚的な diff ツールがありません
- Git にはマージが簡単にできるという思想が前提としてあります。今の所 vvvv のマージツールが存在しません。なのでブランチを切るのはつらいでしょう。
Git の変則性 / S と R の利点
vvvv プロジェクトのチームでの作業で、初期段階において、Git はエラーやフラストレーションの発生源になります。これは機能の微妙な組み合わせや、機能の欠如です。
たくさんのサブパッチと1つのルートパッチを想像して下さい。二人のプログラマが独立して各自サブパッチを作っています。仕様は完全には決まっておらず、各プログラマは追加のピンをサブパッチに加え、親パッチから繋ぎます。しばしばプログラマは二つのサブパッチを開発していて、それらを親のレベルで接続する必要があります。
サブパッチなしで親を同期すると他のプログラマと一貫性の無い結果になる事にも注意して下さい。
また、vvvv と git の組み合わせはマージが出来ません。これは良くない点です。
何をしたらいい?
- 各独立したモジュールで作業をする前に、全ての入出力が厳密に定義されているか確認して下さい。
- 留意するべきは、ある問題はピンの数を減らすことで、大きく開放される事が出来ます。S と R の数が増えたとしても。("S と R は気をつけて使おう"を参照)
なのでグローバル変数やアニメーション時間などは厳密に構造を定義しよう。
- 視覚的なマージツールが欲しい。
- vvvv のオブジェクトを深く統合的に扱う手段が欲しい。
- まだサブパッチの深さの S と R が隠れない。最初のサブパッチの頭に保持している。
ピンに名前をつけよう
何をしたらいい?
- モジュールはインプットとアウトプットと共に出来る限り自然なデバッグ手法を提供するように使う。
- 名前付き IOBox が設置できる所には出来るだけ設置する。
- 名前をつける事が難しい場合はもう一度アルゴリズムを考え直そう。
- 関係ないデータ1つにまとめるために Stallone, Cons, Zip を使うのは可能な限り避けよう。ピンの意味合いが分からなくなる。
理由
- 何が接続されているのか探し出すための時間は、ピンに名前が無いと爆発的に増加します。
- 目で接続を手繰るのは時間がかかります。その時間が増えるという事はつまり考えるのが遅くなるという事です。
- 各遠回りな事は、あなたが脳内で考える事のうち1つ追加されます(1度に考える事は6つまでを参照)
- 正しく IOBox を配置すると、テストのために値を変えたりする事も簡単になります。