2011-12-17 4 views
2

私はJavaプログラムで違法な状態を処理すべき概念について現実的に考えています。 画像に処理ステップを実行するクラスを導入しました。例外スロー専用のメソッドを導入するのは悪い決定ですか?

public class ImageProcessor{ 
    public Image processImage(Image img){ 
     //do some processing steps 
    } 
} 

ここで、処理を行う前に画像を確認する別のクラスを紹介します。

public class ImageChecker{ 
    public void checkImage(Image img) throws ImageNotProcessableException{ 
     //for example, if the image has a width of 0 the full process 
     //should be broken, throw an exception 
     if (img.width=0) throw new ImageNotProcessableException("width is 0"); 

     //other conditions throwing also exceptions 

     // the image is fine, do nothing 
    } 
} 

2つのクラスは、Coordinatorクラスで使用する必要があります。

public class Coordinator{ 
    public void coordinate(Image img) throws ImageNotProcessableException{ 
     //initialize both 

     imageChecker.checkImage(img); //if no exception is throw the process can run 
     imageprocessor.processImage(img); 
    } 
} 

ここで問題は、例外(別のメソッドを定義する)を悪いコーディングスタイルとして扱うかどうかです。この設計の考え方は、例外処理を伴う処理コードの汚染を防ぐことでした。私はコーディネーターに例外を投げて欲しいと思っており、これは感覚的な方法かもしれないと思いました。あなたはどう思いますか?これは良い方法ですか、それとも反パターンですか? ありがとう!

+1

'imageChecker'は実際には複数の他のクラスにとって有用な別のクラスですか、それとも' imageProcessor'に固有のチェックですか?そして、 'imageChecker'にはいくつのメソッドがありますか? –

答えて

4

検証方法自体はとても良いアイデアです。前提条件と検証を1か所で確認し、実際の処理を別の場所で確認することで、懸念が非常に良好に分離されます。

ただし、使用方法が間違っています。 ImageProcessorは熱心にImageChecker.checkImage()に電話する必要があります。さもなければ、あなたのライブラリのクライアントはそれを呼び出して無効なイメージを渡すことを忘れるかもしれません。

また、@ Damien_The_Unbeliever *は、コードの構造について非常に良い点を示しています。できるだけ空想としてそれを作るために

私は2つの実装でImageProcessorインタフェースを作成します。ImageProcessorを標的とするオブジェクトを検証し、検証し、パスを実行し、実際の処理及びdecorator実装(ImageChecker)を行うもの。

このようにして、安全または高速(検証にはコストがかかります)の実装を使用できます。また、将来キャッシュやプロファイリングのような他の要素をchainに導入するかもしれません。

+1

私はまったく同じレスポンスを書いていました! –

+0

これはまさに私の意図でした。私は懸念を分けたい。私がアスペクトを使用していた場合、私はこれを一面で行いました。あなたがImageProcessorでImageCheckerを呼び出すことについて言及したのは、私の意図は、両方のクラスを完全に切り離し、コーディネーターの機能に加わることでした。コーディネーターを他のクライアントに提供したいと思います。 – martin

1

これは不合理ではありません。 checkImageが画像を処理しても問題ないかどうかをチェックする唯一の目的のために存在する場合、Exceptionをスローしてvoidを返すのではなく、ステータスコード/オブジェクトを返すのが妥当でしょう。例えば

ImageStatus status = checkImage(image); 
if (status.isOk()) { 
    processImage(image); 
} 

これは、ゼロ除算のチェックに類似して次のようになります。

if (y != 0) { 
    z = x/y; 
} 

チェック例外一般的に、あなたは、例えばそれを試してまで何かが成功するか失敗するかどうかを先験的に確認することができない状況に優れています、IOException

1

ここでは3つの質問がありますが、それらを分けると便利です。

  1. 呼び出し元に「ImageProcessor」というクラスまたは「コーディネータ」と呼ばれるクラスが表示されますか?

  2. メイン処理とは別の方法で入力の検証を行うのは良いですか?

  3. このコードでは、チェック例外または未チェック例外を使用する必要がありますか?

私の答えは次のようになります。

  1. あなたが公開するクラスまたはインタフェースのためにきれいに名前を使用してください。ですから、ここでは "ImageProcessor"は "Coordinator"よりもずっと良いです。 (「コーディネーター」は、公開したくない実装のように聞こえます)

  2. これは実装の決定です。物事をよりクリーンにするなら、いくつかのバリデーションロジックを別々のメソッドに分けるのはいいです。しかし、処理の後期段階で間違っている可能性のあるものをすべて前もって予測できると考えていることに注意する必要があります。実際の処理を行うメソッドは、初期のクイック検証が何を決定したとしても、例外をスローするのは自由でなければならず、できるだけ正確に失敗を記述することができます。また、不要なコードの重複であるため、2つの場所に検証コードを書くことを避けたいとします。だから、私はこの分離をすることについて少し懐疑的ですが、コードを見る必要があります。おそらく、実際の画像処理自体をさまざまなサブタスクに分割し、必要な時点で検証を行う方がよいでしょう。

  3. これは私たちの生涯ではなくならない古くからの例外的なJavaの例外の議論であり、ここで要約することは不可能です。しかし、コンセンサスは、例外をチェックするのではなく、ランタイム例外を使用してかなり強くシフトしていると思います。もちろん、従来のAPIでは引き続きチェック例外が使用されます。しかし、ほとんどの新しいコードでは、チェックされた例外ではなく、実行時の例外を使用する方が良いです。 (チェックされた例外は、例外ハンドラに到達する前にラップ、再ラップ、飲み込まれたり、他の方法で変形されたりする厄介な性質を持ち、すべてのスロー句を長くすることによって途中で多くの付随的なダメージを受けます)

関連する問題