次の方法で共有


ワークフローの方法: Windows Workflow Foundation について

David Chappell
Chappell & Associates

2009 年 4 月

この記事をダウンロードする

  • Word 形式 を する
  • PDF

Windows Workflow Foundation の概要

コードを記述する全員が、優れたソフトウェアを構築したいと考えています。 そのソフトウェアがサーバー アプリケーションの場合、優れた機能の一部はスケーリングが適切であり、大量のリソースを消費することなく大きな負荷を処理します。 優れたアプリケーションは、作成者とそれを維持する人々の両方にとって、できるだけ理解しやすいものでなければなりません。

これらの両方の目標を達成するのは簡単ではありません。 アプリケーションのスケーリングに役立つアプローチは、それらを分解し、ロジックを理解しにくい個別のチャンクに分割する傾向があります。 しかし、1 つの実行可能ファイルに存在する統合ロジックを記述すると、アプリケーションのスケーリングが不可能になる可能性があります。 必要なのは、アプリケーションのロジックを統一し、アプリケーションのスケーリングを可能にしながら、理解しやすくする方法です。

これを実現することは、Windows Workflow Foundation (WF) の主な目標です。 WF は、ワークフローを使用して作成されたロジックをサポートすることで、統合されたスケーラブルなアプリケーションを作成するための基盤を提供します。 これに加えて、WF では、並列作業の調整、プログラムの実行の追跡など、他の開発の課題も簡略化できます。

WF は 2006 年に .NET Framework 3.0 で最初にリリースされた後、.NET Framework 3.5 で更新されました。 これらの最初の 2 つのバージョンは、特に独立系ソフトウェア ベンダー (ISV) に役立ちましたが、エンタープライズ開発者にとって主流のテクノロジにはなっていません。 .NET Framework 4 の一部である WF のバージョンでは、作成者はこれを変更することを目指しています。 この最新リリースの主な目標は、WF をすべての .NET 開発者向けのプログラミング ツールキットの標準部分にすることです。

他のテクノロジと同様に、WF を適用するには、WF の概要、役に立つ理由、および WF を使用するのが理にかなっているタイミングを理解する必要があります。 この概要の目的は、これらのことを明確にすることです。 WF アプリケーションを記述する方法については学習しませんが、WF が提供する内容、その理由、開発者の生活を改善する方法について説明します。 つまり、ワークフローの方法を理解し始めます。

課題: 統合されたスケーラブルなアプリケーション ロジックの記述

プログラムを記述する簡単な方法の 1 つは、単一のコンピューター上の 1 つのプロセスで実行される統合アプリケーションを作成することです。 図 1 は、この考え方を示しています。

図 1: アプリケーション ロジックは、統合された全体として作成し、1 台のコンピューターで実行されているプロセス内の特定のスレッドで実行できます。

この例の単純な擬似コードは、アプリケーションが通常実行する処理の種類を示しています。

  • 状態を維持します。これは単純な文字列変数で表されます。
  • クライアントからの要求を受信するなどして、外部から入力を取得します。 単純なアプリケーションはコンソールから読み取るだけですが、より一般的な例では、Web ブラウザーから HTTP 要求を受信したり、別のアプリケーションから SOAP メッセージを受信したりする場合があります。
  • 外部に出力を送信します。 構築方法によっては、アプリケーションは HTTP、SOAP メッセージ、コンソールへの書き込み、またはその他の方法でこれを行う場合があります。
  • if/else や while などの制御フロー ステートメントを使用して、ロジックを介して代替パスを提供します。
  • アプリケーションの各ポイントで適切なコードを実行して作業を行います。

ここで示す統合アプローチでは、アプリケーション ロジックは、1 台のコンピューター上の特定のプロセス内のスレッドで実行されるその全体の人生を費やします。 この単純なアプローチには、いくつかの利点があります。 一つには、ロジックを簡単で統一された方法で実装できます。 これは、コードを操作するユーザーがそれを理解するのに役立ち、イベントの許可された順序も明示的になります。 たとえば、図 1 では、クライアントの最初の要求が 2 番目の要求より前に必要であるのは明らかです。プログラムの制御フローで要求されます。 2 番目の要求が到着すると、アプリケーションを経由する他のパスがないため、最初の要求が既に処理されていることを確認する必要はありません。

この方法のもう 1 つの利点は、アプリケーションの状態を簡単に操作できる点です。 その状態はプロセスのメモリに保持され、処理が完了するまでプロセスは継続的に実行されるため、状態は常に使用可能です。開発者は通常の変数にアクセスするだけです。 より簡単なものは何でしょうか?

それでも、この基本的なプログラミング スタイルには制限があります。 アプリケーションが入力を待機する必要がある場合は、コンソールのユーザー、Web サービス クライアント、または他のユーザーのいずれからのものであれ、通常は単にブロックされます。 使用しているスレッドとプロセスの両方が、入力が到着するまで保持されます。時間がかかります。 スレッドとプロセスは比較的希少なリソースであるため、入力を待機している場合にどちらかを保持するアプリケーションは、あまりスケーリングされません。

よりスケーラブルな方法は、入力を待機しているときにアプリケーションをシャットダウンしてから、その入力が到着したら再起動することです。 この方法では、アプリケーションがスレッドやプロセスを必要としないときに保持されないため、リソースを無駄にすることはありません。 これを行うと、アプリケーションは異なるマシン上のさまざまなプロセスで異なる時間に実行されます。 図 1 のように、1 つのシステムにロックされるのではなく、複数の使用可能なマシンのいずれかでアプリケーションを実行できます。 これにより、作業をより簡単にさまざまなコンピューターに分散できるため、スケーラビリティにも役立ちます。 図 2 は、この外観を示しています。

図 2: アプリケーション ロジックはチャンクに分割でき、すべての共有共通状態は異なるマシンで実行できます。

