Writing SOLID code

This content is 14 years old. I don't routinely update old blog posts as they are only intended to represent a view at a particular point in time. Please be warned that the information here may be out of date.

I’m not a coder: the last time I wrote any functioning code was at Uni’ in the early 1990s.  I can adapt other people’s scripts and, given enough time, write my own. I can knock up a bit of XHTML and CSS but writing real applications?  Nope.  Not my game.

Every now and again though, I come up against a development topic and I do find them interesting, if a little baffling.  I guess that’s how devs feel when I talk infrastructure.

From 2004 to 2005, I worked for a company called Conchango (who are now part of EMC Consulting) – I had a great time there, but the company’s focus had shifted from infrastructure to web design agency and Java/.NET development (which, by the way, they were rather good at – with an impressive client list).  Whilst I was there, it seemed that all I heard about was “agile” or “XP” (extreme programming… nothing to do with Windows XP) and these were approaches that were taking the programming world by storm at the time.

Then, a few weeks ago, I had a similar experience at an Edge User Group meeting, where Ian Cooper (a C# MVP) was talking about the SOLID principles.  Not being a coder, most of this went right over my head (I’m sure it would make perfect sense to my old mates from Uni’ who did follow a programming route, like Steve Knight), but it was interesting nonetheless – and, in common with some of the stuff I heard about in my days at Conchango, I’m sure the basic principles of what can go wrong with software projects could be applied to my infrastructure projects (with a little tweaking perhaps):

  • Rigidity – difficult to change.
  • Fragility – change one thing, breaks something else.
  • Immobility – e.g. one part of the solution is welded into the application.
  • Viscosity – wading through treacle, maintaining someone else’s software.
  • Needless complexity – why did we do it that way?
  • Needless repetition – Ctrl+C Ctrl+V is not an ideal programming paradigm!
  • Opacity – it made sense to original developer… but not now!

Because of these issues, maintenance quickly becomes an issue in software development and Robert C Martin (@unclebobmartin – who had previously led the group that created Agile software development from Extreme programming techniques) codified the SOLID principles in his Agile Principles, Patterns and Practices in C# book (there is also a Hanselminutes podcast where Scott Hanselman and “Uncle Bob” Martin discuss the SOLID principles and a follow-up where they discuss the relevance of SOLID).  These principles are:

  • Single responsibility principle
  • Open/closed principle
  • Liskov substitution principle
  • Interface segregation principle
  • Dependency inversion principle

This is the point where my brain starts to hurt, but please bear with me as I attempt to explain the rest of the contents of Ian’s presentation (or listen to the Hanselminutes podcast)!

The single responsibility principle

This principle states that a class should have only one reason to change.

Each responsibility is an axis of change and, when the requirements change, that change will be manifested through a change in responsibility among the classes. If a class assumes more than one responsibility, that class will have more than one reason to change, hence single responsibility.

Applying this principle gives a developer a single concept to code for (also known as separation of concerns) so, for example, instead of having a GUI to display a purchase order, this may be separated into GUI, controller, and purchase order: the controller’s function is to get the data from the appropriate place, the GUI is only concerned with displaying that data, and the purchase order is not concerned with how it is displayed.

The open/closed principle

This principle states that software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.

The thinking here is that, when a single change to a program results in a cascade of changes to dependent modules, the design becomes rigid but, if the open/closed principle is applied well, further changes are achieved by adding new code, not by changing old code that already works.

Some may think that it’s impossible to be both open to extension and closed to change: the key here is abstraction and composing.

For example, a financial model may have different rounding rules for different markets.  This can be implemented with local rounding rules rather than changing the model each time the model is applied to a different market.

The Liskov substitution principle

This principle (attributed to Barbara Liskov) states that subtypes most be substitutable for their base types.  Unfortunately, attempts to fix Liskov substitution problems often result in violations of the open/closed principle but, in essence, the validity of a model can be expressed only in terms of its clients so, for example, if there is a type called Bird (which has got wings and can fly), where what happens to penguin and emu when an attempt is made to implement the fly method? We need to be able to call fly for a penguin and handle it appropriately so there are effectively two solutions: change the type hierarchy; or refactor the type to express it differently – fly may become move, or we could have a flightless bird type and a running bird type.

The interface segregation principle

The interface segregation principle says that clients should not be forced to depend on methods they do not use.

Effectively, this means that clients should not be affected by changes that don’t concern them (i.e. fat types couple disparate parts of the application).  In essence, each interface should have smallest set of features that meet client requirements but this means it may be necessary to create multiple interfaces within a class.

The dependency inversion principle

The dependency inversion principle states that high level models should not depend on low level models – both should depend on abstractions. In addition, abstractions should not depend on details. Details should depend upon abstractions.  This is sometimes known as the Hollywood principle (“Don’t call us, we’ll call you”).  So, where is the inversion?  If a class structure is considered as a tree with the classes at the leaves and abstraction at the trunk, we depend on the tree, not the leaves, effectively inverting the tree and grasping by the roots (inversion of control).

Summing it up

I hope I’ve understood Ian’s presentation enough to do it justice here but to sum it up: the SOLID principles help to match computer science concepts such as cohesion and polymorphism to actual development in practice. Or, for dummies like me, if you write your code according to these principles, it can avoid problems later when the inevitable changes need to be made.

As an infrastructure guy, I don’t fully understand the details, but I can grasp the high level concepts and see that it’s not really so different to my world.  Look at a desktop delivery architecture for a large enterprise:

  • We abstract data from user objects, applications, operating system and hardware (which is possibly virtualised) and this gives us flexibility to extend (or substitute) parts of the infrastructure (well, that’s the idea anyway).
  • We only include those components that we actually want to use (no games, or other consumer functionality). 
  • We construct servers with redundancy then build layers of software to construct service platforms (which is a kind of dependency inversion). 

OK, so the infrastructure links may seem tenuous, but the principle is sound.  Sometimes it’s good for us infrastructure guys to take a look at how developers work…

2 thoughts on “Writing SOLID code

  1. Yeah. Although I’m not convinced about all the merits of SOLID. With all the abstraction going on it becomes very hard to figure out what’s going on without a debugger. Static analysis of code (i.e. by just looking at it) becomes next to impossible without tools or a very big head.

    Code reuse is the driver behind a lot of what you’re talking about but in my experience (other people’s mileage might vary) reuse is pretty limited within an organization. I might argue that if I’m not getting the benefit of reuse why should I make my head hurt-so-bad? This is actually something I’m thinking about writing a blog-entry about in the near future. Stay tuned :-)

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.