Explain Empty Catch

 class​ Logbook {
 
 static​ ​final​ Path LOG_FOLDER = Paths.get(​"/var/log"​);
 static​ ​final​ String FILE_FILTER = ​"*.log"​;
 
  List<Path> getLogs() ​throws​ IOException {
  List<Path> result = ​new​ ArrayList<>();
 
 try​ (DirectoryStream<Path> directoryStream =
  Files.newDirectoryStream(LOG_FOLDER, FILE_FILTER)) {
 for​ (Path logFile : directoryStream) {
  result.add(logFile);
  }
» } ​catch​ (NotDirectoryException e) {
 
  }
 
 return​ result;
  }
 }

In the last comparison of this chapter, we’re going back to catching exceptions. Above, you can see a different version of the LogBook example from the previous pages. It closes resources properly, but something else is strange: the catch block.

You should catch exceptions if and only if you can handle them in a meaningful way. The catch block contains the code that handles the exception. You can handle exceptions in many ways. For example, you can retry something else or just log that the exception occurred.

Sometimes, swallowing an exception and doing nothing is actually the right thing to do. Nevertheless, when we stumble upon an empty catch block, we always get a weird feeling: Is this a bug? Was the catch added unintentionally, for example by the IDE, and does it hide the exception? Or is it a feature? Did the programmer leave the catch block empty on intention?

In the end, we don’t know. An empty catch without any hint of why it’s empty always looks like a bug. We can’t know for sure that it’s been intended. That means we’ll have to waste precious programming time to double-check.

After all, better to be safe than sorry.

So how can we explain the intentions here?

 class​ Logbook {
 
 static​ ​final​ Path LOG_FOLDER = Paths.get(​"/var/log"​);
 static​ ​final​ String FILE_FILTER = ​"*.log"​;
 
  List<Path> getLogs() ​throws​ IOException {
  List<Path> result = ​new​ ArrayList<>();
 
 try​ (DirectoryStream<Path> directoryStream =
  Files.newDirectoryStream(LOG_FOLDER, FILE_FILTER)) {
 for​ (Path logFile : directoryStream) {
  result.add(logFile);
  }
» } ​catch​ (NotDirectoryException ignored) {
 // No directory -> no logs!
  }
 
 return​ result;
  }
 }

This looks much better. The catch block no longer signals to us that something might be wrong.

We achieved this with two changes.

First, we renamed the exception variable e to ignored. It’s more self-explanatory and states explicitly that we want to ignore the exception. This name is almost a convention. Modern IDEs understand it, too, and no longer warn that there’s an empty catch block.

And second, we add a comment why we ignore the exception. This is important, because others programmers will have it easier to comprehend this decision. Since it’s a sort of design decision, we suggest that you use a template here, similar to Document Implementation Decisions. The template we propose is CONDITION -> EFFECT. The condition captures the reason why the exception has been thrown and the effect states why we can swallow and ignore it.

You might say that the comment alone should be enough. But we recommend that you do the renaming and add the comment. Ultimately, the exception variable always needs a name and we should give it a better one than the generic e.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.190.211