このサンプル アプリケーションには以前と同じロジックが含まれていますが、別のチャンクに分割されました。 クライアントの最初の要求を受信すると、適切なチャンクが読み込まれて実行されます。 この要求が処理され、応答が返されると、このチャンクをアンロードできます。メモリに何も残る必要はありません。 クライアントの 2 番目の要求が到着すると、それを処理するチャンクが読み込まれて実行されます。 図 2 に示すように、このチャンクは、最初のチャンクとは異なるマシンで実行されている別のプロセスで、別のスレッドで実行できます。 要求が処理されると、この 2 番目のチャンクをアンロードして、使用していたメモリを解放することもできます。

この方法で動作するテクノロジの一般的な例の 1 つは、ASP.NET です。 開発者は、ASP.NET アプリケーションをページのセットとして実装します。それぞれに、アプリケーションのロジックの一部が含まれています。 要求が到着すると、正しいページが読み込まれ、実行され、再度アンロードされます。

このスタイルで構築されたアプリケーションでは、前に示したより単純なアプローチを使用して作成したアプリケーションよりも効率的にマシン リソースを使用できるため、スケーリングが向上します。 しかし、この改善されたスケーラビリティと複雑さに対する支払いを行いました。 図 2 に示すように、一つには、コードのさまざまなチャンクが何らかの形で状態を共有する必要があります。 各チャンクはオンデマンドで読み込まれ、実行され、シャットダウンされるため、この状態はデータベースや別の永続化ストアなどに外部に格納する必要があります。 図 1 に示すシナリオのように、通常の変数にアクセスするのではなく、開発者はアプリケーションの状態を取得して保存するために特別な操作を行う必要があります。 たとえば、ASP.NET アプリケーションでは、開発者は状態をデータベースに直接書き込んだり、Session オブジェクトにアクセスしたり、他の方法を使用したりできます。

このスケーラビリティの向上のもう 1 つのコストは、コードがプログラムの全体的なロジックの統一されたビューを提供しなくなったということです。 図 1 に示すバージョンでは、プログラムが入力を予期する順序は明らかです。コードを通過できるパスは 1 つだけです。 ただし、図 2 のバージョンでは、この制御フローは明らかではありません。 実際、クライアントの 2 番目の要求を処理するコードのチャンクは、最初の要求が既に完了していることを確認することから始める必要がある場合があります。 あらゆる種類の重要なビジネス プロセスを実装するアプリケーションでは、さまざまなチャンクにわたって制御フローを理解し、正しく実装することは困難な場合があります。

状況は次のとおりです。統合されたアプリケーションを記述すると、開発者の生活が簡単になり、コードを簡単に理解できますが、結果はうまく拡張されません。 ASP.NET アプリケーションなど、外部の状態を共有するチャンクアプリケーションを作成すると、スケーラビリティは可能になりますが、状態の管理が困難になり、統合制御フローが失われます。 私たちが望むのは、単純な状態管理を使用してスケーラブルなビジネス ロジックを記述しながら、アプリケーションの制御フローを統一して表示する方法です。

これはまさにワークフローの方法で提供されるものです。 次のセクションでは、その方法を示します。

解決策: ワークフローの方法

WF アプリケーションでこれらの問題 (およびその他) がどのように解決されるかを理解するには、WF のしくみの基本について説明する必要があります。 その過程で、このテクノロジが驚くほど多くのケースで開発者にとってより良い生活を送ることができる理由を見ていきます。

統合アプリケーション ロジックの作成

WF を使用して作成されたワークフロー ベースのアプリケーションは、通常のアプリケーションと同じ種類の処理を行います。状態を維持し、外部から入力を取得して外部に出力を送信し、制御フローを提供し、アプリケーションの作業を実行するコードを実行します。 ただし、WF ワークフローでは、これらすべての処理がアクティビティによって行われます。 図 3 は、比較のために統一されたコード アプローチと共に、この外観を示しています。

図 3 : WF ワークフローでは、プログラムのすべての作業がアクティビティによって実行されます。

図 3 に示すように、すべてのワークフローには、他のすべてを含む最も外側のアクティビティがあります。 ここで、この最も外側のアクティビティは Sequence と呼ばれ、通常のプログラムと同様に、その状態を維持する変数を持つことができます。 Sequence は複合アクティビティであるため、他のアクティビティを含めることもできます。

この簡単な例では、ワークフローは外部から入力を取得する ReceiveMessage アクティビティで始まります。 その後に If アクティビティが続きます。これは (当然ながら) 分岐を実装します。 複合アクティビティの場合は、各分岐で実行された作業を実行する他のアクティビティ (ここでは X と Y というラベルが付いています) を含みます。 If アクティビティの後に、このワークフロー以外の世界に出力を送信する SendMessage アクティビティが続きます。 別の ReceiveMessage アクティビティが次に表示され、入力が増え、その後に While アクティビティが続きます。 While には、この while ループの処理を行う別のアクティビティ Z が含まれています。 ワークフロー全体が最終的な SendMessage アクティビティで終了し、プログラムの最終的な結果が送信されます。

これらのアクティビティはすべて、図 2 の一致する色が示すように、一般的なプログラムのさまざまな部分に機能的に対応しています。 しかし、従来のプログラムのように、組み込みの言語要素を使用するのではなく、WF ワークフロー内の各アクティビティは実際にはクラスです。 ワークフローの実行は、アクティビティの実行方法を認識するコンポーネントである WF ランタイムによって実行されます。 図 4 は、この考え方を示しています。

図 4 : WF ランタイムは、ワークフローによって決定された順序でアクティビティを実行します。

ワークフローの実行が開始されると、WF ランタイムは最初に最も外側のアクティビティを実行します。この例ではシーケンスです。 次に、その中の最初のアクティビティ (ReceiveMessage、次のアクティビティなど) を実行します。 特定の状況で実行されるアクティビティは、ワークフローを通じて実行されるパスによって異なります。 たとえば、最初の ReceiveMessage アクティビティで 1 種類の入力を取得すると、If アクティビティがアクティビティ X を実行し、別の種類の入力によってアクティビティ Y が実行される可能性があります。他のプログラムと同じです。

WF ランタイムは、実行しているアクティビティの内部について何も認識していないことを理解しておくことが重要です。 ReceiveMessage から If を指定することはできません。 その方法を知っているのは、アクティビティを実行してから次のアクティビティを実行することだけです。 ただし、ランタイムはアクティビティ間の境界を確認できますが、これは役に立ちます。

