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?

10
  • related (possibly a duplicate): Is it always a good idea to divide large classes into smaller ones?
    – gnat
    Commented Jul 27, 2016 at 16:22
  • Thanks for the link, I'll take a look. I would really like to split this up because it's a pain to work with at the length it's at. However maybe I'm overcomplicating and should keep it as is. Commented Jul 27, 2016 at 16:23
  • Your example code still looks like it's accessing one class. Why doesn't it look more like api.repositories.api_call()? Commented Jul 27, 2016 at 16:24
  • >However, I want the final interface to be accessible from one namespace Commented Jul 27, 2016 at 16:25
  • 1
    What language are you using? Commented Jul 27, 2016 at 17:00

3 Answers 3

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.

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.

4
  • 1
    You're throwing around a lot of "laws" here, but at the end of the day, it's just a façade, so the problem amounts to "what is convenient, both for the end user and the programmer." Commented Jul 27, 2016 at 17:30
  • @RobertHarvey Not laws but principles. Principles are not mandatory. Those principles ammount to more maintainable code, which is convenient for both end users and programmers. Commented Jul 27, 2016 at 17:34
  • The thing is, for the end user I want it to be a god object of sorts. I want them to instantiate my API class, and be able to make any API call that they want to on that object. Commented Jul 27, 2016 at 17:48
  • 2
    @SpencerWood You might be right that "any API call from that object" is desirable to your users, but I rather doubt it. Often two or three objects will get you a good amount of conceptual segregation without forcing the user to grapple with a 20 object API. Finding a sweet spot is tricky, Think of the old ADO API. You could do almost anything you needed to with only "Connection" and "Recordset".
    – Mike
    Commented Jul 27, 2016 at 18:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.