SOLID Object Oriented Principles And CSS: Part 2

How should you define the abstraction in a class? What should the class do? What responsibilities should it have? When you want to add something new to the class, should you modify it or extend it? These are some of the questions SOLID principles attempt to answer.

Last week I started to look at the five SOLID object oriented principles and how we might apply them to designing websites. So far we talked about the single responsibility principle and also the open/closed principle.

We still have three principles left to cover.

Scrabble tiles spelling the words solid state

The 5 SOLID Principles

As a reminder here’s a brief definition of all five SOLID principles.

  • Single Responsibility Principle — objects should have only a single encapsulated responsibility
  • Open/Closed Principle — objects should be open for extension, but closed for modification
  • Liskov Substitution Principle — objects should be replaceable with instances of their subtypes without introducing problems
  • Interface Segregation Principle — many client specific interfaces are better than one general purpose interface
  • Dependency Inversion Principle — objects should depend on abstractions and not concretions

As a further reminder about the first two principles here’s the gist.

Object oriented concepts have further convinced me that a modular approach to css development is a good idea

The single responsibility principle suggests we shouldn’t include properties of more than a single type in any class. For example instead of a single selector defining values for both type and color, we’d create multiple classes, one with type properties and another with color properties. The net result is more specific classes, each doing fewer things.

Once these base classes are set up other code in our project is going to rely on them. The open/closed principle suggests that if we need to add something to our base classes we should do so by extending the classes and not by modifying them as the latter could break dependencies.

With that short review behind us, let’s get to the rest of the principles.

Liskov Substitution Principle

The Liskov substitution principle tells us that objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. In other words if a program expects a shape, you should be able to substitute the more specific rectangle without problem.

The idea we can take from this is that classes that extend a base class shouldn’t have a different behavior than the base class they extend.

If our base class follows the single responsibility principle and defines values for properties of type, then subclasses of it should also define only values for type properties. If the base class affects colors, then any class meant to extend it should also only affect colors.

If we swap classes on an element, everywhere type or color was covered by the first class is now covered by the second. Since subclasses in css usually don’t overwrite everything in the base class, we might instead suggest that adding a subclass to an element with our base class doesn’t cause conflicts.

The Liskov substitution principle might also suggest that modifier classes should probably be careful around anything layout related as layout changes are the most likely to cause a significant break.

Interface Segregation Principle

The idea with the interface segregation principle is that no element should be forced to implement an interface it doesn’t use. Better would be to use several more specific interfaces than one general purpose interface.

Say you have a div that’s going to enclose some content inside a border, but isn’t meant to get a background color different from its container. You wouldn’t want to use a class that also includes a background color even if it’s the same as the one on the parent, because you now force any html that gets the class to depend on it for something it isn’t using.

If the base class is allowed to be more general, it gets reused more so as not to repeat code. The problem is that it couples many elements together that should remain independent. Changing the background color affects them all even if only some should change.

It’s better to have multiple and specific base classes than one all encompassing generic one. Here we’d have one class defining borders and another defining backgrounds. Again if we follow SRP we should be ok here.

If you find you’re constantly redefining a lot of properties in sub classes then you might have too generic an abstraction in the base class and you’d be better with several base classes, each with more specific abstractions.

More specific and smaller classes will help reduce coupling, increase cohesion, and generally lead to more maintainable sites.

Dependency Inversion Principle

The dependency inversion principle is stated in two ways, though each essentially says the same thing. The idea is to depend more on abstractions than on concrete implementations.

  • High-level modules should not depend on low-level modules. Both should depend on abstractions.
  • Abstractions should not depend upon details. Details should depend upon abstractions.

This dependency inversion principle is about reducing the dependence of modules on one another. It’s about decoupling.

In the context of html and css, parent containers shouldn’t care how their children are styled and children shouldn’t care how their parents are styled, as long as neither breaks the other. We should be able to swap out the styles of the child without it affecting the parent and vice versa.

Both parent and child should depend on abstractions, which for us are classes. Descendent selectors therefore are a sign you might not be adhering to this principle, since descendent selectors add dependency between parent and child. Instead a new abstraction might be called for. Another class is preferable to a descendent selector.

As soon as I came across this principle it brought to mind Andy Hume’s presentation CSS for Grownups. One of the examples Andy walks through in the presentation involves changing hx selectors to classes.

Starting with the following css on hx elements.

{code type=css}
h1 {font-size: 3em;}
h2 {font-size: 2.3em;}
h3 {font-size: 2.1em;}
{/code}

The selectors are first changed to classes named after the hx tags.

{code type=css}
.h1 {font-size: 3em;}
.h2 {font-size: 2.3em;}
.h3 {font-size: 2.1em;}
{/code}

The class names are then changed to better describe what’s being styled.

{code type=css}
.h-headline {font-size: 3em;}
.h-subhead {font-size: 2.3em;}
.h-byline {font-size: 2.1em;}
{/code}

The original selectors rely on specific html as they are html element selectors. Changing them to classes removes this dependence. The final renaming of classes adds semantics for what each class is meant to style.

Summary

Please accept my usual disclaimer and apology if I’ve misinterpreted these principles in any way or if I’m suggesting they be applied to html and css in a way that doesn’t make sense. Again this is all a learning experience for me and I won’t be surprised to have gotten a few things wrong.

Also please don’t take anything here as me suggesting css or html are object oriented languages. They clearly aren’t, but how we use them to design websites might be able to take a few lessons from object oriented design.

Last year when I looked at development methods like OOCSS, SMACSS, and DRY CSS, it convinced me that a modular approach to development was a good idea worth pursuing. However, I’ve found the ideas challenging to put into practice as I often fall back on old habits.

This recent look at object oriented concepts has mainly been to help me better understand how I might incorporate modularity into my code.

As I mentioned last week, what I’m taking away most from these SOLID principles is that more classes are probably better than less and that those classes should generally be more specific about what they do. The danger is falling prey to classitis, though the more I look at these concepts, the less I’m convinced it’s the problem we used to think.

« »

Download a free sample from my book, Design Fundamentals.

2 comments

  1. The thing that bothers me about all those classes is that you would need to alter the html of a page to change it’s appearance. This clashes with the principle: structure = html and appearance = css.
    It reminds me of inline css via the antique html style attribute.

    That being said, a lot of these principles do make sense and tend to line up with more vague personal guidelines, formed from experience. F.e., different widgets inside a sidebar quickly make you work following the dependency inversion principle.

    I like how these theoretical principles are challenging my more vague personal guidelines.

    • Yes and no. I hear you about having to add and remove classes to existing content, but I don’t think it’s quite the same as inline styles. My instinct was to think that too, but now I see it as different.

      You can still rewrite the css on a class and have everything change across the site. Say you want to change a widget border from red to blue. It’s not like you’d have to change any html to do that.

      You can also remove all the styles from a particular class. That leaves the class in the html, but it’s not the worst thing.

      I used to worry about adding all the classes, but whenever I’ve really changed how web pages looked (beyond changing a color or font-size or similar) I ended up reworking some of the html anyway. Realizing that it doesn’t bother me too much if I’ll now have to add or remove some classes.

      I’m still working my way through this, but it strikes me that with practice and some planning we won’t be reworking html so much. Here and there maybe, but I think it’ll be more changing values in css classes the same as we do now.

Leave a Reply

Your email address will not be published. Required fields are marked *