Forget SOLID. Say Hello To SHOC Principles for Modular Design.

Yesterday, I ran a little experiment on social media. Like TDD, SOLID “class design principles” have become de rigueur on software developers’ CVs. And, like TDD, most of the CVs SOLID is featured on belong to people who evidently haven’t understood – let alone applied – the principles.

There’s also been much talk in recent years about whether SOLID principles need updating. Certainly, as a trainer and coach in software design practices, I’ve found SOLID to be insufficient and often confusing.

So, with both these things in mind, I threw out my own set of principles – SHOC – to explain how Codemanship teaches principles of modular software design. Note that I’m very deliberately not saying “object-oriented” or “class” design.

Here are the four principles taught on Codemanship Code Craft courses. Good modules should:

  • Be Swappable
  • Hide their internal workings
  • Do One job
  • Have Client-driven interfaces

Now, those of you who do understand SOLID may notice that SHOC covers 4 of the 5 letters.

The Liskov Substitution and Dependency Inversion principles in SOLID are about making modules interchangeable (basically, about polymorphism).

The Single Responsibility Principle is essentially “do one job”, though it’s rationale I’ve long found to be a red herring. The real design benefit of SRP is greater composability (think of UNIX pipes), so I focus on that when I explain it.

The Interface Segregation Principle is a backwards way of saying that interfaces should be designed from the client’s point of view.

So that’s the S, the L, the I and the D of SOLID. SLID.

But SOLID is missing something really rather crucial. It doesn’t explicitly mandate encapsulation. Combined, it may imply it, depending on how you interpret and apply the principles.

But you can easily satisfy every SOLID – or SLID – principle and still have every module expose its internals in a very unseemly manner, with getters and setters galore. e.g., Interface Segregation says that’s fine just as long as only the getters and setters the client’s using are exposed.

So I find the need to add Tell, Don’t Ask – that objects shouldn’t ask for data to do work, they should tell the objects that contain the data to do the work themselves, enabling us to hide that data – to the list of modular design principles developers need to learn. SLIDT.

And what happened to the Open-Closed Principle of SOLID – that classes should be open to extension and closed to modification. The original rationale for the OCP was the time it took to build and test code. This is a callback to a time when our computers were about 1000x slower than today. I used to take a long coffee break when my code was compiling, and our tests ran overnight. And that was advanced at the time.

Now we can build and test our code in minutes or even seconds – well, if our testing pyramid is the right way up – and modifying existing modules really is no big deal. The refactoring discipline kind of relies on modules being open to modification, for example.

And, as Kevlin Henney has rightly pointed out, we could think of OCP as being more of a language design principles than a software design principle. “Open to extension” in C++ means something quite different in JavaScript.

So I dropped the O in SOLID. It’s a 90’s thing. Technology moved on.

“SLIDT”**, of course, doesn’t exactly trip off the tongue, and I doubt many would use it as their “memorable information” for their online banking log-in.

So I came up with SHOC. Without a K*. Modules should be swappable, hide their internal workings, do one job and have interfaces designed from the client’s point of view.

This is how I teach modular design now – in multiple programming paradigms and at multiple levels of code organisation – and I can report that it’s been far more successful when you measure it in terms of the impact on code quality it’s had.

It’s much easier to understand, and much easier to apply, be it in C++, or Java, or C#, or JavaScript, or Clojure, or COBOL. Yes, you heard me. COBOL.

SHOC is built on the original principles of modular design dating back to the late 1960s and early 70s – namely that modules should be interchangeable, have good separation of concerns, present “well-defined” interfaces (okay, so I interpreted that) and hide their information. Like Doctor Martin’s boots, I’m not expecting these to go out of fashion anytime soon.

When I teach software design principles, I teach them as two sets: Simple Design and SHOC. Occasionally, students ask “But what about SOLID?” and we have that conversation – but increasingly less often of late.

So, will you be adding “SHOC” to your CV? Probably not. That was never the point. SOLID as a “must-have” skill will soldier on, despite being out-of-date, rarely correctly applied, and widely misunderstood.

But that’s never stopped us before 😉

*It’s been especially fun watching people try to add an arbitrary K to SHOC. Nature abhors an incomplete mnemonic.

**It just occurred to me that if I’d used “encapsulates its internal workings” instead of “Tell, Don’t Ask”, I could have had SLIDE, but folk would still get confused by the SLID part