2

Here's the problem I'm trying to solve:

There's a rather large API I'm trying to write a wrapper class around. The simplest approach would be to make one class with a method representing each possible API call. This gets unwieldly though as the API is very large.

My first thought is to break up each API section into a separate class. If this was the Github API I might have a class for the users API and a class for the repositories API etc. However I want the final interface to be accessible from one namespace like so (this is in Python):

from my_api import APIClient

api = APIClient(api_token)

api.users_api_call()
api.repositories_api_call()

How should I achieve this? At first multiple inheritance seemed like a good option, but I'm unsure how to access things like an API token and other general properties/functions in the specialized classes, furthermore conventional wisdom suggests that MI is a poor design choice. What are some approaches to consider here?

3 Answers3

3

This sis quite common, at least in APIs I deal with.

First, you should create a class for each logical component of your API: users, transactions, tweets, etc etc. I recommend putting a good amount of thought into this. Clear organization is instrumental to a usable API. You should make all these classes publicly available, so users can import these components individually.

If you decide you really must have a single class to handle all API requests, just create a wrapper class API (choose a better name of course) that will hold handles to all of your other classes. Then you can do:

my_api = API(api_token)
my_api.users.get_users()

If you want to go a step further, you can even create forwarding methods such as

def get_users():
    users.get_users()

so your users can save some keystrokes.

gardenhead
  • 4,757
2

Since this is Python-specific, you can have the best of both worlds: a package which splits your API in manageable pieces, avoids the god-object, and lets it have a single import. The solution? Python packages typically have an __init__.py file, which can be used to express how the package imports things and presents them to the outside world.

Example:

package\
  __init__.py
  module_a.py
  module_b.py

in __init__.py:

__all__ = ['module_a', 'module_b']

Now you should be able to import them directly using import package.

See this post for additional information.

0

What you are trying to do is the Facade pattern, but by trying to wrap all of a giant API you are incurring in the God Object antipattern.

God objects violates Single responsbility principle and interface segregation principle and make it hard to comply with Open/Closed principle.

I don't know what language you are using but some languages support packages (a kind of namespace) so you can import several classes at once:

import com.apifacade.*;

My advice is that you model different classes with specific concerns like in the example you give: User, RepositoryList, Repository, etc. That way you will have less dependency problems.

Tulains Córdova
  • 39,570
  • 13
  • 100
  • 156