この重要な作業は、WF がワークフローを記述するための特定の言語を定義していないことです。すべては、開発者が使用することを選択したアクティビティによって異なります。 暮らしを楽にするために、WF には、広く役立つ一連のアクティビティを提供する基本アクティビティ ライブラリ (BAL) が含まれています。 (実際、ここで使用するアクティビティの例はすべて BAL から引き出されています)。ただし、開発者は、好きな他のアクティビティを自由に作成できます。 彼らはBALを完全に無視することもできます。

ここに明白な質問があります:なぜこの問題に行くのですか? アクティビティを使用してプログラムを作成することは、開発者が使用しているものとは異なるので、なぜ誰かが気にする必要がありますか? 通常のコードを記述しないのはなぜですか?

もちろん、このアプローチは、より良いコードを作成するのに役立つということです。 たとえば、ワークフローの方法によって開発者に統一された制御フローが提供されていることに注意してください。 図 1 に示す単純なケースと同様に、プログラムのメイン ロジックは 1 つのコヒーレント ストリームで定義されています。 これにより理解が容易になり、ロジックがチャンクに分割されないため、追加のチェックは必要ありません。 ワークフロー自体は、許可された制御フローを表します。

これは、統合アプリケーション ロジックの作成という目標の半分を表します。 しかし、WF アプリケーションは後半を達成して、単純な状態管理でスケーラブルなアプリケーションを作成することもできます。 次のセクションでは、ワークフローの方法でこれを実現する方法について説明します。

スケーラビリティの提供

スケーラブルであるために、サーバー アプリケーションを 1 台のコンピューター上の 1 つのプロセスにロックすることはできません。 ただし、ASP.NET ページのように、アプリケーション ロジックを明示的にチャンクに分割すると、統一された制御フローとして必要なものが分割されます。 また、プログラマは状態を明示的に操作するように強制されます。 私たちが本当に気に入っているのは、ロジックを自動的にチャンクに分割し、異なるマシン上の異なるプロセスで実行できるようにする方法です。 また、アプリケーションの状態を管理したいと考えているので、必要なのは変数へのアクセスです。

これはまさにワークフローが提供する内容です。 図 5 は、WF がこれらのことを実現する方法の基礎を示しています。

図 5 : WF ランタイムは、入力を待機している間にワークフローをアンロードし、入力が到着したら再度読み込みます。

他のアプリケーションと同様に、WF ワークフローは入力の待機をブロックします。 たとえば、図 5 では、クライアントの 2 番目の要求を待機している 2 番目の ReceiveMessage アクティビティでワークフローがブロックされます (手順 1)。 WF ランタイムはこれを認識するため、ワークフローの状態と、ワークフローを再開する場所を永続化ストアに格納します (手順 2)。 このワークフロー (手順 3) の入力が到着すると、WF ランタイムはその永続的な状態を検出し、ワークフローを再読み込みして、中断した場所で実行を取得します (手順 4)。 これはすべて自動的に行われます。WF 開発者は何もする必要はありません。 WF ランタイムはワークフローを確認できるため、これらの詳細をすべて処理できます。

このアプローチの明らかな利点の 1 つは、入力を待機している間に、スレッドをブロックし、プロセスを使い切るメモリ内でワークフローがハングアップしないという点です。 もう 1 つの利点は、永続化されたワークフローが、最初に実行されていたコンピューター以外のコンピューターに再読み込みされる可能性があるということです。 このため、図 6 に示すように、ワークフローのさまざまな部分が異なるシステムで実行される可能性があります。

図 6 : ワークフローは、有効期間中に異なるスレッド、異なるプロセス、および異なるマシンで実行される場合があります。

この例では、ワークフローがマシン A のプロセスで最初のクライアント要求を処理するとします。2 番目の ReceiveMessage によってワークフローが入力の待機をブロックすると、WF ランタイムは、説明したようにワークフローの状態を永続化ストアにアンロードします。 クライアントの 2 番目の要求が到着すると、このワークフローをマシン B のプロセスに再読み込みできます。特定のコンピューター上の特定のプロセスで特定のスレッドにロックされるのではなく、必要に応じて WF ワークフローを移動できます。 また、開発者はこの機敏性を無料で取得します。WF によって自動的に提供されます。

WF ランタイムは、ワークフローが入力を待機する必要がある期間を気にしないことを指摘する価値があります。 ワークフローが永続化されてから数秒後、数分後、または数か月後に到着する場合があります。 永続化ストアがワークフローの状態を保持している限り、そのワークフローを再起動できます。 これにより、WF は、実行時間の長いプロセスを実装するアプリケーションを構築するための魅力的なテクノロジになります。 たとえば、最初の面接のスケジュールから新しい従業員の組織への統合まで、あらゆるものを含む雇用プロセスをサポートするアプリケーションについて考えてみましょう。 このプロセスは数週間または数か月かかる可能性があるため、WF を使用してアプリケーションの状態を管理することは適切です。 ただし、WF はこの種の実行時間の長いプロセスで非常に役立ちますが、これが唯一の目的ではないことを理解することが重要です。 統合されたスケーラブルなロジックを必要とするアプリケーションは、WF の候補として適しています。

実際、図 6 をもう一度見てみましょう。 図 2 のようには見えません。これは、チャンキーなアプリケーション (たとえば、ASP.NET のみを使用して構築されたもの) がスケーラビリティをどのように達成したかを示しています。 実際、図 6 は図 1 と強い類似性を持っていません。これは、線形制御フローを使用して構築された統合アプリケーションを示しています。 WF は、これらの両方を実現します。アプリケーションの制御フローは理解可能で統一された方法で表され、アプリケーションは 1 台のコンピューター上の 1 つのプロセスにロックされていないため、スケーリングできます。 これがワークフローの方法の美しさです。

そして、それはすべてではありません。WF の使用には、他の利点もあります。 並列作業の調整が容易になります。たとえば、アプリケーションの進行状況の追跡などに役立ちます。 次のセクションでは、テクノロジのこれらの側面について説明します。

