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.
source share