Child pages
  • APIs dos and don'ts
Skip to end of metadata
Go to start of metadata

API dos and don'ts 

This page describes some common errors and mistakes when working with APIs.

Dos

Create AbstractYourProjectAPIImpl. 

Create AbstractYourProjectAPIImpl. Always. There were not project yet, where a common abstract api implementation wasn't needed. And that common abstract api implementation should extends the one that we already have:

public AbstractFooAPIImpl extends AbstractAPIImpl{

 

Don'ts

Don't create exception types for each api. 

At least don't let them extend Exception if you do. Why? Because having incompatible exception types will force one api, that uses another api to catch that api's exceptions, and re-throw them. This will leave to a lot of boilerplate code. Since API is generally syndication of services, it doesn't matter which API through an Exception. Example: 

Consider we have 2 APIs, which depend on each other. 

public MessagingAPI extends API{
  MessageAO getMessage(MessageId id) throws MessagingAPIException;


public UserAPI extends API{
  UserAO getUser(UserId id) throws UserAPIException;


and the MessageAO like that:

public class MessageAO{
  private UserAO sender;
  private UserAO recipient;
  private String headline;
  private String message;

now to synthesize this MessageAO the MessagingAPI would perform something like this. 

try{
	Message message = messagingService.getMessage(...);
    message.setSender(userAPI.getUser(message.getSenderId());
    message.setRecipient(userAPI.getUser(message.getRecipientId());
}catch(MessagingServiceException e){
  throw new MessagingAPIException("Can't get message...");
}catch(UserAPIException e){
  throw new MessagingAPIException("Can't get user");
}

Obviously the second catch block is obsolete. If both APIs would declare to throw APIException, than it would be easy to throw the Exception through. 

Another advantage of declaring all exceptions as APIException is that than a general type of Exceptions can be used, like:

public class BackendFailureException extends APIException{
  public BackendFailureException(Exception cause){
     super("Error in backend, can't continue", cause);
  }
}

This would allow you to handle all backend errors, which you can't handle anyway, at once place. 

Of course, you can still have MessagingAPIException, and you can still use it, and even catch it, but not having it in the throws clause helps a lot. 

So the proper way to do it would be:

public MessagingAPI extends API{
  MessageAO getMessage(MessageId id) throws APIException, MessagingAPIException, MessageNotFoundException;


public UserAPI extends API{
  UserAO getUser(UserId id) throws APIException;

but:
 
public MessageAO getMessage(MessageId id) throws APIException{
  ....
  if (something_bad_happens){
     throw new MessagingAPIException(""); 
  }
}




 

 

 

  • No labels