web-dev-qa-db-ja.com

メソッドパラメータや戻り値の型としてストリームを使用する

したがって、あるファイルタイプを別のファイルタイプに変換できる「トランスフォーマー」インターフェースがあるとします。また、ストリームを使用してTransformerにデータを提供したいとします。これが「ベストプラクティス」と見なされるアプローチです。

public InputStream transform(InputStream data);

OR

public void transform(InputStream originalData, OutputStream newData);

最初の方法は少し簡潔です(つまり、すぐに使用できる入力ストリームを取得します)。ただし、「ストリームの作成者は、それを閉じるものである必要があります」という原則全体に違反しているようです。

2番目の方法は、出力ストリームを処理するためにクライアント側でもう少し作業が必要ですが、場合によっては(たとえば、「newData」引数としてServletOutputStreamを渡す)、クライアントコードが処理する方が便利なようです。ストリームのすべての開閉。

私は2番目の方法に傾いていますが、私が遭遇したさまざまなAPIで両方が使用されているのを見たことがあります。

4
goodsquishy

入力Steamを返すと、データがそこから読み取られるときに、別のスレッドで実行される場合でも、継続的に計算を実行できます。これは、UNIXコマンドラインパイプに相当します。処理が完了するまでにかなりの時間がかかる場合は、処理時間を分散して(または別のコアに分流して)少しずつ結果を返すことで、ユーザーからその処理時間を効果的に隠します。変換の複数の段階を簡単に構築できます。

出力ストリームを渡すときは、古いpre-windows dos Promptを使用するのと同じです。ユーザーにデータを直接送信するだけであれば問題ありませんが、そうでない場合は、一時的にどこかに保存する必要があります(ファイルまたはByteArrayOutputStream)処理を続行する前に。これにより、出力が生成される前に遅延が発生し、複数のコアの利用が困難になり、リソースを不必要に使用します。

さらに、あなたはストリームのオープナーがそれを閉じるべきであるという一般的なルールがあると述べていますが、これは完全なルールではないと思います。 Java IOシステムが構築されているという規則は、ストリームのオープナーがそれを閉じる責任を負うべきである場合を除き、後でcloseメソッドも提供する別のオブジェクトでラップされます。この場合、オープナーは代わりにそのメソッドを呼び出し、オープナーの代わりに元のストリームを閉じる必要があります。 "これは、たとえば、BufferedInputStreamを使用する場合に行います。

これはすべて、前者が一般的に優先されることを示唆していますが、多くの複雑な変換の場合、後者は実装がはるかに簡単であることに注意してください(複数のスレッドを使用したくない場合)。これは場合によっては前者を支持するかもしれませんが、マルチスレッドソリューションが望ましい場合、後者のスタイルのコードは、独自のスレッドに配置し、通信にPiped * Streamペアを使用することにより、前者のインターフェースに適応できます。したがって、私は非常に単純なケース以外では前者が最良であると言いますが、単純なケースがあり、スレッドに関与したくない場合は、後者が許容可能で簡単かもしれません。

2
Jules

一般的に言って、出力パラメータの使用は悪い習慣と考えられています。結局のところ、戻り値は、関数が実行する計算の結果であることを意味しています。パラメータはその計算の入力であると想定されており、パラメータを介して結果をエクスポートすることは意味的に間違っています。

StackOverflow でより詳細な回答を見つけました。 C#に関する質問がありますが、答えは他のプログラミング言語にも適用されます。

問題に対してより具体的な回答が必要な場合は、メソッドの本文を投稿してください。

1
Phil