Обработка исключений Java в непоследовательных задачах (шаблон / хорошая практика) - PullRequest
4 голосов
/ 23 апреля 2010

Есть некоторые задачи, которые не следует выполнять параллельно (например, открытие файла, чтение, запись и закрытие, на это есть порядок ...)

Но ... Некоторые задачи больше похожи на список покупок, я имею в виду, что они могут иметь желаемый заказ, но это не обязательно .. Пример в общении или загрузке независимых драйверов и т. Д.

Для такого рода задач, Я хотел бы знать лучшие практики Java или шаблон для управления исключениями ..

Простой способ Java:

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

Но как насчет исключения в одном из действий, но при желании попробуйте со следующими ??

Я думал, что такой подход, но не похоже, что это хорошее применение для исключений Я не знаю, работает ли это, не имеет значения, это действительно ужасно !!

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 ]

5 голосов
/ 23 апреля 2010

Рассмотрим выполнение вокруг идиомы .

Другой вариант (который на самом деле не так уж отличается, просто их больше разделяет) - выполнять каждую задачу в отдельном потоке.

Редактировать:

Вот что я имею в виду:

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 - предпочтение простоте, а не сложным функциям языка, которые могут усложнить поддержку кода с течением времени, если не будут выполнены должным образом.

3 голосов
/ 23 апреля 2010

Попробуйте это:

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 );
}

Это дает подклассам шанс изменить поведение. Например, подкласс может реализовать загрузку каждого драйвера в отдельном потоке. Основной класс не должен заботиться о том, как загружаются драйверы, равно как и пользователи основного класса.

1 голос
/ 23 апреля 2010

IMO, для вашего случая, если исключение "игнорируется", лучше всего, если метод "loadSoundDriver" перехватывает исключение и просто возвращает ошибку.

Затем в функции, которая загружает вещи, вы можете записать все ошибки и в конце последовательности решить, что с ними делать. [редактировать] Примерно так:

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

if(soundErr!=null || otherErr !=null){
 // handle the error(s)
}
0 голосов
/ 23 апреля 2010

Просто окружите каждую отдельную операцию загрузки собственным блоком try / catch.

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

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

  // ...

Таким образом, вы можете обработать каждое исключение отдельно и продолжить обработку операций oder.

...