At Coursera, we have two codebases that power our user-facing experience - the one behind www.coursera.org, where students browse and enroll for courses, and the one behind class.coursera.org, where students actually take classes. The latter is our oldest codebase, and is based on the code that powered the first version of Coursera (before we even had a name or a company), the machine learning class. It's built on PHP/mySQL and a custom routing/templating/ORM framework.
But, it worked — so we didn't want to touch it. When we touch it, we risk introducing bugs or un-introducing "features" that we were unknowingly supporting before, and when students grades and instructors happiness are on the line, we opt for doing the safe thing.
We couldn't leave it unchanged forever, though. We had many usabilty issues (meaningless icons everywhere, hard-to-navigate menus) and we also wanted to improve the university branding. So our designer proposed a redesign of the user-facing interface, and when I set about implementing that redesign in the codebase, I realized that I could not bring myself to do the user-facing improvements without making some developer-facing improvements too.
Why? Well, as a developer myself, I find it frustrating to work in an environment that doesn't use modern tools (like CSS pre-processors) and best practices (like avoiding global variables). And, as I know we will be bringing on more developers soon, I want them to be surrounded by good examples of what our codebase should look like, and not think "Oh, I guess this is just how we do things around here." I also want them to enjoy working in any of our codebases and expect that they can apply the same best practices to all of them.
So, I set about on the behind-the-scenes redesign, and thanks to help from the rest of the frontend team, we were able to make a lot of significant improvements. Here's a round up:
JS Code quality:
- We moved all of the <script> tags into the bottom of the page.
- We wrote a build task to compress all of the JS files.
- We wrote a build task to create a single compressed file of all the JS libraries that are used across most of the pages.
CSS Code Quality:
- We stopped using CSS class names that were short and ambiguous, like "title", and instead moved to prefixed, explicit names, like "css-forum-thread-title". We also only use IDs when needed for accessibility reasons, and instead prefer classes everywhere.
- We ported all of our CSS to Stylus. That means we can now take advantage of variables (like the URLs for our assets, which we can now serve off CloudFront), automatic vendor prefix generation (which will improve our cross-browser support), and extending (which means I can extend Bootstrap classes and avoid directly using them in our HTML).
- We started using box-sizing:border-box, which makes our height and padding calculations easier, but did require overriding the CSS for a few third party libraries.
- We created separate Stylus files for each functional area of the site, and we have one file that imports all of them, so that we can work in small files but still only serve one big file.
- We wrote a build task that compresses the generated CSS, so it's not actually that big.
226 commits later...! Now that we have our codebase in a better state, we can enforce our conventions on any changes that developers make in the future (via code reviews), and maybe future developers won't even realize that it was ever our legacy codebase. Maybe. :-)