mardi 12 mars 2019

Third-party API wrapper in Java: how to design

Suppose, there's a site that provides an API, such as this:

  • Users post questions, answers on that site
  • You can make GET and POST calls
  • There are two types of authentication: weak (only gives read rights) and strong (gives both read and write rights)
  • Right now, I'd like to read users' questions and answers (only need weak access) and send them messages or post my own questions in the future (would need strong access)
  • The site's API has actions both to do with users (e.g. send a message) and with site in general (see about, see most popular questions)

What I have right now looks like this:

public class Wrapper  {
   private AccessToken accessToken;

   public Wrapper(...)  {
     //does some stuff
     //gets access token:
     getAccessToken(...);
   }    

   public AccessToken getAccessToken(...)  {
      AccessToken result;
      //gets access token, given the auth info provided as arguments
      accessToken = result;

      return result; 
   }

   public ArrayList<Question> getQuestions(User user)  {
       //gets user's questions, using the accessToken field
       //set's a user's questions field to the result and returns the result
   }

   public ArrayList<Answer> getAnswers(User user)  {
       //same as previous
   }

   public boolean sendMessage(User user)  {
      //sends a message, if current accessToken is strong
   }
}

and User class:

class User  {
  private String username;

  private ArrayList<Question> questions;
  private ArrayList<Answer> answers;

  public User(String username) {this.username=username;}    

  //getters and setters
}

So, to use it you would use something like this:

public class Main  {
  public static void main(String[] args)  {
     Wrapper wrapper = new Wrapper(...);
     ArrayList<Question> questions = wrapper.getQuestions(new User("username"));
     wrapper.sendMessage(new User("username2"));
  }
}

I have issues with this.

First of all, class User feels superfluous, since all the functionality is inside the Wrapper class.

Second, I wonder if what my methods do is wright - from the design's perspective: in getAccessToken I both return AccessToken and set a Wrapper's field accessToken to the result. Is this the right approach? Or should the method only return access token and then that result should be assigned to a class' field explicitly? Same goes for the getQuestions and getAnswers methods: they both get the ArrayLists, return them and assign a User's field to the result - all inside the single method.

I would like for a User class to have some meaning. I thought of doing it something like that:

    Wrapper wrapper = new Wrapper(...);

    User user = new User("username");
    user.getQuestions(wrapper.getAccessToken());
    user.sendMessage(wrapper.getAccessToken());

So, the Wrapper class would only serve as a place to get an access token from, which doesn't feel right as well. I could place the access token functionality inside the User class and use it like this:

     User user = new User("username", ...);
     user.getQuestions();
     user.sendMessage();

The User's constructor would take both username and auth data, would get access token and store it inside a user and then use it when getting questions/answers or sending messages. I could make the accessToken field inside User class static so that all users shared the same token.

However, there are actions the site API provides, that aren't obviously connected with users: for instance, getting the site's most popular questions. It feels right to use a generic Wrapper class for that purpose which contradicts with the previous approach.

I'm new to this and only know a couple design patterns. Perhaps, there are widespread patterns that are to be used for this type of problem? Any help/advice is appreciated.

Aucun commentaire:

Enregistrer un commentaire