You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: oeps/best-practices/oep-0068-bp-naming-identifiers.rst
+67-9Lines changed: 67 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,7 +36,7 @@ OEP-68: Naming Identifiers
36
36
Abstract
37
37
********
38
38
39
-
Open edX code uses several distinct types of identifiers. To make code unambiguous and readable, we adopt consistent naming conventions for each type. This OEP defines four categories of identifiers—Primary Keys, OpaqueKeys, OpaqueKey Strings, and Codes—and specifies the naming conventions for each. These conventions apply across Python code, database column names, REST API fields, event schemas, and any other context where identifiers appear.
39
+
Open edX code uses several distinct types of identifiers. To make code unambiguous and readable, we adopt consistent naming conventions for each type. This OEP defines five categories of identifiers—Primary Keys, OpaqueKeys, Codes, UUIDs, and Other—and specifies the naming conventions for each. These conventions apply across Python code, database column names, REST API fields, event schemas, and any other context where identifiers appear.
40
40
41
41
Motivation
42
42
**********
@@ -50,7 +50,7 @@ Consistent naming makes identifier types immediately apparent from the name alon
50
50
Specification
51
51
*************
52
52
53
-
There are four recognized categories of identifier in Open edX code. When naming an identifier, first determine which category it belongs to, then apply the naming convention for that category. If an identifier does not fit any category, choose a name that does not collide with any of the four conventions, so that readers are not misled.
53
+
There are five recognized categories of identifier in Open edX code. When naming an identifier, first determine which category it belongs to, then apply the naming convention for that category. If an identifier does not fit any category, choose a name that does not collide with any of the five conventions, so that readers are not misled.
54
54
55
55
These conventions apply wherever identifiers are named: Python variables, parameters, and attributes; Django model field names and database column names; REST API request and response field names; and event data schema fields.
56
56
@@ -70,7 +70,7 @@ Summary
70
70
- ``int``
71
71
- ``pk``, ``*_pk``
72
72
* - OpaqueKey
73
-
- Globally-scoped parsed key object
73
+
- Parsed key object scoped to one Open edX instance
74
74
- subclass of ``OpaqueKey``
75
75
- ``*_key``
76
76
* - OpaqueKey String
@@ -81,6 +81,14 @@ Summary
81
81
- Locally-scoped slug-like string
82
82
- ``str``
83
83
- ``*_code``
84
+
* - UUID
85
+
- Globally unique identifier scoped across all Open edX instances
86
+
- ``uuid.UUID``
87
+
- ``*_uuid``
88
+
* - UUID String
89
+
- Serialized form of a UUID
90
+
- ``str``
91
+
- ``*_uuid_string`` (or ``*_uuid`` when unambiguous)
84
92
85
93
Primary Keys
86
94
============
@@ -124,7 +132,7 @@ Please note that, for historical reasons, concrete OpaqueKey subclasses use the
The serialized (string) form of an OpaqueKey is distinct from the parsed object. When the context makes it unambiguous that the value is a string—such as inside a Django form, serializer, or REST API field—it is acceptable to use ``*_key`` for the serialized form as well.
130
138
@@ -140,13 +148,17 @@ When there is any ambiguity about whether a value is a parsed ``OpaqueKey`` obje
Please note that OpaqueKeys Strings should only be used at the boundaries of the platform (REST APIs, external events, logging, etc.). Within the system, parsed OpaqueKey objects are always preferred, as they protect against serializationd-deserializatione errors and provide type safety.
157
+
Please note that OpaqueKey Strings should only be used at the boundaries of the platform (REST APIs, external events, logging, etc.). Within the system, parsed OpaqueKey objects are always preferred, as they protect against serialization-deserialization errors and provide type safety.
158
+
159
+
.. note::
160
+
161
+
On the frontend, parsed ``OpaqueKey`` objects are not available; OpaqueKeys are always plain strings. Therefore, a ``*KeyString`` suffix is not needed in frontend code—``*Key`` is always acceptable.
150
162
151
163
Codes
152
164
=====
@@ -168,19 +180,65 @@ Variables and fields holding a code should use the suffix ``_code``.
A UUID (Universally Unique Identifier) is a 128-bit identifier that uniquely identifies a resource across *all* Open edX instances, not just within one. UUIDs are suitable for use as stable identifiers in cross-instance contexts such as event data, external integrations, and shared databases.
187
+
188
+
The preferred Python type for a UUID is ``uuid.UUID``. Variables and fields holding a UUID should use the suffix ``_uuid``.
The serialized (string) form of a UUID is distinct from the ``uuid.UUID`` object. When the context makes it unambiguous that the value is a string—such as inside a Django serializer or REST API field—it is acceptable to use ``*_uuid`` for the serialized form as well.
206
+
207
+
When there is any ambiguity about whether a value is a ``uuid.UUID`` object or its string serialization, use the suffix ``*_uuid_string`` to make the distinction explicit.
208
+
209
+
.. code-block:: python
210
+
211
+
# Unambiguous context (serializer field): *_uuid is fine
212
+
classThreadSerializer(serializers.Serializer):
213
+
discussion_uuid = serializers.UUIDField()
214
+
215
+
# Ambiguous context: use *_uuid_string to distinguish from the UUID object
As with OpaqueKey Strings, UUID Strings should only be used at the boundaries of the platform. Within the system, ``uuid.UUID`` objects are always preferred.
224
+
225
+
.. note::
226
+
227
+
On the frontend, ``uuid.UUID`` objects are not available; UUIDs are always plain strings. Therefore, a ``*UuidString`` suffix is not needed in frontend code—``*Uuid`` is always acceptable.
228
+
171
229
Other Identifiers
172
230
=================
173
231
174
-
Not every identifier fits neatly into one of the above categories. When an identifier does not, choose a name that does not use any of the suffixes ``_pk``, ``_key``, ``_key_string``, or ``_code``, so that readers are not misled into assuming a type or scope that does not apply.
232
+
Not every identifier fits neatly into one of the above categories. When an identifier does not, choose a name that does not use any of the suffixes ``_pk``, ``_key``, ``_key_string``, ``_code``, ``_uuid``, or ``_uuid_string``, so that readers are not misled into assuming a type or scope that does not apply.
175
233
176
234
For inspiration, consider the ``refname`` field on ``PublishableEntity`` objects in ``openedx-learning``. A ``refname`` correlates a database entity with its representation in off-platform or cross-platform ZIP archives. It is not a primary key (which would be database-specific), not a code (because it may contain non-slug characters), and not an OpaqueKey (because it cannot be parsed into a globally-scoped identifier). By choosing the name ``refname``—which collides with none of the conventions above—the code signals clearly that this identifier is its own distinct thing.
177
235
178
236
Rationale
179
237
*********
180
238
181
-
The four categories above cover the vast majority of identifiers that appear in Open edX Python code. Keeping the naming conventions to a small, well-defined set makes them easy to learn and apply consistently. The ``_pk`` / ``_key`` / ``_code`` suffixes were chosen because they are short, distinct from one another, and directly evocative of the kind of identifier they represent.
239
+
The five categories above cover the vast majority of identifiers that appear in Open edX Python code. Keeping the naming conventions to a small, well-defined set makes them easy to learn and apply consistently. The ``_pk`` / ``_key`` / ``_code`` / ``_uuid`` suffixes were chosen because they are short, distinct from one another, and directly evocative of the kind of identifier they represent.
182
240
183
-
The ``_key_string`` convention for serialized OpaqueKeys was chosen over alternatives like ``_key_str`` or ``_key_serialized`` for readability. The word "string" more clearly signals to a reader that the value is a plain string rather than a Python object.
241
+
The ``_key_string`` and ``_uuid_string`` conventions were chosen over alternatives like ``_key_str`` or ``_uuid_str`` for readability. The word "string" more clearly signals to a reader that the value is a plain string rather than a Python object.
0 commit comments