6 ms·
I usually like to have some Client object that’s responsible for establishing connections and performing unauthenticated interactions with the API. For things t
by teeray 6y ago
I usually like to have some Client object that’s responsible for establishing connections and performing unauthenticated interactions with the API. For things that require auth, I usually hang a Login / Authenticate method off of the Client that does whatever auth is necessary (you can even have multiple if there are multiple strategies). Those authentication methods usually return some kind of Session that has whatever token is ultimately produced as state. Authenticated methods hang off the Session object. EDIT: One other nice consequence of this design is that a separate Session makes it possible to have multiple simultaneous authenticated sessions while still maintaining the ability to call unauthenticated methods (e.g. Ping()).
I’ve found this prevents users of the library from having to shuttle around credentials and accidentally calling authenticated endpoints without credentials (since those methods don’t even exist off the Client). Also, if the Client is responsible for managing connections, it can also deal with things like rate limiting and whatnot. Finally, having a separate Session object eases testing, as you don’t have to mock the entirety of the auth flow (think of the complexity of OAuth 2.0) in order to get to a state that you care about. You can simply start with “given an authenticated session...”.
There are some other pieces that can be useful too depending on the abstractions available to you in your language of choice. Sometimes I’ll include a lower-level Request to do basic URL construction given a higher-level map of parameters. Corresponding Response objects can occasionally be useful too in those scenarios to unpack JSON / XML / w/e and present a higher-level construct to your methods.
- lezorich 6y agoI agree that a good idea is having a Client object, which main concern is to authenticate to the API and make the first connection. This Client should be in charge of creating instances of each resource available in the API. Don’t try to just offer a replica of the web API: you should figure out which are the most important use cases for the API and then offer them to your end-user. And it’s important to prioritize so you don’t clutter the public interface of the library. If you want to share common features across your resources, you could create a mixin with them. If you want to check an example, we released just a few days ago a Python-flavored client [1]. The code is readable and still in early stages; hopefully you can borrow a few ideas from there. These guidelines are mainly based on OOP, and Python with its data model (i.e. dunder methods) is flexible enough to offer a great user interface. [1]: https://github.com/fintoc-com/fintoc-python https://github.com/fintoc-com/fintoc-python Edit: wording