Skip to content

Commit 12f9b38

Browse files
committed
docs: Add slot naming and life cycle ADR
1 parent aae46b3 commit 12f9b38

File tree

1 file changed

+188
-0
lines changed

1 file changed

+188
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
====================================
2+
3. Plugin Slot Naming and Life Cycle
3+
====================================
4+
5+
Status
6+
======
7+
8+
Accepted
9+
10+
11+
Context
12+
=======
13+
14+
The Frontend Plugin Framework introduced the concept of plugin slots as a way
15+
to customize micro-frontends. Slots are defined in each application's codebase
16+
with React, currently taking the form:
17+
18+
<PluginSlot id="arbitrary_slot_name">
19+
...
20+
</PluginSlot>
21+
22+
Operators can subsequently insert plugins into this slot by referencing
23+
"arbitrary_slot_name" in configuration as follows:
24+
25+
pluginSlots: {
26+
arbitrary_slot_name: {
27+
plugins: [{
28+
op: PLUGIN_OPERATIONS.Insert,
29+
widget: {
30+
id: 'arbitrary_plugin_name',
31+
...
32+
}
33+
}]
34+
}
35+
}
36+
37+
However, the following concerns were identified in relation to completely
38+
arbitrary slot names:
39+
40+
1. The codebase can become progressively littered with slot names that are
41+
unintuitively or inconsistently named, making it harder to document,
42+
maintain, and use them
43+
44+
2. There is no expectation that one should be able to infer purpose and
45+
location from the slot name
46+
47+
3. While Frontend Plugin Framework supports defining multiple slots with the
48+
same name in a frontend app, as the number of slots across the codebase
49+
increases it becomes harder and harder for developers to avoid introducing
50+
accidental name collisions
51+
52+
4. Without a versioning scheme, there's no way to modify a slot's API without
53+
making an implicit breaking change
54+
55+
This is a common problem in computer science, one that has often been addressed
56+
by use of `reverse domain name notation`_. It can be seen everywhere, from
57+
Android package names to Open edX's own specification for `server event
58+
types`_.
59+
60+
.. _reverse domain name notation: https://en.wikipedia.org/wiki/Reverse_domain_name_notation
61+
.. _server event types: https://docs.openedx.org/projects/openedx-proposals/en/latest/architectural-decisions/oep-0041-arch-async-server-event-messaging.html#id5
62+
63+
This technique allows for namespace uniqueness within a self-documentated
64+
hierarchy. For instance, take this fictitious slot name that uses said
65+
notation:
66+
67+
org.openedx.frontend.layout.header.v1
68+
69+
Even without further information, it's possible to tell that:
70+
71+
* The slot belongs to an app in the Open edX org
72+
* It's a frontend app
73+
* It's in the app's layout module
74+
* The slot probably wraps the header
75+
* This is version 1 of the slot, which indicates changes are possible in the
76+
future
77+
78+
And last but not least:
79+
80+
* There's little chance that a slot with the same name exists anywhere in the
81+
codebase other than where the layout header is defined
82+
83+
Based on this concept, this ADR aims to define rules that govern how developers
84+
maintain plugin slots in Open edX frontend apps throughout their lifecycle. In
85+
particular, when adding, deprecating, or removing plugin slots.
86+
87+
88+
Decisions
89+
=========
90+
91+
1. Naming format
92+
----------------
93+
94+
The full name of a plugin slot will be a ``string`` that follows the following
95+
format:
96+
97+
{Reverse DNS}.{Subdomain}.{Module}.{Identifier}.{Version}
98+
99+
Where:
100+
101+
* *Reverse DNS* is always ``org.openedx``
102+
* *Subdomain* is always ``frontend``
103+
* *Module* denotes the frontend module where the slot is exposed, such as
104+
``courseware``, or ``authoring``
105+
* *Identifier* is a snake-case string that identifies the slot, which must be
106+
unique for the module that contains it
107+
* *Version* is either the string `beta`, denoting a slot with a yet unstable
108+
API, or a monotonically increasing integer prefaced by a `v` and starting
109+
with `v1`.
110+
111+
For example:
112+
113+
* org.openedx.frontend.layout.footer.beta
114+
* org.openedx.frontend.courseware.navigation_sidebar.v2
115+
116+
In practice, this is what the slot definition will look like:
117+
118+
<PluginSlot id="org.openedx.frontend.courseware.navigation_sidebar.v2">
119+
...
120+
</PluginSlot>
121+
122+
And this is how operators would configure it:
123+
124+
pluginSlots: {
125+
org.openedx.frontend.courseware.navigation_sidebar.v2: {
126+
plugins: [{
127+
op: PLUGIN_OPERATIONS.Insert,
128+
widget: {
129+
id: 'arbitrary_plugin_name',
130+
...
131+
}
132+
}]
133+
}
134+
}
135+
136+
Note that while this ADR does not prescribe a list of modules, whenever a new
137+
slot is introduced special care should be taken with the selection of the
138+
module name. In particular, slots that occur in multiple modules should have
139+
consistent names. For instance, while the "layout" module suggested above for
140+
the footer is not to be considered one of the decisions described here, it is a
141+
good example of a case where a single module name would apply to at least two
142+
slots that would be present in more than one codebase: ``layout.header`` and
143+
``layout.footer``.
144+
145+
146+
2. Versioning
147+
-------------
148+
149+
For the purposes of versioning, a given slot's API contract is comprised of:
150+
151+
* Its location, visual or otherwise, in the Module
152+
* The type (but not implementation!) of the content it is expected to wrap
153+
* The specific set of `pluginProps` it exposes
154+
155+
If one of the above changes for a particular slot in such a way that existing
156+
plugins break or present undefined behavior, *and* if it still make sense to
157+
use the same Identifier, the version string appended to its name will be
158+
incremented by `1`.
159+
160+
Note: a given slot's default content is explicitly *not* part of its contract.
161+
Changes to it do not result in a version bump.
162+
163+
3. Deprecation process
164+
----------------------
165+
166+
When a slot changes sufficiently to require its version to be incremented, the
167+
developer will take care to:
168+
169+
* Propose the previous version's deprecation via the official Open edX
170+
Deprecation Process
171+
172+
* Keep the definition of the previously released version of the slot in the
173+
codebase for the duration of the deprecation process, which should include at
174+
least one Open edX release where it co-exists with the new version
175+
176+
* Implement the new version of the slot in such a way that coexists with the
177+
previous one with no detriment to either's functionality
178+
179+
180+
Consequences
181+
============
182+
183+
The decisions above are intended to let plugin authors create and maintain
184+
plugins that are stable across releases of Open edX, while also allowing slots
185+
themselves to evolve. The naming convention itself has no significant
186+
downsides, and while the deprecation process does add some maintenance burden,
187+
it is expected to be offset by the additional stability provided.
188+

0 commit comments

Comments
 (0)