POSA 本でアーキテクチャパターンを勉強しよう(3) - アーキテクチャパターン「混沌から構造へ」より「Pipes and Filters」
- パターンとは何か?
- アーキテクチャパターン「混沌から構造へ」より「Layers(レイヤパターン)」
- アーキテクチャパターン「混沌から構造へ」より「Pipes and Filters」
- アーキテクチャパターン「混沌から構造へ」より「Blackboard」
動的側面
POSA本ではパイプとフィルタの動的側面を4つのシナリオで紹介しています。一つ一つ見ていくことにしましょう。
シナリオ1はプッシュ型の受動フィルタと能動的なデータソースの組み合わせを説明したものです。データソースがデータをフィルタに伝えていき、データシンクに書き出すというものです。下図のように動作しますが、パイプが存在していません。
図「シナリオ1 - プッシュ型の受動フィルタ」
シナリオ2ではプル型の受動フィルタを説明したものです。データシンクがフィルタからデータを呼び出し、フィルタはデータソースからデータを呼び出すというものです。下図のように動作しますが、シナリオ1と同様にパイプが存在しません。
図「シナリオ2 - プル型の受動フィルタ」
シナリオ3はプッシュ型とプル型が混在した受動フィルタと受動的なデータソースとデータシンクが登場するケースを説明したものです。図では、二番目のフィルタが起点となって、フィルタを呼び出し、データソースから情報を取得し、順番にフィルタを実行したあとデータシンクに結果を書き出すという処理を説明しています。
図「シナリオ3 - プッシュ型とプル型が混在した受動フィルタ」
シナリオ4は能動フィルタを説明したものです。POSA本には典型的なパイプとフィルタの振る舞いと書かれています。各フィルタは独立したプロセスもしくはスレッドなどのアクティブオブジェクトとして振る舞い、パイプがバッファとして動作し、フィルタ間の同期を取ります。フィルタは能動的にデータソースやパイプからデータを取得し、能動的にデータシンクやパイプにデータを出力します。
図「シナリオ4 - 能動フィルタ」
実現手段
POSA本で紹介されているパイプとフィルタの実現手段について簡単に紹介します。(1) システムタスクを段階に分ける、(2) それぞれのパイプに引き渡されるフォーマットを定義する、(3) 各パイプ接続の実装方法を決定する、(4) フィルタを設計し実装する、(5) 例外処理を設計する、(6) 処理のパイプラインを設定するという流れでパイプとフィルタを実装します。
例外処理について少し補足します。パイプとフィルタの実装方法によっては、どこで例外処理を実装するか決定することが困難である場合があります。パイプラインコンポーネント間で状態を共有しないからです。UNIXの場合はstderr(標準エラー出力)が定義されていますが、このようなエラー出力先を定義することで例外を検知することは可能です。この方法で入力データの検証やリソースの制約による例外を検知することができますが、パイプラインが並列して動作している場合は、エラーメッセージが混合してしまう場合があります。
通常、パイプライン処理が失敗した場合、ユーザーがパイプライン処理を再起動する必要があります。しかし、データにタグをつけるか、パイプにデータをバッファしておいて、フィルタが例外を発生させた場合は、タグやバッファした情報を使って自動的にパイプライン処理を再スタートさせるという方法もあります。ただし、この戦略が取れないタスクや例外が存在することも事実です。
いずれにせよ、タスクや例外の種類によって戦略を変えなくてはならず、例外戦略はパイプとフィルタを採用する際の重要な課題と言えます。
バリエーション
パイプとフィルタにはteeとジョインパイプラインシステム(Tee and join pipeline systems)というバリエーションが存在します。これは、フィルタの一つの入力と一つの出力というパターンを変化させて、入出力を一つ以上にするというものです。
POSA本では、UNIXのteeとcommコマンドを例に挙げていました。teeコマンドは、入力を標準出力と名前付きパイプやファイルなどに同時に出力することができます。commは複数のファイルや名前付きパイプを読んで行の比較結果を返します。このようなパイプライン処理では、teeで一度分岐したパイプライン処理をcommで合流させることをしています。
結論
POSA本によると、パイプとフィルタには、「中間結果の再利用」「フィルタの交換可能性と再利用性」「組み合わせの変更可能性」「パイプラインのラピッドプロトタイピング」「並列処理による効率性」というメリットがあります。
少し補足します。「中間結果の再利用」とは、パイプライン処理途中に生成された中間結果を、複数のプログラムで処理するなどが可能になるということです。また、「パイプラインのラピッドプロトタイピング」とは、既存のフィルタを使うことでデータ処理システムのプロトタイピングを手軽に行うことができることを指します。
逆にデメリットとして、「状態の共有コストが高価」「並列の効果を得られない場合がある」「データ変換のオーバーヘッド」「例外処理が組み込みにくい」などが挙げられています。
「並列の効果を得られない場合がある」とは、フィルタの処理コストが小さい場合、コンテキストスイッチや複数のフィルタの同期を取る必要がある場合などのコストによって並列による処理能力向上コストが相殺される場合があるということです。また、「例外処理が組み込みにくい」とは、このパターンはグローバルに状態を共有するものではないのでどのコンポーネントで例外処理を行うか決めにくいという意味です。
まとめ
以上、アーキテクチャパターンの Pipes and Filters(パイプとフィルタ)でした。パイプとフィルタは、データストリームをパイプライン処理する際に採用されるパターンであり、フィルタの組み合わせと再利用性からシステムの柔軟性を実現するためのものです。パイプとフィルタは、ある程度複雑なシステムを構造的に開発するためのパターンであることからレイヤに近いパターンと言えます。
POSA本によると、レイヤとパイプとフィルタを比較すると、例外処理の容易さから信頼性が必要なシステムではレイヤを採用する方がよいと書かれています。ただし、パイプとフィルタはコンポーネントの再利用性と組み合わせの変更容易性に優れているという特徴があります。両者を比較する際には覚えておくとよいポイントだと思われます。
次回は「混沌から構造へ」の最後のパターンである Blackboard を紹介します。それでは!
1 2
このサイトについて
TrackBack URL :
