Open edX courseware leverages two powerful technologies for locating and interacting with course content, both of which were developed internally. Opaque Keys describe the location of course content both in terms of browser access via url as well as internally in the application source code. XBlocks generically describe individual units of course content such as a Chapter, a Subsection or an individual homework problem or test question. Lets take a closer look at how these two intertwined technologies work.
Though the Open edX course structure and its object key system, Opaque Keys are each quite complex, you’ll see in “Code Sample I” that we can create and traverse a course outline in only four lines of code. With a cursory understanding of edx-platform’s in-place application api’s you’ll be able to do amazing things with little code.
Our discussion necessarily begins with Opaque Keys as these are the code objects that describe individual chunks of course content. By way of example, each of the following is a string representation of some kind of Opaque Key:
What are Opaque Keys?
Opaque Keys do the following:
1.) accurately describe any course object in terms of its structural location, which course run, which branch, and which version
2.) facilitate a map to-from the Open edX URL structures
3.) provide backward compatibility to older Open edX key and storage strategies
Opaque Keys are referred to generically in documentation as locators, keys, course keys, course id’s, asset keys, and usage keys. None of these is incorrect mind you. The three most common kinds of opaque keys are:
A CourseLocator (formerly CourseKey) contains many BlockUsageLocators (AssetKeys and UsageKeys), and it knows about these. An AssetKey and a UsageKey each knows which CourseKey it is associated with. DefinitonKey’s are context independent. The class hierarchy diagram below helps to make sense of each of these statements.
Opaque Keys Class Hierarchy
Opaque Keys Persistence Models
Opaque keys are fast and powerful. The keys are referenced everywhere in the code base and therefore need to instantiate and execute performantly. Incidentally, there’s a longer-term plan for Opaque Keys which will make them, well, more opaque. While I’m not privy to the salient details of this vision, I am aware that bright minds are hard at work at a brighter future for Opaque Keys (pun intended).
Modern Opaque Keys provides a way to embed additional distinguishing content attributes such as course run, branch (ie “Draft” or “Published”), and version in the object itself. Naturally, attributes of this nature have implications to the user experience and the overall behavior of the platform itself. Much of this is encapsulated in the Opaque Keys project.
In Open edX source code, whether this be in edx-platform or any other code repository in the Open edX ecosystem, the string representations of Opaque Keys such as the course_id slug in a course url are consumed by the pip-installed opaque-keys Python package which provides powerful introspection and utility capabilities. As the name “Opaque” implies, there is more to these keys than meets the eye. The Opaque Keys project was originally part of edx-platform, but it was spun off into a separate repository in 2014.
I am aware of only these three documentation sources for Opaque Keys, each located in the edx-platform repo Wiki: 1.) “Opaque Keys (Locators)“, 2.) “Locators: Developer Notes“, and 3.) “Split: the versioning, structure saving DAO“. When reading these documents it behooves you to keep in mind that they were written to inform an already-knowledgeable audience about noteworthy changes to Opaque Keys at a point in time in the past. It’s therefore pretty easy to draw incorrect conclusions from these documents. Conversely, this article is intended to illustrate in practical terms how to make use of these technologies at present based on my own personal experience.
Something else to keep in mind is that Opaque Keys have changed significantly over the life of the project (10+ years), and the Open edX code base provides backward compatibility to all of its incarnations. In many cases this complicates analyzing and understanding the source code. This is a direct effect of the double-edge sword of maturing open-source projects. it’s oftentimes best to not delve too deeply into the sausage-making of Opaque Keys’ inter-workings. Fortunately, the Opaque Key classes have been stable for more than seven years, and thus you have little if no need to burden yourself with its knotty history.
Lastly, the Opaque Keys project straddles large and gradual tectonic shifts in Open edX’s persistence strategy referred to, respectively, as “Old Mongo” and “Split Mongo”. This itself merits an eventual blog post as the changes were substantial and thus also impacted the complexity of the lower-levels of the Open edX code base. Vastly paraphrasing, the modern Open edX platform leverages XModule, which identifies courses with “Locators” (a kind of Opaque Key), and reusable program code with “Locations” (also a kind of Opaque Key).
What is a Block?
From the extension engine blog, “XBlock is the SDK for the edX MOOC platform. It’s a framework that allows the open source software development community to extend and enhance edX to meet future needs and is written in Python2. XBlock is one of the aspects of edX that makes it such a powerful tool.” Except this is a little bit misleading in that all Open edX course content is created with XBlocks, also referred to more generically as “blocks”.
We could talk at length about blocks but we’ll save that for another blog post someday soon, hopefully.