The real world case for unobtrusive JavaScript
Unobtrusive JavaScript (UJS) has gained mainstream acceptance. Except for a few holdouts, the collective conscience of web developers has changed from thinking inline JavaScript is good enough to accepting that UJS is the modern and right way to add behaviour to web pages. But this is not the same thing as really understanding how JavaScript relates to modern web development; I believe there’s a word for this kind of collective behaviour.
I want to explain the real world, pragmatic and practical reasons for unobtrusive JavaScript. Actually, I think the word unobtrusive is misleading because unobtrusiveness is just a side effect of what I will call structured JavaScript. It is not purity for purity’s sake that should drive you towards a cleaner, more structured, more reusable and more scalable way to program JavaScript, but the benefits inherent in these qualities, including keeping your sanity when dealing with less-than-trivial functionality.
First, let’s examine the weaknesses of unstructured or obtrusive JavaScript:
- It’s unstructured: This should be enough of a weakness in itself. Lack of structure results in messy code that increases the overhead of making changes to a point where it becomes nearly impossible.
- It doesn’t scale: Any sufficiently complex web application will implode from its own weight if you keep adding inline JavaScript. What seems simple to begin with will eventually evolve into a mess of inline event handlers, global functions and variables clashing with each other and strong coupling. It will become increasingly difficult to find anything at all and adding or changing functionality will eventually become a dreaded, near-impossible task where even the smallest change could bring the whole thing down.
- It’s not testable: It’s much, much harder to write automated tests for messy, coupled code than it is for properly structured code.
- It’s not reusable: Yes, you may have some server-side function that generates the same code over and over again that you could call reusable, but that’s like saying Java is conceptually simple because you have this huge IDE generating your huge classes, interfaces and XML configuration files for you. You’re still littering your HTML with the exact same code over and over, increasing page load and complexity along the way. You can’t abstract away JavaScript.
- It adds more coupling to your code: Inline code couples your JavaScript to something as volatile as HTML, resulting in easier breakage of semi-unrelated components of your application. You might argue that having it all in the same place makes it easier to see the coupling and change both at the same time, but well-structured unobtrusive JavaScript has considerably less coupling to begin with and can handle much more change to the HTML tree without breaking than inline code can ever dream of.
- It forces responsibility overlap: By inlining JavaScript you force both designers and programmers (both server- and client-side) to be responsible for and understand the details of each other’s work. This is not entirely avoidable; the content, style and structure of your page will overlap, but by staying unobtrusive you can keep this to a much more sane level. A designer shouldn’t have to journey deep inside the intestines of your inline JavaScript to change the way an element looks.
- Your page elements can’t have their own state: Unobtrusive JavaScript often ignores this as well, but when using inline code you’re making sure your page elements (like a post, comment, etc) can’t have their own internal state; they’re not self-conscious. This is a basic requirement for good object-oriented programming which can make it much easier to deal with complexity.
The basic tenets of good programming apply to JavaScript just as much as they do to Ruby or Java programming. Modularity, proper structure, reusability and encapsulation provide exactly the same benefits for JavaScript programming as they do for other languages and “obtrusive” JavaScript breaks all of these practises. Inline JavaScript is to structured JavaScript what PHP is to Ruby on Rails: Its simplicity only works in its favour for very simple applications. JavaScript is a rebellious teenager in need of structure and discipline; you’re the parent who must send it to boarding school.
So what are these benefits I talk about? They’re basically the opposite of the weaknesses of not following best practises:
- It’s structured: Again, this is a strength in itself. Structured code is a pre-requisite for most of the other best practises.
- It scales: Once your code is properly modularised, decoupled and encapsulated, it becomes so much easier to add or change functionality. It’s considerably less work than it would have been with an inline Frankensteinian mess of an application.
- It’s less complex: Complex code is more difficult to understand, change and test.
- It’s testable: You can test discrete components of your application’s functionality without setting up scaffolding to support it or having unrelated tests break because your code is coupled.
- It’s decoupled: You can change one part of the page’s functionality without worrying that something completely unrelated will break.
- It’s reusable: Once your code is modular and decoupled it becomes much easier to reuse parts of it.
Contrary to what a lot of people think, writing structured JavaScript is not more work than using inline code. There is a small penalty at the very beginning where the overhead of separating behaviour from content is noticeable, but at a certain point the relation reverses to mean that inline code is more work, and that threshold is very low.
JavaScript is a real programming language. Stop using it like it’s PHP and start using it to your own benefit.
Comments
Log in to comment.