ワークフロー方法のその他の利点

WF ワークフローは、WF ランタイムによって実行されるアクティビティで構成されます。 WF の世界を理解するには多少の労力がかかりますが、このスタイルでアプリケーション ロジックを記述すると、次に説明するように、多くの一般的なプログラミング課題が簡単になります。

並列作業の調整

WF BAL には、使い慣れたプログラミング言語ステートメントに対応するアクティビティが含まれています。 このため、通常のプログラムと同じように動作するワークフローを記述できます。 ただし、WF ランタイムが存在すると、従来のプログラミング言語よりも多くを提供するアクティビティを作成することもできます。 この重要な例は、ワークフローを使用して並列作業の調整を容易にすることです。

混同しないでください。ここでは、マルチコア プロセッサで同時に実行される並列コードを記述することに焦点を当てないでください。 代わりに、たとえば、2 つの Web サービスを呼び出し、両方の結果を待ってから続行する必要があるアプリケーションについて考えます。 呼び出しを並列で実行する方が、順番に実行するよりも明らかに高速ですが、これを行う従来のコードを記述するのは簡単ではありません。 また、.NET Framework には、これらの呼び出しを非同期に行うさまざまな方法が用意されていますが、特に単純なものはありません。 これは、ワークフローの方法が輝くことができる別の状況です:WFはこれを簡単にします。 図 7 は、その方法を示しています。

図 7 : Parallel アクティビティに含まれるアクティビティは並列で実行されます。

この図は、前の例とよく似た単純なワークフローを示しています。 大きな違いは、2 つの Web サービスを呼び出し、両方からの応答を待ってから続行するという点です。 これらの呼び出しを並列で実行するために、ワークフローの作成者は、並列アクティビティ内で SendMessage アクティビティと ReceiveMessage アクティビティの両方のペアをラップしました。 Parallel は WF の基本アクティビティ ライブラリの標準的な部分であり、名前が示すとおりに行われます。含まれているアクティビティを並列で実行します。 開発者がこれを処理する複雑さを処理するのではなく、WF ランタイムと Parallel アクティビティが重い作業を行います。 開発者が行う必要があるのは、問題を解決するために必要に応じてアクティビティを手配することです。

自動追跡の提供

WF ランタイムはワークフローのアクティビティ間の境界を確認できるため、これらの各アクティビティがいつ開始および終了するかを認識します。 これを考えると、ワークフローの実行の自動追跡は簡単です。 図 8 は、この考え方を示しています。

図 8 : WF ランタイムはワークフローの実行を自動的に追跡できます。

この例に示すように、WF ランタイムはワークフローの実行のレコードを追跡ストアに書き込むことができます。 1 つのオプションは、アクティビティの開始と終了のたびに書き込まれたレコードを含むアクティビティをログに記録することです。 たとえば、図に示されている時点で、ワークフローは If アクティビティの実行を開始しようとしているため、WF ランタイムはこれを示すイベントを書き込みます。 また、特定の変数 (ワークフローの状態など) を追跡し、ワークフローの実行のさまざまなポイントで値を記録することもできます。

WF の他の側面と同様に、この自動ログ記録には、基本的に開発者側の作業は必要ありません。 追跡が行われる必要があることを示し、関心のあるレベルを指定するだけで、WF が残りの処理を行います。

再利用可能なカスタム アクティビティの作成

WFのBALの活動は、さまざまな便利な機能を提供します。 たとえば、既に示されているように、この組み込みセットには、制御フロー、メッセージの送受信、作業の並列実行などのアクティビティが含まれています。 ただし、実際のアプリケーションをビルドするには、通常、そのアプリケーションに固有のタスクを実行するアクティビティを作成する必要があります。

これを可能にするために、WF ではカスタム アクティビティを作成できます。 たとえば、前に示したワークフローの X、Y、Z というラベルの付いたアクティビティは、実際にはカスタム アクティビティです。図 9 は明示的に示しています。

図 9 : カスタム アクティビティを使用すると、ワークフローでアプリケーション固有のタスクを実行できます。

カスタム アクティビティは単純で、1 つのタスクのみを実行することも、任意に複雑なロジックを含む複合アクティビティにすることもできます。 また、単純でも複雑でも、カスタム アクティビティはさまざまな方法で使用できます。 たとえば、WF を使用して作成されたビジネス アプリケーションでは、アプリケーション固有のロジックを 1 つ以上のカスタム アクティビティとして実装できます。 また、WF を使用するソフトウェア ベンダーは、顧客の生活を容易にするために一連のカスタム アクティビティを提供する場合があります。 たとえば、Windows SharePoint Services を使用すると、開発者は SharePoint の標準リストを使用してユーザーと対話する WF ベースのアプリケーションを作成できます。 これを簡単にするために、SharePoint にはリストに情報を書き込むためのカスタム アクティビティが含まれています。

カスタム アクティビティは、C# または Visual Basic または別の言語を使用して、コードで直接記述できます。 また、既存のアクティビティを組み合わせて作成することもできます。これにより、いくつかの興味深いオプションが可能になります。 たとえば、組織では、最も熟練した開発者向けに低レベルのカスタム アクティビティを作成し、これらをより高度なビジネス機能にパッケージ化して、使用する技術担当者を減らします。 これらの上位レベルのアクティビティは、必要なビジネス ロジックをすべて、再利用可能なボックスにきちんとラップして実装できます。

これを考えるもう 1 つの方法は、WF ランタイムによって実行される特定のアクティビティのセットを言語として表示することです。 組織が複数のアプリケーション間で特定の問題を解決するために再利用できるカスタム アクティビティのグループを作成する場合、実際に行っていることは、一種のドメイン固有言語 (DSL) を作成することです。 これが完了すると、これらの事前にパッケージ化されたカスタム機能のチャンクを使用して WF アプリケーションを作成する技術担当者が少なくなる可能性があります。 アプリケーションの関数を実装する新しいコードを記述する代わりに、既存のアクティビティを組み立てるだけで便利な新しいソフトウェアを作成できます。 ワークフローの方法で定義されたこのスタイルの DSL は、状況によっては開発者の生産性を大幅に向上させることができます。

