ほとんどのデータ処理は、コンポーネントのパイプラインとして想定でき、ある出力が別の入力にフィードされます。典型的な処理パイプラインは次のとおりです。
reader | handler | writer
この議論を始めるためのフォイルとして、各セグメントがオブジェクトであるこのパイプラインのオブジェクト指向の実装を考えてみましょう。オブジェクトにはとオブジェクトhandler
の両方への参照が含まれ、次のようなメソッドがあります。reader
writer
run
define handler.run:
while (reader.has_next) {
data = reader.next
output = ...some function of data...
writer.put(output)
}
概略的には、依存関係は次のとおりです。
reader <- handler -> writer
ここで、リーダーとハンドラーの間に新しいパイプラインセグメントを挿入したいとします。
reader | tweaker | handler | writer
繰り返しますが、このOO実装では、はオブジェクトtweaker
のラッパーになり、メソッドは次のようになります(疑似命令型コードでは)。reader
tweaker
define tweaker.has_next:
return reader.has_next
define tweaker.next:
value = reader.next
result = ...some function of value...
return result
これはあまり構成可能な抽象化ではないことがわかりました。いくつかの問題は次のとおりです。
tweaker
の左側でのみ使用できますhandler
。つまり、上記の実装を使用tweaker
してこのパイプラインを形成することはできません。リーダー| ハンドラー| 微調整| 作家
パイプラインの結合法則を利用したいので、このパイプラインは次のようになります。
リーダー| ハンドラー| 作家
次のように表すことができます:
reader | p
p
パイプラインはどこにありますかhandler | writer
。このOO実装では、handler
オブジェクトを部分的にインスタンス化する必要があります
- (1)の言い換えでは、オブジェクトはデータを「プッシュ」するか「プル」するかを知る必要があります。
これらの問題に対処するデータ処理パイプラインを作成するためのフレームワーク(必ずしもOOではない)を探しています。
私はこれにタグを付けました。関数型プログラミングの概念がここで役立つかもしれないと感じたからですHaskell
。functional programming
目標として、次のようなパイプラインを作成できると便利です。
handler1
/ \
reader | partition writer
\ /
handler2
いくつかの観点から、Unixシェルパイプは、次の実装上の決定により、これらの問題の多くを解決します。
パイプラインコンポーネントは、別々のプロセスで非同期的に実行されます
パイプオブジェクトは、「プッシャー」と「プラー」の間のデータの受け渡しを仲介します。つまり、データの書き込み速度が速すぎるライターと、読み取り速度が速すぎるリーダーをブロックします。
特別なコネクタ
<
を使用>
し、パッシブコンポーネント(つまりファイル)をパイプラインに接続します
特に、エージェント間でのスレッド化やメッセージパッシングを使用しないアプローチに興味があります。これを行うにはおそらくそれが最善の方法ですが、可能であればスレッド化は避けたいと思います。
ありがとう!