Novoda is an advocate for clean code and actively using pair-programming, collaboration and code reviews. The SOLID principles are fundamental to explaining a part of what clean code is, but sometimes explaining what SOLID means is a task in itself. This blog posts shows how we tried to re-examine SOLID visually to help all our developers embrace and learn from SOLID design.
Before we begin to visualise the SOLID principles, we should clear what they stand for. Let's start off with the basics. Here it is in a Wikipedia nutshell:
|S||SRP||Single responsibility principle||a class should have only a single responsibility (i.e. only one potential change in the software's specification should be able to affect the specification of the class)|
|O||OCP||Open/closed principle||“software entities … should be open for extension, but closed for modification.”|
|L||LSP||Liskov substitution principle||“objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.”|
|I||ISP||Interface segregation principle||“many client-specific interfaces are better than one general-purpose interface.”|
|D||DIP||Dependency inversion principle||one should “Depend upon Abstractions. Do not depend upon concretions.”|
The Wikipedia excerpt gives you an idea of what the principles stand for but if you didn't know them you would have to go do some further reading to understand them in depth. Furthermore, as a refresher the Wikipedia page is not particularly interesting or stimulating and could be considered verbose.
One of our amazing designers - Qi Qu - undertook the challenge of re-imagining these principles visually to help drive understanding. The idea behind our imagery is to show visually what the principles say you should not be doing.
There is psychology behind this idea. People tend to remember lucid, stupid or silly imagery much more readily than a bland static image.1
Don't have your class, method, object, or concept doing more than one thing. Imagine a single chef running the entire restaurant, being responsible for taking orders, cooking all the meals, and washing up. Eventually the chef would make a mistake. It is too complex a system for one actor to do everything correctly every time. Your code should be written with this in mind, aiming to do one simple task well.
Don't program in such a way that, in order to add new behaviour, you need to write additional code in lower layers of your code-base. Imagine each time you wanted to try on new shoes you had to cut off your own foot to get the shoe off, put the shoe on the bloodied foot then surgically re-attach your foot with the new shoe in place. Layers of code - like layers of clothing - should be independent and not rely on one another.
Don't implement interfaces in a way that breaks expected semantic behaviour. For example, an interface for sunglasses would have fairly simple rules like: shields from the sun; attaches to a face. Implementing the sunglasses interface with suntan lotion would seem to make sense: it shields from the sun and attaches to the face. But semantically the expected behaviour is different enough to cause behavioural problems - in this case, by stinging your eyes!
Don't create one all encompassing interface with all the methods you might ever need on it. As an example, consider an interface for charging your phone - a simple power socket. The problem is that a power socket can come in many different variations: by country, device, voltage, size etc. Designing an interface which tried to accommodate all of these would not only be very confusing but could even end up with you breaking your device. The simplest possibly interface to get the job done - arguably USB - is likely the best.
Don't let your components depend on specific implementations. For example, having your lamp wired directly into your house mains the lamp 'knows of' the specific electric system and how its individual wires connect to it. Instead it's better for the lamp to expose a plug and depend on a socket - an abstraction of an electrical provider - knowing nothing of the house. This means it's easier to maintain, move, or re-use elsewhere, just as your code should be.
Creating these images was difficult but fun and required a lot of discussion, collaboration and determination. The thought process involved and the iterations of the ideas was a long time in the making. Even after this, we still find ourselves discussing them internally and arguing about how best to represent the principles. Nevertheless, we hope at least some of these pictures help you remember SOLID.
Interested in getting these posters for your office? We'll have some available in our competition at our stand at Droidcon London 2016 this year. If you want to purchase your own head but can't make it to Droidcon, you can head over to our redbubble page to grab them from October 31st.