プロセスを表示する

従来のプログラミング言語でアプリケーションを作成することは、コードを記述することを意味します。 WF を使用してアプリケーションを作成することは、通常、それほど低いレベルではありません。 代わりに、少なくともワークフローのメイン制御フローをグラフィカルに組み立てることができます。 これを可能にするために、WF には Visual Studio 内で実行されるワークフロー デザイナーが含まれています。 図 10 に例を示します。

図 10 : Visual Studio 内で実行されているワークフロー デザイナーを使用すると、開発者はアクティビティをドラッグ アンド ドロップしてワークフローを作成できます。

この例に示すように、WF 開発者が使用できるアクティビティが左側に表示されます。 ワークフローを作成するために、これらのアクティビティをデザインサーフェイスに組み立てて、アプリケーションに必要なロジックを作成できます。 必要に応じて、WF ワークフロー デザイナーを他の環境で再ホストして、他のユーザーが独自のオファリング内でこのツールを使用できるようにすることもできます。

一部の開発者にとって、このグラフィカルアプローチにより、アプリケーションの作成が迅速かつ簡単になります。 また、アプリケーションのメイン ロジックが見えやすくなります。 WF ワークフロー デザイナーは、何が起こっているのかを簡単に把握できるため、開発者がアプリケーションの構造をより迅速に理解するのに役立ちます。 これは、デプロイされたアプリケーションを維持する必要があるユーザーにとって特に役立ちます。これは、新しいアプリケーションを十分に学習して変更する必要があるため、時間のかかるプロセスになる可能性があるためです。

しかし、カスタム アクティビティはどうでしょうか。 コードを記述する必要がまだありませんか? 答えははいなので、WF では Visual Studio を使用して C#、Visual Basic、およびその他の言語でカスタム アクティビティを作成することもできます。 このしくみを把握するには、WF デザイナーがワークフローのさまざまな部分をどのように表しているかを理解することが重要です。 図 11 は、これが通常どのように行われるかを示しています。

図 11 : ワークフローの状態と制御フローは通常 XAML で記述されますが、カスタム アクティビティはコードで記述できます。

WF ワークフローの構成 (含まれるアクティビティとそれらのアクティビティの関連) は、通常、eXtensible Application Markup Language (XAML) を使用して表されます。 図 11 に示すように、XAML は、ワークフローの状態を変数として記述し、ワークフローのアクティビティ間の関係を表す XML ベースの方法を提供します。 たとえば、最も外側のワークフロー アクティビティ シーケンスの XAML には、想定どおりに ReceiveMessage アクティビティの後に If アクティビティが続きます。

この If アクティビティには、カスタム アクティビティ X と Y が含まれています。ただし、XAML で作成されるのではなく、これらのアクティビティは C# クラスとして記述されます。 XAML でのみいくつかのカスタム アクティビティを作成することは可能ですが、通常、より特殊なロジックはコードで直接記述されます。 実際、通常のアプローチではありませんが、開発者はコード内でワークフローを完全に記述することもできます。XAML を使用する必要は厳密ではありません。

Windows Workflow Foundation の使用: 一部のシナリオ

WF の仕組みを理解することは、ワークフローの方法を把握するうえで不可欠な部分です。 ただし、十分ではありません。また、アプリケーションでワークフローを使用する方法も理解する必要があります。 したがって、このセクションでは、WF が一般的な状況でどのように、なぜ使用されるかをアーキテクチャで確認します。

ワークフロー サービスの作成

多くの場合、サービスとしてのビジネス ロジックの構築は理にかなっています。 たとえば、ブラウザーから ASP.NET、Silverlight クライアント、スタンドアロン デスクトップ アプリケーションから同じ機能セットにアクセスする必要があるとします。 これらのクライアントのいずれか (つまり、サービスとして) から呼び出すことができる一連の操作として、このロジックを実装するのが最適なアプローチである可能性があります。 サービスとしてロジックを公開すると、他のロジックにもアクセスできるようになり、アプリケーションの統合が容易になる場合があります。 (これは、サービス指向アーキテクチャである SOA の概念の背後にある中心的な考え方です)。

現在の .NET 開発者にとって、サービスを作成するための主要なテクノロジは Windows Communication Foundation (WCF) です。 特に、WCF を使用すると、開発者は REST、SOAP、およびその他の通信スタイルを使用してアクセスできるビジネス ロジックを実装できます。 また、一部のサービスでは、WCF がすべて必要な場合があります。 たとえば、各操作が単独で実行されるサービスを実装する場合は、任意の操作をいつでも呼び出すことができます。順序は不要です。生の WCF サービスとしてこれらのサービスを構築するだけで問題ありません。 操作がデータのみを公開するサービスの作成者は、たとえば WCF を使用するだけで済む場合があります。

ただし、より複雑な状況では、サービス内の操作で関連する一連の機能が実装されている場合、WCF だけでは不十分な場合があります。 お客様がフライトの予約を予約したり、オンライン ショッピングを行ったり、他のビジネス プロセスを実行したりできるアプリケーションについて考えてみましょう。 このような場合は、WF を使用してサービスのロジックを実装することもできます。 この組み合わせには名前もあります。WF を使用して実装され、WCF 経由で公開されるロジックはワークフロー サービスと呼ばれます。 図 12 は、その考え方を示しています。

図 12 : ワークフロー サービスは WCF を使用して WF ベースのロジックを公開します。

図に示すように、WCF では、クライアントが SOAP、REST、またはその他の何かを介して呼び出すことができる 1 つ以上のエンドポイントを公開できます。 クライアントがこのサンプル サービスで最初の操作を呼び出すと、要求はワークフローの最初の ReceiveMessage アクティビティによって処理されます。 If アクティビティが次に表示され、含まれているカスタム アクティビティのうち実行されるアクティビティは、クライアントの要求の内容によって異なります。 If が完了すると、SendMessage 経由で応答が返されます。 別の操作を呼び出すクライアントの 2 番目の要求も同様の方法で処理されます。これは ReceiveMessage によって受け入れられ、ワークフローのロジックによって処理され、SendMessage の使用に応答されます。

