xref: /aosp_15_r20/external/pigweed/docs/facades.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _docs-facades:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker==================
4*61c4878aSAndroid Build Coastguard WorkerFacades & backends
5*61c4878aSAndroid Build Coastguard Worker==================
6*61c4878aSAndroid Build Coastguard WorkerThis page explains what "facades" and "backends" mean in the context of Pigweed
7*61c4878aSAndroid Build Coastguard Workerand provides guidelines on when to use them.
8*61c4878aSAndroid Build Coastguard Worker
9*61c4878aSAndroid Build Coastguard Worker.. _docs-facades-definition:
10*61c4878aSAndroid Build Coastguard Worker
11*61c4878aSAndroid Build Coastguard Worker------------------------------
12*61c4878aSAndroid Build Coastguard WorkerWhat are facades and backends?
13*61c4878aSAndroid Build Coastguard Worker------------------------------
14*61c4878aSAndroid Build Coastguard Worker.. _top-down approach: https://en.wikipedia.org/wiki/Bottom%E2%80%93up_and_top%E2%80%93down_design
15*61c4878aSAndroid Build Coastguard Worker
16*61c4878aSAndroid Build Coastguard WorkerLet's take a `top-down approach`_, starting with high-level definitions.
17*61c4878aSAndroid Build Coastguard WorkerIn the context of a Pigweed module:
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard Worker* A facade is an API contract of a module that must be satisfied at compile-time,
20*61c4878aSAndroid Build Coastguard Worker  i.e. a swappable dependency that changes the implementation of an API at
21*61c4878aSAndroid Build Coastguard Worker  compile-time.
22*61c4878aSAndroid Build Coastguard Worker* A backend is an implementation of a facade's contract.
23*61c4878aSAndroid Build Coastguard Worker
24*61c4878aSAndroid Build Coastguard WorkerUsually, the facade and the backend are in different modules. One module
25*61c4878aSAndroid Build Coastguard Workerexposes the facade contract, and another module is the backend that implements
26*61c4878aSAndroid Build Coastguard Workerthe facade contract. The naming pattern that Pigweed follows is
27*61c4878aSAndroid Build Coastguard Worker``{facade_name}_{backend_name}``.
28*61c4878aSAndroid Build Coastguard Worker
29*61c4878aSAndroid Build Coastguard WorkerFacades, by design, don't need to be configured until they're actually used.
30*61c4878aSAndroid Build Coastguard WorkerThis makes it significantly easier to bring up features piece-by-piece.
31*61c4878aSAndroid Build Coastguard Worker
32*61c4878aSAndroid Build Coastguard WorkerExample: pw_log and pw_log_string
33*61c4878aSAndroid Build Coastguard Worker=================================
34*61c4878aSAndroid Build Coastguard WorkerHere's a step-by-step walkthrough of how a real backend module implements
35*61c4878aSAndroid Build Coastguard Workeranother module's facade.
36*61c4878aSAndroid Build Coastguard Worker
37*61c4878aSAndroid Build Coastguard Worker.. _//pw_log/public/pw_log/log.h: https://cs.opensource.google/pigweed/pigweed/+/main:pw_log/public/pw_log/log.h
38*61c4878aSAndroid Build Coastguard Worker.. _//pw_log_string/public_overrides/pw_log_backend/log_backend.h: https://cs.opensource.google/pigweed/pigweed/+/main:pw_log_string/public_overrides/pw_log_backend/log_backend.h
39*61c4878aSAndroid Build Coastguard Worker
40*61c4878aSAndroid Build Coastguard Worker* :ref:`module-pw_log` is a module that exposes a facade. The macros listed in
41*61c4878aSAndroid Build Coastguard Worker  :ref:`module-pw_log-macros` represent the API of the module.
42*61c4878aSAndroid Build Coastguard Worker* The ``#include "pw_log/log_backend.h"`` line in `//pw_log/public/pw_log/log.h`_
43*61c4878aSAndroid Build Coastguard Worker  represents the facade contract of ``pw_log``.
44*61c4878aSAndroid Build Coastguard Worker* :ref:`module-pw_log_string` is a backend module, It implements the
45*61c4878aSAndroid Build Coastguard Worker  ``pw_log/log_backend.h`` facade contract in
46*61c4878aSAndroid Build Coastguard Worker  `//pw_log_string/public_overrides/pw_log_backend/log_backend.h`_.
47*61c4878aSAndroid Build Coastguard Worker* In the build system there is a variable of some sort that specifies the
48*61c4878aSAndroid Build Coastguard Worker  backend. In Bazel there's a `label
49*61c4878aSAndroid Build Coastguard Worker  flag <https://bazel.build/extending/config#label-typed-build-settings>`_
50*61c4878aSAndroid Build Coastguard Worker  at ``//pw_log:backend``. In CMake there's a ``pw_log_BACKEND`` variable set
51*61c4878aSAndroid Build Coastguard Worker  to ``pw_log_string``. In GN there's a ``pw_log_BACKEND`` variable set to
52*61c4878aSAndroid Build Coastguard Worker  ``dir_pw_log_string``.
53*61c4878aSAndroid Build Coastguard Worker
54*61c4878aSAndroid Build Coastguard Worker.. note::
55*61c4878aSAndroid Build Coastguard Worker
56*61c4878aSAndroid Build Coastguard Worker   There are a few more steps needed to get ``pw_log_string`` hooked up as the
57*61c4878aSAndroid Build Coastguard Worker   backend for ``pw_log`` but they aren't essential for the current discussion.
58*61c4878aSAndroid Build Coastguard Worker   See :ref:`module-pw_log_string-get-started-gn` for the details.
59*61c4878aSAndroid Build Coastguard Worker
60*61c4878aSAndroid Build Coastguard WorkerExample: Swappable OS libraries
61*61c4878aSAndroid Build Coastguard Worker===============================
62*61c4878aSAndroid Build Coastguard WorkerThe facade and backend system is similar to swappable OS libraries: you can
63*61c4878aSAndroid Build Coastguard Workerwrite code against ``libc`` (for example) and it will work so long as you have
64*61c4878aSAndroid Build Coastguard Workeran object to link against that has the symbols you're depending on. You can
65*61c4878aSAndroid Build Coastguard Workerswap in different versions of ``libc`` and your code doesn't need to know about
66*61c4878aSAndroid Build Coastguard Workerit.
67*61c4878aSAndroid Build Coastguard Worker
68*61c4878aSAndroid Build Coastguard WorkerA similar example from Windows is ``d3d9.dll``. Developers often swap this DLL
69*61c4878aSAndroid Build Coastguard Workerwith a different library like ReShade to customize shading behavior.
70*61c4878aSAndroid Build Coastguard Worker
71*61c4878aSAndroid Build Coastguard WorkerCan a module have multiple facades?
72*61c4878aSAndroid Build Coastguard Worker===================================
73*61c4878aSAndroid Build Coastguard WorkerYes. The module-to-facade relationship is one-to-many. A module can expose
74*61c4878aSAndroid Build Coastguard Worker0, 1, or many facades. There can be (and usually are) multiple backend modules
75*61c4878aSAndroid Build Coastguard Workerimplementing the same facade.
76*61c4878aSAndroid Build Coastguard Worker
77*61c4878aSAndroid Build Coastguard WorkerIs the module facade the same thing as its API?
78*61c4878aSAndroid Build Coastguard Worker===============================================
79*61c4878aSAndroid Build Coastguard WorkerNo. It's best to think of them as different concepts. The API is the interface
80*61c4878aSAndroid Build Coastguard Workerthat downstream projects interact with. There's always a one-to-one relationship
81*61c4878aSAndroid Build Coastguard Workerbetween a module and its API. A facade represents the build system "glue" that
82*61c4878aSAndroid Build Coastguard Workerbinds a backend to an API.
83*61c4878aSAndroid Build Coastguard Worker
84*61c4878aSAndroid Build Coastguard WorkerThis is a common point of confusion because there are a few modules that
85*61c4878aSAndroid Build Coastguard Workerblur this distinction. Historically, the facade comprised the API as well as
86*61c4878aSAndroid Build Coastguard Workerthe build system concept. We're moving away from this perspective.
87*61c4878aSAndroid Build Coastguard Worker
88*61c4878aSAndroid Build Coastguard WorkerAre Pigweed facades the same as the GoF facade design pattern?
89*61c4878aSAndroid Build Coastguard Worker==============================================================
90*61c4878aSAndroid Build Coastguard Worker.. _facade pattern: https://en.wikipedia.org/wiki/Facade_pattern
91*61c4878aSAndroid Build Coastguard Worker
92*61c4878aSAndroid Build Coastguard WorkerThere are some loose similarities but it's best to think of them as different
93*61c4878aSAndroid Build Coastguard Workerthings. The goal of the Gang of Four `facade pattern`_ is to compress some
94*61c4878aSAndroid Build Coastguard Workerugly, complex API behind a much smaller API that is more aligned with your
95*61c4878aSAndroid Build Coastguard Workernarrow business needs. The motivation behind some Pigweed facades is loosely
96*61c4878aSAndroid Build Coastguard Workerthe same: we don't want a device HAL to leak out into your include paths when
97*61c4878aSAndroid Build Coastguard Workera facade is implemented.
98*61c4878aSAndroid Build Coastguard Worker
99*61c4878aSAndroid Build Coastguard Worker------------------------------
100*61c4878aSAndroid Build Coastguard WorkerWhy does Pigweed have facades?
101*61c4878aSAndroid Build Coastguard Worker------------------------------
102*61c4878aSAndroid Build Coastguard WorkerPigweed's facades are basically a pattern that builds off the ideas of
103*61c4878aSAndroid Build Coastguard Worker`link-time substitution <https://bramtertoolen.medium.com/91ffd4ef8687>`_.
104*61c4878aSAndroid Build Coastguard WorkerLink-time substitution only allows you to replace one source file with another,
105*61c4878aSAndroid Build Coastguard Workerwhereas facades enable substituting program elements defined in *header files*.
106*61c4878aSAndroid Build Coastguard Worker
107*61c4878aSAndroid Build Coastguard WorkerPigweed facades enable implementation flexibility with zero performance cost.
108*61c4878aSAndroid Build Coastguard WorkerThere are two ways to look at this. Continuing with the ``pw_log`` example:
109*61c4878aSAndroid Build Coastguard Worker
110*61c4878aSAndroid Build Coastguard Worker* Organizations can reuse more code across projects by adopting the ``pw_log``
111*61c4878aSAndroid Build Coastguard Worker  API as their logging layer. Facades enable each project to customize how
112*61c4878aSAndroid Build Coastguard Worker  its logs are handled.
113*61c4878aSAndroid Build Coastguard Worker* For projects that want to integrate with ``pw_log`` but cannot adopt its
114*61c4878aSAndroid Build Coastguard Worker  API, facades can wrap the existing API which enables Pigweed to be compatible
115*61c4878aSAndroid Build Coastguard Worker  with the existing system.
116*61c4878aSAndroid Build Coastguard Worker
117*61c4878aSAndroid Build Coastguard WorkerTwo of the major aspects of "implementation flexibility" enabled by facades are:
118*61c4878aSAndroid Build Coastguard Worker
119*61c4878aSAndroid Build Coastguard Worker* Portability. For example, ``pw_sync`` needs platform-specific
120*61c4878aSAndroid Build Coastguard Worker  implementations to work correctly.
121*61c4878aSAndroid Build Coastguard Worker* Customized behavior. For example, you can make a fully portable ``pw_log``
122*61c4878aSAndroid Build Coastguard Worker  implementation, but what makes it special is the ability to tune it to your
123*61c4878aSAndroid Build Coastguard Worker  needs.
124*61c4878aSAndroid Build Coastguard Worker
125*61c4878aSAndroid Build Coastguard WorkerWhy compile-time?
126*61c4878aSAndroid Build Coastguard Worker=================
127*61c4878aSAndroid Build Coastguard WorkerResolving facades and backends at compile-time enables:
128*61c4878aSAndroid Build Coastguard Worker
129*61c4878aSAndroid Build Coastguard Worker* Call-site control from backends.
130*61c4878aSAndroid Build Coastguard Worker* Static allocation of backend-provided types.
131*61c4878aSAndroid Build Coastguard Worker* Explicit backend includes so it’s visually obvious you’re poking through
132*61c4878aSAndroid Build Coastguard Worker  abstraction.
133*61c4878aSAndroid Build Coastguard Worker
134*61c4878aSAndroid Build Coastguard Worker--------------------------------
135*61c4878aSAndroid Build Coastguard WorkerWhen to use facades and backends
136*61c4878aSAndroid Build Coastguard Worker--------------------------------
137*61c4878aSAndroid Build Coastguard WorkerIf you're trying to use a Pigweed module, and that module exposes a facade,
138*61c4878aSAndroid Build Coastguard Workerthen you've got no choice: you've got to hook up a backend to fulfill that
139*61c4878aSAndroid Build Coastguard Workerfacade contract or else the module won't work.
140*61c4878aSAndroid Build Coastguard Worker
141*61c4878aSAndroid Build Coastguard WorkerWhen to roll your own facades and backends
142*61c4878aSAndroid Build Coastguard Worker==========================================
143*61c4878aSAndroid Build Coastguard Worker* You need a global function or macro.
144*61c4878aSAndroid Build Coastguard Worker* You absolutely must avoid the overhead of virtual functions.
145*61c4878aSAndroid Build Coastguard Worker
146*61c4878aSAndroid Build Coastguard WorkerWhen to NOT roll your own facades and backends
147*61c4878aSAndroid Build Coastguard Worker==============================================
148*61c4878aSAndroid Build Coastguard Worker* If you can afford the runtime cost of dependency injection, use that.
149*61c4878aSAndroid Build Coastguard Worker  In all other cases where link-time subsitution will work, use that.
150*61c4878aSAndroid Build Coastguard Worker  Only if the API contract requires a backend to provide a header (which
151*61c4878aSAndroid Build Coastguard Worker  link-time substitution doesn't let you do) should you reach for a facde.
152*61c4878aSAndroid Build Coastguard Worker* You're trying to use globals to avoid dependency injection. Use
153*61c4878aSAndroid Build Coastguard Worker  the dependency injection! It makes testing much easier.
154*61c4878aSAndroid Build Coastguard Worker* Your needs can be served by a standard mechanism like virtual interfaces.
155*61c4878aSAndroid Build Coastguard Worker  Use the standard mechanism.
156