Public API and App Organization#

Status#

Accepted

Context#

The original apps in the library (e.g. cache and monitoring) exposed a public API via __init__.py.

There are several problems with the original organization of the app code:

  • It was easy to forget to add new code to the public API, or ignore this requirement. For example, the Middleware didn’t follow the same process.

  • It was easy for a user of the library to mistakenly use code from a different module in the app, rather than through the public API.

Decision#

All implementation code should be moved to an internal module.

using monitoring as an example, the public API would be exposed as follows in edx_django_utils/monitoring/__init__.py:

from .internal.somemodule import ...

The benefits of this setup include:

  • A clear designation of what is part of the public API.

  • The ability to refactor the implementation without changing the API.

  • A clear reminder to developers adding new code that it needs to be exposed if it is public.

  • A clear reminder to developers using the library not to use code from the internal implementation.

Consequences#

Whenever a new class or function is added to the edx_django_utils public API, it should be implemented in the Django app’s internal module and explicitly imported in its __init__.py module.

Additionally, some existing apps will need to be refactored.