このような方法でサービス指向のビジネス ロジックを構築することは、なぜ良いアイデアなのでしょうか。 答えは明白です:統合されたスケーラブルなアプリケーションを作成できます。 すべての操作にチェックを含める必要はなく、今すぐ呼び出すことができますか? この知識はワークフロー ロジック自体に埋め込まれています。 これにより、アプリケーションの記述が容易になり、最終的に保守する必要があるユーザーにとって、同様に重要な理解が容易になります。 また、スケーラビリティと状態管理を処理する独自のコードを記述するのではなく、WF ランタイムによってこれらの処理が自動的に行われます。

ワークフロー サービスには、他の WF アプリケーションと同様に、前に説明したすべての利点も取得されます。 これには、次のものが含まれます。

  • 並列作業を行うサービスの実装は簡単です。アクティビティを並列アクティビティにドロップするだけです。
  • 追跡はランタイムによって提供されます。
  • 問題のドメインによっては、他のサービスで使用する再利用可能なカスタム アクティビティを作成できる場合があります。
  • ワークフローは、WF ワークフロー デザイナーに直接表示されるプロセス ロジックを使用して、グラフィカルに作成できます。

WF と WCF をこのように組み合わせて使用する (ワークフロー サービスを作成する) の方が、以前のバージョンの WF ではそう簡単ではありませんでした。 .NET Framework 4 では、このテクノロジの組み合わせがより自然な方法で結合されます。 目標は、このスタイルでビジネス ロジックを可能な限り簡単に作成することです。

"Dublin" を使用したワークフロー サービスの実行

ワークフローに関する 1 つの大きな問題がまだ説明されていません。ワークフローはどこで実行されますか? WF ランタイムは、アクティビティと同様にクラスです。 これらの処理はすべてホスト プロセスで実行する必要がありますが、これはどのようなプロセスですか?

答えは、WF ワークフローはほぼすべてのプロセスで実行できるということです。 必要であれば、WF の基本的なサービス (永続化など) の一部を置き換えても、独自のホストを自由に作成できます。 多くの組織、特にソフトウェア ベンダーがこれを行っています。 しかし、管理機能を備えた WF の真に機能的なホスト プロセスを構築することは、世界で最も簡単なことではありません。 また、インフラストラクチャではなくビジネス ロジックの構築にお金を費やしたい組織にとって、この作業を回避することは理にかなっています。

より簡単なオプションは、インターネット インフォメーション サーバー (IIS) によって提供されるワーカー プロセスで WF ワークフローをホストすることです。 これは機能しますが、ベアボーン ソリューションのみを提供します。 WF 開発者の生活を容易にするために、Microsoft は "Dublin" という名前のテクノロジ コードを提供しています。 IIS と Windows プロセス アクティブ化サービス (WAS) の拡張機能として実装される "Dublin" の主な目標は、IIS と WAS をワークフロー サービスのホストとしてより魅力的にすることです。 図 13 は、"Dublin" 環境で実行されているワークフロー サービスの外観を示しています。

図 13: "Dublin" は、ワークフロー サービスの管理とその他を提供します。

WF 自体には、ワークフローの状態や追跡などを保持するためのメカニズムが含まれていますが、基本のみが提供されます。 "Dublin" は WF の本質的なサポートに基づいて構築されており、より完全に便利で管理しやすい環境を提供します。 たとえば、SQL Server ベースの永続化ストアと追跡ストアと共に、"Dublin" には、これらのストアを操作するための管理ツールが用意されています。 IIS マネージャーの拡張機能として実装されたこのツールを使用すると、ユーザーは、永続化されたワークフローの調査と管理 (終了など)、実行される追跡の量の制御、追跡ログの確認などを行うことができます。

WF の既存の機能に加えて、"Dublin" は他のサービスも追加します。 たとえば、"Dublin" は実行中のワークフロー インスタンスを監視し、失敗したワークフロー インスタンスを自動的に再起動できます。 "Dublin" を使用した Microsoft の主な目標は明確です。IIS/WAS でホストされているワークフロー サービスを管理および監視するための便利なツールとインフラストラクチャのセットを提供します。

ASP.NET アプリケーションでのワークフロー サービスの使用

.NET アプリケーションの大半は、ASP.NET を使用していると言ってよいでしょう。 ワークフローを主流にすることは、WF を ASP.NET 開発者にとって魅力的な選択肢にすることを意味します。

以前のバージョンの WF では、多数の ASP.NET アプリケーションではワークフローのパフォーマンスが不十分でした。 ただし、.NET Framework 4 リリースでは、WF の設計者はテクノロジの重要な部分を再設計し、パフォーマンスを大幅に向上させた。 このリリースは、"Dublin" の登場と共に、WF ベースのアプリケーション (特にワークフロー サービス) を、ASP.NET 開発者にとってより実行可能なオプションにします。 図 14 は、この外観の簡単な図を示しています。

図 14: ASP.NET アプリケーションのビジネス ロジックは、ワークフロー サービス として実装できます

このシナリオでは、ASP.NET ページはアプリケーションのユーザー インターフェイスのみを実装します。 そのロジックは、ワークフロー サービスに完全に実装されます。 ワークフロー サービスでは、ASP.NET アプリケーションは単なる別のクライアントですが、ASP.NET アプリケーションでは、ワークフロー サービスは他のサービスのようになります。 このサービスは WF と WCF を使用して実装されていることに注意する必要はありません。

