How to approach the basic exception generated by the API method?

Let's say that I , dealing with , am forced to use a library API method that throws some kind of unreasonable base exception; for example, throw an exception in Java. Suppose I have no way to change the source of the library, and I have to deal with the basic exception when calling the API method from my own methods. In some context, my code might look like this without intervention:

public void myMethod() throws Exception { // I don't want to do this. someAPIObject.theirMethod(); // API method throwing base exception. } 

And here may be the API method I am referring to:

 public void theirMethod() throws Exception { // This is my problem. // Does stuff that could cause problems, but is // lazy and implicitly throws base exception. // Now it my problem! } 

My question is: what is the best way to deal with this basic exception thrown to my methods? I believe it is in my interest to somehow preserve all the source information about the exception when propagating something more useful than the basic exception. For example, I considered the ability to catch and save a basic exception in my own type of exception, and instead chose:

 public void myMethod() { try { someAPIObject.theirMethod(); // API method throwing base exception. } catch (Exception e) { throw new MySpecificException(e); // Re-throw my own exception. } } 

I'm not looking for opinions, but rather solid and direct evidence (pluses) as to why a particular solution is a good solution, as well as any cavaets (minuses). I'm focused on Java, but I'm curious about any general concepts or "best practices."

+6
source share
2 answers

This question will undoubtedly be closed as โ€œtoo broadโ€ or โ€œopinion-based,โ€ but I will write down my 2c before he does.

Your second code sample should (almost) always be on the way:

 public void myMethod() { try { someAPIObject.theirMethod(); // API method throwing base exception. } catch (Exception e) { throw new MySpecificException(e); // Re-throw my own exception. } } 

My main reason is that I do not want fuzzy abstraction . For example, let's say I have some kind of repository for accessing users with the following interface:

 public interface UserRepository { public User byId(UserId id); } 

And I have it implemented in the MySql database, so you have the following specific class:

 public class MySqlUserRepository implements UserRepository { public User byId(UserId id); } 

Inside this class, I will have to handle JDBC exceptions. If I just let them spread through the interface, for example:

 public interface UserRepository { public User byId(UserId id) throws SqlException; } 

Then the client of my code now knows that it is using JDBC in the background. If I complete this, as with you, then the underlying data store is fully encapsulated, which is one of the points of abstraction in the first place. If I provide an implementation that uses some other data store, for example. Redis, then SqlException does not make sense anymore, but I will need to update the contract so that now methods throw Exceptions that a specific data store can throw.

+3
source

Assuming you know the full list of subclasses of exceptions that the API can select, you might be better off hacking the type of exception with runtime checks and wrap the method in its own wrapper that throws certain exceptions.

Here's an example: let's say the API can call three specific subclasses of Exception โ€” namely, ExceptionOne , ExceptionTwo and ExceptionThree . You can create a wrapper as follows:

 class SomeApiWrapper { public void myMethod() throws ExceptionOne, ExceptionTwo, ExceptionThree { try { someAPIObject.theirMethod(); } catch (Exception e) { crackException(e); } } private static void crackException(Exception e) throws ExceptionOne, ExceptionTwo, ExceptionThree { if (e instanceof ExceptionOne) throw (ExceptionOne)e; if (e instanceof ExceptionTwo) throw (ExceptionTwo)e; if (e instanceof ExceptionThree) throw (ExceptionThree)e; throw new RuntimeException("Caught an exception of unexpected type", e); } } 

Your API users will not have to catch Exception (which is very bad) and save all the information embedded in the original exception.

+2
source

Source: https://habr.com/ru/post/980940/


All Articles