OpenCraft Coding Standards and Best Practices¶
Here are the guidelines that OpenCraft follows with all of our software development. Some of these are not strict rules, but all of them are the standards that we aim for.
We are an open source company which means that all software we create should be open source by default (unless there is some compelling or legal reason not to).
Documentation or other non-software works that we create should be licensed under a Creative Commons license, usually CC BY-SA 3.0.
In addition, any time we make a change (feature, bugfix, etc.) to an external software project (like Open edX, Django, etc.), we contribute that change back to the project. (Sometimes they won't accept it as a contribution, but we always try.)
Coding Standards and Best Practices¶
1. Do your best to ensure you've written clean, maintainable code.
- Remember "Don't make me think!": use descriptive variable/function/class names in your code and comments to make your code as easy to read as a book.
- Short, simple code is usually better than long, complex code, but don't fall for the temptation of writing code that's visually dense, which is hard to read and understand. Add docstrings, blank lines, and comments to space things out and make your code more readable.
Here is an example, showing the same python function written in a "bad" and "good" way:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
2. Document your decisions
- When you're building something new, you'll make a lot of decisions about how it works. Write those decisions down so that other developers can understand more easily.
- It's tempting (and helpful) to put these details into a pull request description, but pull requests are temporary and hard to find once merged. It's much better to put the details of your decisions into the codebase itself as a docstring (for small components), a README, or an Architecture Decision Record (ADR) (example).
3. Write tests for your code
- Testing is critical for designing robust, high quality software components and avoiding regressions.
- "Unit Tests: Best and Worst Practices" provides good tips about the role of tests and how to maximize their value. ("It's overwhelmingly easy to write bad unit tests that add very little value to a project while inflating the cost of code changes astronomically.")
4. Backend guidelines:
- Choosing a language: we default to using Python for most new projects for simplicity and consistency.
- Follow the edX Python Style Guide (even for non-edX projects, unless the project has its own style guide).
- Use pycodestyle and pylint to enforce coding standards automatically
5. Frontend guidelines:
- Use TypeScript for non-edX projects.
- Ensure that any UI you build follows best practices for accessibility and complies with the WCAG 2.0 Level AA standards:
- Every UI component and content item has a text version (alt text, screenreader text), so that non-visual users can still understand and use it.
- The UI can be used with a keyboard only (tab order, keyboard controls).
- Text colors have sufficient contrast.
- See the complete checklist/cheatsheet (levels A and AA only).
More in-depth guidelines and discussion of particular technologies can be found in our technical documentation handbook.
Infrastructure as Code¶
As much as possible, infrastructure, server provisioning, and devstack setup should be defined by code and version controlled using git.
In particular, this means:
- AWS and OpenStack/OVH infrastructure should be configured using Terraform.
- Set up for the environment your application requires (installing apt packages, etc.) should be scripted using either Ansible or a Dockerfile.
- Setting up client-specific devstacks should be automated using bash scripts or whatever else is convenient.
Contributing Features to edx-platform¶
For feature contributions to the Open edX core platform in particular:
Discuss with the team and/or edX to determine if the feature you're building should be part of the core platform or should be a plugin (like an XBlock or a django app plugin). Generally, if it provides a platform feature that most of the community will use or provides a foundation for building other functionality, it would be a good candidate for the core platform, and if it's a feature that only a minority of Open edX instances are likely to use, it would be better as a plugin.
If you are writing the feature as a plugin, ensure that it only uses stable public APIs such as the XBlock API, the Django App Plugin API, and/or any inter-app API (
api.py files within each Django app in the core platform). If there is no public API defined for the integration you need, modify the core platform to provide the API that you need, e.g. in an
api.py file, and contribute the API to the core platform.