Domain-driven design for HTTP resources
migduroli opened this issue · comments
Summary
HTTP resources as counterpart of SQLAlchemy resources
Motivation
At the moment, when we want to interact with a database, we know we can use the SQLAlchemyWorker
and the SQLAlchemyTableRepository
to represent the connection to the DB, and one of the tables, respectively. In particular, we reach an interface of the like:
async with worker:
worker.repository_name.action(*args, **kwargs)
So that the worker provides the context, under which the connection with the DB is established, and the transaction is initialised, to then interact with one of the tables via repository_name
(its type being SQLAlchemyTableRepository
) and one of the actions available for such a repository, and to finally, commit the changes and eventually close the connection when the context is closed.
With all this, we have a perfectly isolated way of working with the database tables in a DDD-compliant way. However DBs are not the only type of unit of work we can find. Indeed, one of the most common units of work found (implicitly) during the development of APIs is the interaction with another API (microservice). Thus, it's worth considering the implementation of a similar approach for HTTP/REST resources.
Proposed changes
With the previous context given, we propose a similar approach to that followed with the SQLAlchemyWorker
and SQLAlchemyTableRepository
. In this case we would have:
HTTPWorker
which will be in charge of initializing theflama.Client
with the correspondingbase_url
of the microservice to interact with.HTTPResourceRepository
which will be in charge of implementing the CRUDL methods to interact with a specific_resource
(enpoint) of the microservice we're interacting with.
The idea is that if we have an API at the URL, say, http://my_api_url.dev
and we want to make requests to the enpoint /user/
(representing the REST resource User
), then we would like to have the following communication interface:
class MyAPIWorker(HTTPWorker):
_url = "http://my_api_url.dev"
class User(HTTPResourceRepository):
_resource = "user"
...
async with worker:
await worker.user.create(...)