Look, honey! I injected a dependency!

July 23, 2011

The WMD Markdown editor

I recently spent some time refactoring the JavaScript version of the Markdown converter and editor used on the Stack Exchange sites. While we usually refer to both by the same name – “WMD” –, the two parts are actually separate parts.

The Markdown converter, called “Showdown”, is (or was at some point) a more or less one-to-one port of John Gruber's original Perl implementation. “WMD” is the real editor (dubbed a “What you see is what you mean” editor by its author); it uses Showdown to convert the user-entered Markdown to HTML in order to display a real-time preview of what the final result will look like.

Both Showdown and WMD were created by John Fraser (under the label “Attacklab”). WMD's use on Stack Overflow (and later all the Stack Exchange sites) has an interesting history to it, including work by many people inside and outside the company. Under the name of “WMD-New”, we also published the code for others to use and improve.

Over time, WMD has deviated more and more from the original version: Bugs were fixed, additional Stack Exchange-specific syntax variations were added (e.g. spoilers or syntax highlighting hints), some features were removed because we don't use them, other features were added that are only interesting to the Stack Exchange use (like our image upload dialog).

Cleaning up and separating

It became harder and harder to fold bug fixes and improvements into the open source version, as well as to maintain our own version of it: Original JavaScript code is intertwined with code that's only interesting for us, sometimes even depending on jQuery (which we use, but WMD doesn't); sometimes, our additions were added to the Markdown converter code, sometimes they were added to the Markdown editor code, sometimes they were added from the outside by the use of an ad-hoc inserted callback. Especially with the arrival of inline editing, where we suddenly could have several editors in the same page, we ran into more and more issues.

So the purpose of refactoring was cleaning all this up. We will shortly publish the new version; possibly under a different name, since we have deviated quite a bit from the original WMD and Showdown (however, this is not meant to imply that we're trying to shadow the work John Fraser has done – a very large part is still his work!). That version will be identical to the version that's running on the Stack Exchange sites; all our custom additions are added through a simple plugin mechanism, keeping both parts cleanly separated.

Most of the refactoring was simple moving around of code, removing an unnecessary variable here, renaming an object there, and so on. But there's one fairly high-level change I'd like to mention.

In the old version, the code responsible for showing the preview contains (essentially) this:

if (!converter && Attacklab.showdown) {
    converter = new Attacklab.showdown.converter();
}

if (converter) {
    text = converter.makeHtml(text);
}

– we check if the Markdown converter is available, and then create an instance of it. Then we use this to convert the user-entered Markdown to HTML, in order to display a preview. In the new version, when you create an editor, it looks like this:

var converter = new Markdown.Converter();
var editor = new Markdown.Editor(converter);
editor.run();

you create the converter (possibly adding some custom processing to it via plugin hooks), then pass the converter instance you want the Editor to use to the Editor constructor. This solves a few problems by more cleanly separating the Markdown-to-HTML conversion and the Editor code.

Helpful and simple

Now this change isn't something magical; it's a pretty straightforward way of keeping two parts of the code apart, making the whole thing easier to maintain. So why am I mentioning this very change?

I mention it because this simple, straightforward handling of responsibilities has a well-known name: Dependency injection.

There is no IOC container, no DI framework, no service locator, or any other buzzy-sounding terms that you often hear when dependency injection is the topic at hand. It's no hard-to-grasp concept requiring lots of tools and learning. It's just creating an object and giving it to another object.

This is what James Shore wrote five years ago:

When I first heard about dependency injection, I thought, “Dependendiwhatsit?” and promptly forgot about it. When I finally took the time to figure out what people were talking about, I laughed. “That's all it is?”

“Dependency Injection” is a 25-dollar term for a 5-cent concept. That's not to say that it's a bad term… and it's a good tool. But the top articles on Google focus on bells and whistles at the expense of the basic concept.

Yep, that's all it is.

So go forth and inject dependencies, and don't let people scare you away who pretend (and of course don't scare other people away by pretending) that this mythical thing called “dependency injection” requires the study of advanced software development pattern books, framework documentation, and a stack of UML diagrams.

It doesn't.


previous post: Introducing Lyfe: Yield in JavaScript

next post: jQuery script insertion and its consequences for debugging

blog comments powered by Disqus