しかし、もう一度、大きな問題は、なぜこれを行うのですか? ASP.NET アプリケーションのロジックを通常の方法で記述するだけではなぜですか? WF (および WCF) を使用すると何が購入されますか? この時点で、これらの質問に対する答えのほとんどはおそらく明白ですが、まだ繰り返す価値があります。

  • アプリケーションのロジックをさまざまな ASP.NET ページに分散するのではなく、そのロジックを単一の統合ワークフロー内に実装できます。 特に大規模なサイトの場合、これにより、アプリケーションのビルドと保守が大幅に容易になります。
  • ASP.NET アプリケーションで状態を明示的に操作するのではなく、Session オブジェクトなどを使用する場合、開発者は WF ランタイムに依存してこれを行うことができます。 ASP.NET アプリケーションは、ワークフロー インスタンスごとにインスタンス識別子 (ユーザーごとに 1 つ) のみを追跡する必要があります (Cookie に格納するなど)。 アプリケーションがこの識別子を "Dublin" に提供すると、ワークフロー インスタンスが自動的に再読み込みされます。 その後、中断したところから実行が開始され、すべての状態が復元されます。
  • WF の他の利点は、並列処理の容易さ、組み込みの追跡、再利用可能なアクティビティの可能性、アプリケーションのロジックを視覚化する機能などにも適用されます。

ワークフロー サービスは特定のマシン上の特定のプロセスに関連付けられていないため、複数の "Dublin" インスタンス間で負荷分散できます。 図 15 は、この外観の例を示しています。

図 15 : レプリケートされた ASP.NET アプリケーションは、複数の "Dublin" インスタンスを使用してワークフロー サービスを実行できます。

この単純なシナリオでは、ASP.NET アプリケーションのページが 3 台の IIS サーバー コンピューターにレプリケートされます。 これらのページはユーザーとの対話を処理しますが、アプリケーションのビジネス ロジックは"Dublin" で実行されるワークフロー サービスとして実装されます。 "Dublin" 環境の 2 つのインスタンスが、それぞれ独自のコンピューター上で実行されています。 ユーザーからの最初の要求が入ると、ロード バランサーによって IIS の最上位インスタンスにルーティングされます。 この要求を処理する ASP.NET ページは、このビジネス ロジックのチャンクを実装するワークフロー サービスの操作を呼び出します。 これにより、WF ワークフローが図の一番上のコンピューターの "Dublin" インスタンスで実行を開始します。 このワークフローの関連するアクティビティが完了すると、呼び出しは ASP.NET ページに戻り、ワークフローは永続化されます。

ユーザーの 2 番目の要求は、IIS の別のインスタンスにルーティングされます。 このマシンの ASP.NET ページでは、最初の要求を処理したコンピューターとは別のコンピューター上の (永続化された) ワークフローで操作が呼び出されます。 これは問題ありません:"Dublin" は、同じサーバーと共有する永続化ストアからワークフロー インスタンスを読み込むだけです。 この再読み込みされたワークフロー サービスは、ユーザーの要求を処理し、中断した場所を取得します。

WF (および WCF) について理解し、この新しいスタイルでロジックを作成する方法を学習するには、いくつかの作業が必要です。 単純な ASP.NET アプリケーションでは、この学習曲線を登る価値がない可能性があります。 ただし、.NET を使用して大規模な Web アプリケーションを作成する場合は、少なくともワークフロー サービスとしてロジックを作成する可能性を考慮する必要があります。

クライアント アプリケーションでのワークフローの使用

これまでは、WF を使用してサーバー アプリケーションを作成することに重点を置いてきました。 しかし、このテクノロジは現在最も頻繁に使用されていますが、WF はクライアント アプリケーションにも役立ちます。 通常、クライアント コンピューターで実行されるコードは多数の同時ユーザーを処理する必要はありませんが、WF は引き続き使用できるため、この場合、スケーラビリティの側面はあまり追加されません。

たとえば、Windows フォームまたは Windows Presentation Foundation を使用して作成されたグラフィカル インターフェイスをユーザーに提示するクライアント アプリケーションについて考えてみましょう。 アプリケーションには、おそらく、ユーザーのマウス クリックを処理するイベント ハンドラーがあり、ビジネス ロジックがこれらのイベント ハンドラーに分散されている可能性があります。 これは、ASP.NET アプリケーションがロジックを別々のページのグループに分散させ、同じ課題を生み出すのとよく似ています。 たとえば、アプリケーションのフローを識別するのが難しい場合があり、開発者は、正しい順序で行われることを確認するためにチェックを挿入する必要がある場合があります。 ASP.NET アプリケーションと同様に、このロジックを統合 WF ワークフローとして実装すると、これらの問題に対処するのに役立ちます。

WF のその他の側面は、クライアントでも役立ちます。 たとえば、アプリケーションで複数のバックエンド Web サービスを並列で呼び出す必要がある場合や、追跡のメリットがあるとします。 サーバーと同様に、WF はこれらの課題に対処するのに役立ちます。 現在、WF アプリケーションの大半はサーバー上で実行されていますが、これが唯一の選択肢ではないことを認識することが重要です。

詳しく見る: Windows Workflow Foundation のテクノロジ

この概要の目的は、WF 開発者にすることです。 それでも、WF のテクノロジについてもう少し知ることは、ワークフローの方法を選択するのが適切なタイミングを決定するのに役立ちます。 したがって、このセクションでは WF の最も重要な部分について詳しく説明します。

ワークフローの種類

.NET Framework 4 では、WF 開発者は通常、最も外側のアクティビティを選択して、2 つの異なるワークフロー スタイルから選択します。 これらのアクティビティは次のとおりです。

  • シーケンス: アクティビティを順番に順番に実行します。 シーケンスには、If アクティビティ、While アクティビティ、およびその他の種類の制御フローを含めることができます。 ただし、前に進むことはできません。実行は常に前に進む必要があります。
  • フローチャート: シーケンスなどのアクティビティを 1 つずつ実行しますが、前の手順に制御を戻すこともできます。 WF の .NET Framework 4 リリースの新機能であるこのより柔軟なアプローチは、実際のプロセスのしくみと、ほとんどのユーザーの考え方の両方に近くなります。

シーケンスとフローチャートはどちらもワークフローの最も外側のアクティビティとして機能できますが、ワークフロー内で使用することもできます。 これにより、これらの複合アクティビティを任意の方法で入れ子にすることができます。

