4

並行して行うべきではないタスクがいくつかあります (たとえば、ファイルを開く、読み取る、書き込む、閉じるなど、順序があります...)

しかし...いくつかのタスクは買い物リストのようなものです。つまり、望ましい順序を持つことができますが、必須ではありません..通信や独立したドライバーのロードなどの例..

そのようなタスクについては、例外を管理するための Java のベスト プラクティスまたはパターンを知りたいです。

Javaの簡単な方法は次のとおりです。

 getUFO {
      try {
            loadSoundDriver();
            loadUsbDriver();
            loadAlienDetectorDriver();
            loadKeyboardDriver();    
  } catch (loadSoundDriverFailed) {
     doSomethingA;
  } catch (loadUsbDriverFailed) {
      doSomethingB;
  } catch (loadAlienDetectorDriverFailed) {
      doSomethingC;
  } catch (loadKeyboardDriverFailed) {
      doSomethingD;
  } 
}

しかし、アクションの 1 つに例外があり、次のアクションを試してみたい場合はどうでしょ うか??

私はこのアプローチを考えましたが、例外の適切な使用法ではないようです。機能するかどうかはわかりません。問題ではありません。本当にひどいです!!

getUFO {
       Exception ex=null;
 try {
       try{  loadSoundDriver();
       }catch (Exception e)  {  ex=e; }
       try{  loadUsbDriver();
       }catch (Exception e)  {  ex=e; }
       try{ loadAlienDetectorDriver();
       }catch (Exception e)  {  ex=e; }
       try{  loadKeyboardDriver()
       }catch (Exception e)  {  ex=e; }

       if(ex!=null)
       { throw ex;
        }
  } catch (loadSoundDriverFailed) {
     doSomethingA;
  } catch (loadUsbDriverFailed) {
      doSomethingB;
  } catch (loadAlienDetectorDriverFailed) {
      doSomethingC;
  } catch (loadKeyboardDriverFailed) {
      doSomethingD;
  } 
}

それを行うためのより良いプラクティスを見つけるのは複雑ではないようです..私はまだしませんでした

アドバイスをありがとう

4

4 に答える 4

5

イディオムの周りの実行を検討してください。

別のオプション(実際にはそれほど違いはありませんが、それらをさらに分離するだけです)は、各タスクを別々のスレッドで実行することです。

編集:

これが私が心に留めている種類のことです:

public interface LoadableDriver {
     public String getName();
     public void loadDriver() throws DriverException;
     public void onError(Throwable e);
}

public class DriverLoader {
     private Map<String, Exception> errors = new HashMap<String, Exception>();

     public void load(LoadableDriver driver) {
        try {
           driver.loadDriver();
        } catch (DriverException e) {
           errors.put(driver.getName(), e);
           driver.onError(e);
        }
     }

    public Map<String, Exception> getErrors() { return errors; }
}

public class Main {
     public void loadDrivers() {
           DriverLoader loader = new DriverLoader();
           loader.loadDriver(new LoadableDriver(){
                public String getName() { return "SoundDriver"; }
                public void loadDriver() { loadSoundDriver(); }
                public void onError(Throwable e) { doSomethingA(); }
           });
           //etc. Or in the alternative make a real class that implements the interface for each driver.
           Map<String, Exception> errors = loader.getErrors();
           //react to any specific drivers that were not loaded and try again.
      }
 }

編集:これは、ドライバーをクラスとして実装した場合のクリーンなJavaバージョンの最終的な外観です(これは、Java OOパラダイムがここでIMHOに期待するものです)。Main.loadDrivers()メソッドは次のように変更されます。

       public void loadDrivers(LoadableDriver... drivers) {
           DriverLoader loader = ...
           for(LoadableDriver driver : drivers) {
                 loader.load(driver);
           }
           //retry code if you want.
           Set<LoadableDriver> failures = loader.getErrors();
           if(failures.size() > 0 && tries++ > MAX_TRIES) {
               //log retrying and then:
               loadDrivers(drivers.toArray(new LoadableDriver[0]));
           }
       }

もちろん、オブジェクトは自給自足であるため(getName()メソッドも削除できますが、おそらくtoString()をオーバーライドする必要があります)、マップを使用しなくなりました。そのため、エラーはセットで返され、再試行します。 。各ドライバーが再試行する頻度を把握している場合は、再試行コードをさらに簡単にすることができます。

Javaは、よくできたC ++テンプレートほど見栄えがよくありませんが、それがJava言語の設計上の選択です。適切に行わないとコードの保守が困難になる可能性がある複雑な言語機能よりも単純さを優先します。

于 2010-04-23T16:21:26.853 に答える
3

これを試して:

protected void loadDrivers() {
  loadSoundDriver();
  loadUsbDriver();
  loadAlienDetectorDriver();
  loadKeyboardDriver();    
}

それで:

protected void loadSoundDriver() {
  try {
    // original code ...
  }
  catch( Exception e ) {
    soundDriverFailed( e );
  }
}

protected void soundDriverFailed( Exception e ) {
  log( e );
}

これにより、サブクラスに動作を変更する機会が与えられます。たとえば、サブクラスは、各ドライバーのロードを個別のスレッドに実装できます。メイン クラスは、ドライバーのロード方法を気にする必要はなく、メイン クラスのユーザーも気にする必要はありません。

于 2010-04-23T16:25:44.313 に答える
1

IMOの場合、例外が「無視できる」場合は、「loadSoundDriver」メソッドが例外をキャッチしてエラーを返すのが最適です。

次に、ものをロードする関数で、すべてのエラーを記録し、シーケンスの最後に、それらをどう処理するかを決定できます。[編集]このようなもの:

// init
MyError soundErr = loadSoundDriver();
MyError otherErr = loadOtherDriver();

if(soundErr!=null || otherErr !=null){
 // handle the error(s)
}
于 2010-04-23T16:20:57.847 に答える
0

すべてのロード操作を独自の try / catch ブロックで囲むだけです。

try {
  loadSoundDriver();
} catch (loadSoundDriverFailed) {
  doSomethingA;
} 

try {
  loadUsbDriver();
} catch (loadUsbDriverFailed) {
  doSomethingB;
}

  // ...

したがって、すべての例外を単独で処理し、次の操作の処理を続行できます。

于 2010-04-23T16:27:12.293 に答える