In my recent post, Building a digital clock with OOCSS and MVC, I mentioned that I believe direct style manipulation is not a good engineering practice, and then promptly punted on explaining why until a later post. This was going to be that post, and then John Hann went and laid out many of the points I was going to make.
I have more I’d like to add, so jump over to his post, cujo.js — OOJS, OOCSS, and OOHTML — Part 1 (OOCSS for Engineers) and come back. He specifically touches on direct style manipulation in the sections OOCSS State and OOCSS decreases risk.
The major points he makes are that direct style manipulation:
- leads to complex branching code as runtime specialization and state inheritance becomes wider and deeper, as it does in real applications,
- tightly couples things that shouldn’t be,
- is usually less cpu-efficient than fully leveraging a good browser’s CSS engine,
These are great points, and I agree with them. I’d like to expand on #s 1 and 2 a bit, and talk about a few other reasons in the context of the “OO” in OOCSS.
The OO in OOCSS
Some of the fundamentals of OO are abstraction, inheritance, polymorphism, and encapsulation, among others. Yeah, they’re all 30 point scrabble words, but more importantly, they are time-tested software engineering principles.
If OO means “with a focus on objects”, it seems logical to say OOCSS means, “with a focus on CSS objects”, and I believe there is a huge amount of value to be had in thinking of HTML and CSS as defining View Objects. I’d love to write about how various OO principles apply to OOCSS, and maybe someday soon I will, but for now, I’d like to look at how direct style manipulation violates two of them in particular: inheritance and encapsulation.
I previously wrote about the power of ancestor specializations and state changes affecting changes in descendants, and John goes into even more detail about it. Part of the reason it is so powerful is that it works in harmony with the “C” in CSS, the Cascade.
Procedural code is less-easily checked by IDE’s, and is more risky to change than declarative CSS rules. I’d also argue that a well-organized set of CSS rules will visually communicate the cascade, and thus specialization order, more quickly and clearly than procedural branching. To draw an analogy with another popular OO language, which is faster and easier to get right: declaring a Java subclass via “class MySubclass extends MySuperclass” and letting the compiler do the heavy lifting, or writing the Java code that generates the bytecode for MySubclass?
Encapsulation is the principle of bundling the state with operations that retrieve and modify that state, as well as the idea that only those operations should access the state directly. To put it in terms of objects, an object is responsible for maintaining and controlling access to its own state by exposing only those operations which other actors are allowed to perform on its state. The other actors in the system must send messages (via exposed operations) to an object to request state changes. The object itself elects how to affect the state change, or even whether to affect it at all.
Without this access control and message passing, it would be much easier to “reach in” and alter the internal state of an object, potentially corrupting it if you don’t understand all the intricacies of its invariants. With access control, an object is protected against corruption, and your application is protected against a corrupted object wreaking havoc.
There is no encapsulation mechanism built into HTML or CSS. The only mechanism that exists is engineering diligence.
Encapsulation, OOCSS, and View Objects
The objects defined by OOCSS are View Objects. The HTML node ancestor/descendant relationships, in conjunction with the OOCSS specializations and state, define these objects. Their “state”, in the OO/encapsulation sense, is their style. For example, consider an HTML/OOCSS View Object that is a stylized button. It’s encapsulated state may contain height, width, background-color, background-image, background-position (maybe using CSS sprites for button states), borders margins, padding, etc. These were probably carefully crafted by a CSS designer to produce a button that looks great and has interesting and useful visual cues on hover, when pressed, etc.
I’ll also point out again that this kind of conditional logic is essentially duplicating the cascade, which is a bad idea for the reasons I listed above.
OOCSS: The Right Tool for the Job
CSS has a powerful inheritance mechanism in the cascade, and its declarative style, IMHO, provides a simple and expressive way to setup presentation across many view states. It is, in that regard, a declarative language for presentation state machines. The “OO” in OOCSS is a powerful way of thinking about HTML + CSS as View Objects, and gives designers and developers the right tools to declare and manage them.