+1  A: 

IMO, for your case, if the exception is "ignorable" it's best if the "loadSoundDriver" method catches the exception and simply returns an error.

Then in the function that loads stuff, you can record all the errors and at the end of the sequence, decide what to do with them. [edit] Something like this:

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

if(soundErr!=null || otherErr !=null){
 // handle the error(s)
}
Virgil
+4  A: 

Consider the execute around idiom.

Another option (which isn't really all that different, it just decouples them more) is to do each task in a separate thread.

Edit:

Here is the kind of thing I have in mind:

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.
      }
 }

Edit: This is what a clean Java version would ultimately look like if you implemented the drivers as classes (which is what the Java OO paradigm would expect here IMHO). The Main.loadDrivers() method would change like this:

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

Of course I no longer use a map because the objects would be self-sufficient (you could get rid of the getName() method as well, but probably should override toString()), so the errors are just returned in a set to retry. You could make the retry code even simpler if each driver was responsible for knowing how often it should it retry.

Java won't look as nice as a well done C++ template, but that is the Java language design choice - prefer simplicity over complex language features that can make code hard to maintain over time if not done properly.

Yishai
I think he updated the question; the execute around idiom is a bit more complicated than necessary in this case (no parameters, no clean-up).
Dave Jarvis
@Dave, although there is no clean-up, there is exception handling which is kind of the same thing (as in you need execute around to handle it). I'll try to stub out what I have in mind.
Yishai
This approach seems to be really more complex, I am tempted to think there is no any way to do it clean with java (in C++ I could write some macros to at least keep the visible code very clean)
Hernán Eche
Well it is definitely verbose (see my link where Jon Skeet explains why it is so painful in Java) but it handles the extra scenarios you ask for - retry and custom error handling. If the goal was to make that routine nice, start with having each driver implement that interface. Then it would start to get very clean. Have the driver able to be a key in the Map, even cleaner, and then turn the loading into a recursive method, even better. What this code does gain you over your version is that it is much less error prone when adding drivers than the other version. I'll write up a "clean version."
Yishai
+2  A: 

Try this:

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

Then:

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

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

This gives subclasses a chance to change the behaviour. For example, a subclass could implement loading each driver in a separate thread. The main class need not care about how the drivers are loaded, nor should any users of the main class.

Dave Jarvis
+1 Your solution is actually abound the same as mine, just better :)
Virgil
A: 

Just surround every single load operation with its own try / catch block.

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

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

  // ...

So you can handle every exception by itself and continue processing the oder operations.

Florian Gutmann
I have already put that way, like the ugly one, I was searching for a clean alternative
Hernán Eche