最初の 2 つのリリースでは、WF には、ステート マシンと呼ばれるワークフローの最も外側のアクティビティの別のオプションも含まれていました。 その名前が示すように、このアクティビティにより、開発者はステート マシンを明示的に作成し、そのステート マシンで外部イベントによってアクティビティがトリガーされます。 .NET Framework 4 の WF は大きな変更ですが、以前のリリースでほとんどのアクティビティを書き直し、新しいデザイナーを構築する必要がありました。 この作業のため、WF の作成者は、最初の .NET Framework 4 リリースからステート マシン アクティビティを提供しません。 (Microsoft のリソースでも制限はありません)。それでも、新しいフローチャート アクティビティは、以前にステート マシンを使用する必要がある多くの状況に対処する必要があります。

基本アクティビティ ライブラリ

ワークフローには、開発者が使用することを選択したアクティビティのセットを含めることができます。 たとえば、ワークフローにはカスタム アクティビティしか含めずに、完全に有効です。 それでも、これはあまり可能性が高くありません。 ほとんどの場合、WF ワークフローでは、基本アクティビティ ライブラリで提供されているものの少なくとも一部が使用されます。 .NET Framework 4 で WF によって提供される、より広く役立つ BAL アクティビティの中には、次のものが含まれます。

  • 割り当て: ワークフロー内の変数に値を割り当てます。
  • 補正: 実行時間の長いトランザクションで発生する問題を処理するなど、補正を行う方法を提供します。
  • DoWhile: アクティビティを実行し、条件を確認します。 条件が true である限り、アクティビティは繰り返し実行されます。
  • フローチャート: 順番に実行される一連のアクティビティをグループ化しますが、前の手順に制御を戻すこともできます。
  • ForEach: コレクション内の各オブジェクトに対してアクティビティを実行します。
  • If: 実行の分岐を作成します。
  • 並列: 複数のアクティビティを同時に実行します。
  • Persist: ワークフローを永続化するように WF ランタイムに明示的に要求します。
  • 選択: 一連のイベントを待機してから、最初のイベントに関連付けられているアクティビティのみを実行できます。
  • ReceiveMessage: WCF 経由でメッセージを受信します。
  • SendMessage: WCF 経由でメッセージを送信します。
  • シーケンス: 順番に実行される一連のアクティビティをグループ化します。 ワークフローの最も外側のアクティビティとして機能するだけでなく、シーケンスはワークフロー内でも役立ちます。 たとえば、While アクティビティには他のアクティビティを 1 つだけ含めることができます。 そのアクティビティが Sequence の場合、開発者は while ループ内で任意の数のアクティビティを実行できます。
  • Switch: 複数方向の実行分岐を提供します。
  • スロー: 例外を発生させます。
  • TryCatch: try/catch ブロックを作成して例外を処理できるようにします。
  • While: 条件が true である限り、1 つのアクティビティを実行します。

これは完全な一覧ではありません。.NET Framework 4 の WF には、さらに多くの情報が含まれています。 また、Microsoft は、オープン ソース プロジェクトのホスティング サイトである CodePlex で新しい WF アクティビティを利用できるようにする予定です。 たとえば、.NET Framework 4 リリースの直後に、ワークフローがデータベースのクエリや更新を発行したり、PowerShell コマンドを実行したりできるアクティビティを探します。

この一覧からわかるように、BAL は、従来の汎用プログラミング言語の機能を主に反映しています。 WF は汎用テクノロジを意図しているため、これは驚くべきではありません。 ただし、この概要で説明したように、WF ランタイムによって実行されるアクティビティに対するアプローチによって、アプリケーション開発者の生活が向上する場合があります。

.NET Framework 4 のワークフロー

.NET Framework のリリース 4 では、Windows Workflow Foundation が大幅に変更されます。 たとえば、BAL の活動が再書き込まれ、いくつかの新しいアクティビティが追加されました。 これにより、たとえば、多くのワークフローの実行速度が大幅に向上しますが、以前のバージョンの WF を使用して作成されたワークフローは、.NET 4 バージョンの WF ランタイムでは実行できないことも意味します。 これらの古いワークフローは、.NET Framework 4 ワークフローと共にそのまま実行できますが、破棄する必要はありません。 また、ワークフロー全体を含む、古いバージョンの WF を使用して作成されたアクティビティは、.NET Framework 4 の WF が提供する新しい相互運用アクティビティ内で実行される可能性があります。 これにより、古いワークフローのロジックを新しいワークフローで使用できます。

WF のこの新しいリリースでは、パフォーマンスの向上に加えて、他の興味深い変更も加わります。 たとえば、以前のバージョンの WF には、任意のコードを含むことができる Code アクティビティが含まれていました。 これにより、開発者はワークフローに必要な機能をほとんど追加できますが、これは少しスムーズなソリューションでした。 .NET Framework 4 では、WF の作成者はカスタム アクティビティの記述を大幅に簡素化し、コード アクティビティが削除されました。 新しい機能がカスタム アクティビティとして作成されるようになりました。

.NET Framework 4 リリースの変更は、2006 年の WF の元の外観以降で最も重要です。 ただし、開発者がワークフローを使用して効果的なアプリケーションを簡単に構築できるようにするという目標はすべて同じです。

結論

Windows Workflow Foundation は、多くのアプリケーションに本当の利点を提供します。 最初のリリースでは、WFは主にソフトウェアベンダーと和音を鳴らしました。 このテクノロジの元の化身は役に立ちましたが、メインストリームの企業での使用には実際には適していません。 .NET Framework 4 では、WF の作成者はこれを変更しようとしている。

WF と WCF を適切に連携させ、WF のパフォーマンスを向上させ、より優れたワークフロー デザイナーを提供し、"Dublin" を使用してフル機能のホスト プロセスを提供することで、Microsoft はワークフローを幅広いシナリオでより魅力的なものにしています。 Windows アプリケーション開発ドラマの専門プレーヤーとしての時代は、終わりに近づきます。 WF は中央のステージに向かいます。

作成者について

David Chappell は、カリフォルニア州サンフランシスコのシャペル & アソシエイツ のプリンシパル です。 スピーキング、ライティング、コンサルティングを通じて、世界中の人々が新しいテクノロジについて理解し、使用し、より良い意思決定を行えるように支援します。