ソフトウェアの開発および保守を最大限に効率化するためには、優れたLabVIEWアプリケーションが不可欠です。 このドキュメントでは、LabVIEWのソフトウェア設計に特に関連する基本構成モデル、デザインパターン、アーキテクチャを紹介します。この資料は包括的なものではありませんが、最も一般的なLabVIEWソフトウェア設計要素に関する参考資料を提供します。詳細については、ドキュメントの各リンクを参照してください。
以降のセクションでは、特定のタスク実行のためLabVIEWプログラミングで使用される一般的な構成モデルについて説明します。これらの基本構成モデルの理解を深めると、LabVIEWアプリケーション内での構成モデルの使用法を簡単に認識し、理解することができます。
タイプ定義 (多くの場合「typedef」と略記) を使用すると、アプリケーション全体で一貫して定義されるデータタイプを指定できます。たとえば、以下はクラスタのタイプ定義です。
このタイプ定義をフロントパネルまたはブロック図に配置するとクラスタとして表示され、端子と定数の左上隅には黒い三角形が表示されます。
タイプ定義は、アプリケーション全体で一貫したタイプを定義するのに非常に便利です。例として、タイプ定義に新しいパラメータ (この場合は構成パス) を追加するとどうなるか見てみましょう。
1つの場所でタイプ定義 (ソースのtypedef .ctlファイル) を変更すると、この変更はアプリケーション全体に自動的に反映されます。
もしクラスタがタイプ定義でなかったら、アプリケーション全体のクラスタ (フロントパネルとブロック図にある) のすべてのインスタンスを手動で更新しなくてはなりません。まれな例外を除いて、LabVIEWアプリケーションの開発中に作成するすべてのクラスタおよび列挙体をタイプ定義することが必要になります。
タイプ定義を使用すると、共有データタイプをシングルソースにすることでコードの保守性が向上します。
イベントストラクチャは、LabVIEWブロック図のユーザインタフェースイベントとプログラム的イベントに応答する機能を提供します。たとえば、フロントパネルの制御値が変化するたびに実行されるイベントダイアグラムを登録できます。ユーザイベントを生成関数を使用すると、ブロック図でプログラム的に生成されるイベントを登録することもできます。
イベントストラクチャは通常、コードがその実行中に複数のイベントに応答できるようWhileループの内側に配置されます。検出するさまざまなイベントに対して異なるフレームを使用するようイベントストラクチャを構成します。各イベントフレームには、イベントが発生すると実行される処理コードが含まれます。
LabVIEWに付属する以下のプロジェクトで、ユーザインタフェースイベントおよびプログラミングイベントを参照してください。
機能的グローバル変数 (「FGV」、「LabVIEW 2スタイルグローバル」、または「アクションエンジン」とも呼びます) はデータストレージのメカニズムです。 FGVは、初期化されていないシフトレジスタまたは初期化されていないフィードバックノードにデータを格納し、アプリケーションのどこからでも (つまり、「グローバルに」) そのデータにアクセスできるようにします。 以下の基本的な「FGV」VIのブロック図には、データ入力とデータ出力、および2つのアクション (「設定」と「取得」) を持つ操作列挙体が含まれています。
この単純な取得/設定のFGVの機能は、グローバル変数を使用した場合と同じです。実際には、FGVは「設定」と「取得」以外の機能も実行します。
FGVは、リファレンスの格納やより高度な操作も実行できます。 たとえば、次のファイルI/O FGVをご覧ください。そこではフィードバックノードの代わりに初期化されていないシフトレジスタが使用されています。 このFGVは連続した呼び出しの間にファイルリファレンスを保存し、単一のVI内でいくつかの異なる動作 (開く、読み取り、書き込み、閉じる) を実行します。
FGVは、グローバル変数と同じように競合状態の影響を受けやすいことに注意してください。原則として、コード内の複数の場所でグローバルデータに書き込むことは避けてください。
サブパネルは、他のVIのフロントパネルを表示できるフロントパネル制御器です。 サブパネルを使用すると、サブパネルに表示する別のVIを指定することで、UIのセクション全体を交換できるダイナミックユーザインタフェースを設計できます。また、サブパネルにより、論理的にグループ化されたフロントパネル項目を個別のVIに包含できるため、モジュール式のアプリケーション開発を促進できます。 このデザインを使用すると、他の「表示」VIや「メインアプリケーション」VIのコードを変更することなく、サブパネル内に表示されている個々のVIを変更できます。
以下のサンプルでは、「プラグイン」VIのフォルダをスキャンし、それらのプラグインでテキストリングを作成しています。テキストリングの項目を選択すると、対応する「プラグイン」VIが「メイン」VIのサブパネルに挿入されます。 この構成モデルを使用すると、「メイン」VIに変更を加えることなく新しい「プラグイン」VIをディスクに追加できます。
LabVIEWに付属の以下のサンプルを実行して、サブパネルをさらに試してみます。
デフォルトでは、LabVIEW内のVIは再入可能ではありません。これは、実行できるのは一度に1つのVIのインスタンスに限られるということです。そのため、以下のダイアグラムでは、「Process.vi」の1つの「サブ」VIインスタンスはもう1つのインスタンスが終了するまで待機する必要があります。
1つのVIの複数のインスタンスを並列で実行するには、VIを再入可能にする必要があります。これを行うには、ファイル→VIプロパティ→実行を選択し、「再入実行」設定をクローン共有による再入実行またはクローンの事前割り当てによる再入実行に変更します。
VIを再入可能に変更すると、複数のインスタンスを並列に実行できます。
以下の場合は、VIを再入可能にすることを検討してください。
機能的グローバル変数は、ほとんどの場合再入不可になります。これは、アプリケーション全体での共有が必要な、グローバルな状態データを保持するためです。
LabVIEWに付属の以下のサンプルを実行して、「再入可能」VIを試してみます。
別のVIからVIを呼び出すときはほとんどの場合、通常の「サブ」VI呼び出しを使用します。「サブ」VIを呼び出す場合、発呼ダイアグラムは「サブ」VIの実行が終了するまで待機する必要があります。これは同期呼び出しの例です。
ただし、アプリケーションによっては、「サブ」VIの起動を要求し、その「サブ」VIが実行中の場合にも、「発呼者」VIを実行することがあります。これは非同期呼び出しの例です。VIの非同期呼び出しを使用すると、任意の数のVIを動的に並列実行できます。さらに、再入可能VIを使用すると、同じVIのインスタンスを任意の数だけ作成でき、それらを非同期で実行できます。
以下の例では、「発呼者」VIは再入可能なProcess.viの複数のインスタンスを非同期で呼び出します。 各VIは独立して実行され、終了時のデータを「発呼者」VIに返します。 「発呼者」VIは、「処理」VIインスタンスの終了を待機せずに、他のブロックダイアグラムのコードを並列で実行できます。
LabVIEWに付属の以下のプロジェクトで、VIの非同期呼び出しの詳細を説明するサンプルを確認します。
LabVIEWでは、LabVIEWクラスを使用してオブジェクト指向プログラミングを容易に行うことができます。 LabVIEWのオブジェクト指向プログラミングは、クラス構造、カプセル化、継承を含む、C++やJavaなどのオブジェクト指向プログラミング言語の概念を取り入れています。これらの概念を使用して、アプリケーション内の他のコードセクションに影響を与えずに保守および変更しやすいコードを作成できます。LabVIEWに適用できるオブジェクト指向のデザインパターンはたくさんあります。 これらは、共通オブジェクト指向 (OO) デザインパターンのLabVIEWへの適用ドキュメントで説明されています。
LabVIEWに付属の以下のフォルダにあるプロジェクトを参照して、LabVIEWクラスを使用したプログラミングの基本を説明します。
デザインパターンは、同期または非同期コードを実行するための理論的なメカニズムです。ほとんどの実際のアーキテクチャ (下記のセクションを参照) では、中心となる実行メカニズムの一部として1つまたは複数のデザインパターンが使用されます。このセクションで説明するデザインパターンの動作を理解すると、それらのデザインパターンに基づいて構築されたより複雑なアーキテクチャの動作をより深く理解することができます。
ステートマシンとは、状態図またはフローチャートをLabVIEWのブロック図に実装したものです。任意の「ステート」は、次に実行するステートを決定するブロック図ロジックを持っています。ステートマシンには、ユーザ入力またはブロック図ロジックが次に実行するステートを決定する、ユーザインタフェース駆動で動作するものもあります。
基本的なLabVIEWステートマシンは次の主要コンポーネントで構成されています。
ステートマシンの詳細については、LabVIEWに付属の以下のプロジェクトを参照してください。
LabVIEWで「簡易ステートマシン」プロジェクトテンプレートを使用すると、ステートマシンベースのプロジェクトを作成できます。LabVIEWのファイルメニュ→プロジェクトを作成→簡易ステートマシンを選択します。このテンプレートをベースとしてアプリケーションを作成できます。
生産者/消費者デザインパターンは、異なる速度で実行する複数のループ間で、キューを使用してデータを共有する方法を示すものです。要素をエンキュー関数を含むループは「生産者」、要素をデキュー関数を含むループは「消費者」といいます。キューを使用すると、ループが異なるレートで実行されていてもデータが失われることがありません。
生産者/消費者デザインパターンはほぼ理論的なものであることに留意してください。実際には、実世界のコードでは基本的な生産者/消費者パターンはほとんど見られません。代わりに、キューメッセージハンドラが圧倒的に多く使用されています。
LabVIEWに付属の以下のサンプルを実行して、キューを使用したループ間でのデータ共有方法を確認してください。
キューメッセージハンドラ (QMH) は、生産者/消費者デザインパターンの1つの実装で、これにはユーザインタフェースによるイベント生成とプログラムによるイベント生成の両方のイベントストラクチャも含まれます。 イベント処理ループ (EHL) には、メッセージ処理ループ (MHL) 用のメッセージをエンキュー (生産) するイベントストラクチャが含まれています。MHLはメッセージをデキュー (消費) します。 MHLは、必要に応じて自分自身にもメッセージを生成できます。 この場合の「メッセージ」は、文字列 (MHLでケースストラクチャを駆動する) およびバリアント含むクラスタで、任意のタイプのメッセージ固有データを含むことができます。 QMHでは、MHLはユーザイベントを使用してEHLに送信します。
QMHの詳細の詳細については、LabVIEWに付属の以下のプロジェクトを参照してください。
LabVIEWで「キューメッセージハンドラ」プロジェクトテンプレートを使用すると、QMHベースのプロジェクトを作成できます。LabVIEWのファイルメニュ→プロジェクトを作成...→キューメッセージハンドラを選択します。
大規模なLabVIEWアプリケーションを拡張および保守するには、適切に構成する必要があります。
デバイスをテストする理論的なLabVIEWアプリケーションを考えてみましょう。これには、アプリケーションの構成、デバイスへの接続、測定の実行、データの表示、データのログ記録、エラー状態の処理、その他さらに多くの機能を実行するコードが必要になります。
以上述べたアプリケーションのすべての機能が同じLabVIEWブロック図にある場合、アプリケーションの機能を単独で開発、テスト、デバッグすることはできません。 たとえば、ロギングコードに問題がある場合、アプリケーション全体を実行せずにロギングのみをデバッグすることはできません。さらに、ロギングコードを変更すると、アプリケーションの他の部分がすべて同じVI内に存在するため、それらが意図せず影響を受ける可能性があります。
上記の各機能は、モジュール式で個別に開発、テスト、デバッグが可能なため、非同期プロセスに適しています。プロセス間の堅牢な通信メカニズムも必要になります。
LabVIEWコードを実装してこのようなモジュール式非同期設計を容易化する構造的アプローチは、アーキテクチャと呼ばれます。一部のLabVIEWチームは、独自のアーキテクチャを開発しています。非同期LabVIEWアプリケーションの実装に必要なコードインフラストラクチャとメッセージングの開発に伴う多くの考慮事項、落とし穴、注意事項を考えると、これは困難な作業になる可能性があります。さらに、堅牢なフレームワークの実装に必要なボイラープレートコードの量が多くなると、フレームワーク内で反復タスクを自動化する機能を十分に備えたツールが必要になります。これにより、開発者がフレームワークレベルのコードを自ら手動でプログラミングする際の間違いを防止できます。
幸いなことに、NI内外の複数の組織によって、消費者向けのアーキテクチャがLabVIEWコミュニティに提供されています。現在最もよく使用されている2つのLabVIEWアーキテクチャとして、アクターフレームワークとDQMHがあります。
アクターフレームワーク (AF) は、NIがサポートしているLabVIEW付属のアーキテクチャです。これは、キューメッセージハンドラ (QMH) のオブジェクト指向実装です。ケースストラクチャのメッセージ処理ループフレームおよび「要素をエンキュー」関数の代わりに、メッセージクラスは「実行」メソッドVIを提供して、「アクターコア」VI内の特定のコードを実行します。
AFのクラスベースの設計は、標準のケースストラクチャベースのQMHのアプローチでは不可能な、親アクターの動作を継承する子アクターの実装において拡張可能なフレームワークを提供します。さらに、フレームワークのすべてのコア機能 (初期化、メッセージ、エラー応答など) は、フレームワークのオブジェクト指向設計により、特定のアクターで拡張またはオーバーライドが可能です。
アクターフレームワークの詳細については、LabVIEWに付属の以下のプロジェクトを参照してください。
LabVIEWで「アクターフレームワーク」プロジェクトテンプレートを使用すると、AFベースのプロジェクトを作成できます。LabVIEWのファイルメニュ→プロジェクトを作成...→アクターフレームワークを選択します。
アクターフレームワークを成功させるには、オブジェクト指向プログラミングの基礎的な知識をはじめ、フレームワークについての理解と適切な指導が不可欠です。AFトレーニング用のリソースを多数用意しています。最も人気のコースを次にご紹介します。
開発中のアプリケーションでAFアーキテクチャの使用を開始する際に、NIコミュニティユーザーグループであるアクターフレームワークの他のユーザと対話したり、他のプログラマと質問したりベストプラクティスについて話し合ったりすることができます。
Deracor Queued Message Handler (DQMH®) は、特定のプロセス (または「モジュール」) 内での通信に標準のQMHに似たメカニズムを利用しますが、非同期モジュール間の通信はユーザイベントを使用します。DQMHはフレームワークのマイナーコンポーネントでLabVIEWクラスを使用していますが、オブジェクト指向アーキテクチャではありません。
DQMHは、DQMHコンソーシアムが開発、保守しているサードパーティのアーキテクチャです。最初のDQMH設計チームの主な目的は、CLAD/CLDレベルの開発者がアクセスできる無料のフレームワークをLabVIEWコミュニティに提供することでした。
DQMHは、VI Package Managerを使用してインストールできます。
DQMHパッケージのインストールを完了したら、以下のプロジェクトで詳細を確認します。
DQMHトレーニング用のリソースを多数用意しています。 ご自身のアプリケーションでDQMHアーキテクチャの使用を開始する際に、NIコミュニティユーザーグループであるDQMHコンソーシアムツールキットの他のユーザと対話したり、他のプログラマと質問したりベストプラクティスについて話し合うことができます。
DQMH®はDQMH Consortium, LLCの登録商標です。
AFとDQMHは世界で最も人気のあるLabVIEWアーキテクチャですが、それだけではありません。LabVIEWコミュニティで利用できるアーキテクチャには以下が含まれます。