- Software Architecture: Meta and SOLID Principles in C#
- Introduction to SOLID Principles
- SOLID Principles: Single Responsibility Principle (SRP)
- SOLID Principles: The Open/Closed Principle (OCP)
- SOLID Principles: Liskov Substitution Principle (LSP) In Practice
- SOLID Principles: Interface Segregation Principle (ISP)
Before investigating what the SOLID principles are and how to apply them properly, we need to understand why do we need them at all?
SOLID principles are all about designing software. But what is design? How to define the design of software?
Robert C. Martin in his book “Agile Principles, Patterns, and Practices in C#” stated that the design of software is source code itself. Martin Fowler wrote in his blog that architecture is the shape which code takes. Why is this so? Engineers produce documents, blueprints which specify how to build a product. The only thing which truly specifies how software works is the source code. You may say that source code is the product, but the product is the running program, not the source code itself.
Look at this from the following perspective. What is the input to a factory of circuit boards? Special electronic diagrams. In the case of software development, we have a factory which is called “compiler”. We feed it by the source code. A compiler builds software using the source code. And this leads to interesting thoughts regarding costs model of building software and, say, houses. When we build a house, it’s much cheaper to create a good design upfront rather than rebuild an entire house if we don’t like the result. It is just not feasible to rebuild a house each time we don’t like the result. The opposite we can say about software development. We can build binaries in a minute, roughly speaking. Big upfront design in case of software development is much more expensive than to draw a sketch, build the software and then tweak it along the way.
Software development process is somewhat unique because conducting a big upfront design we actually can’t guarantee that we take into account all the possible requirements. The software is the fluid substance and requirements tend to change very quickly. Because of such a fluid, uncertain nature of software requirements, we need to constantly keep the design as clean as we can. Saying clean, I mean as maintainable as we can. To determine whether the source code is clean or not we need to mark out the signs of design rotting. Developers refer to such signs as design smells.
We can mark out five major design smells:
- Needless Complexity
Let’s define them one by one.
The software is rigid if the cost of making a single change is very high. If something very simple takes many hours to implement, then the software is rigid. To overcome this problem, you might need to redesign the software. The primary source of rigidity is the high coupling between modules. When modules are highly coupled, then it’s very hard to introduce any changes with ease.
The software is fragile when small changes in one module cause bugs appearance in other, sometimes even unrelated modules. This smell is also often caused by poorly designed relationships between modules. To overcome fragility, you need to isolate dependencies.
The software is immobile when it’s components can’t be reused in other systems. Most of the time we should be able to extract a component without too many efforts and adapt for using in another system. And what a surprise, this smell is most likely caused by a tight coupling between components. To overcome this smell, you need to decouple components well.
The software is viscose when adding a single feature evokes dealing with tons of aspects including, say, transport layer security, marshaling and such things. In practice, you also can detect this smell by observing hard to perform check-ins, check-outs, and merges. And most likely, the primary reason for this smell is a tight coupling between components.
The software is needlessly complex when developers all the time are trying to forecast the future, anticipating upcoming changes, introducing excessive points of extension. Developers should concentrate on the current requirements, they should construct the supple architecture which can bend to be able to meet new requirements. Adding not needed points of extension yet is a bad practice which leads to a needless complexity.
Did you notice that almost all the smells are related to bad dependencies management? The major difference between object-oriented and not object-oriented languages is that OO-languages are capable of harnessing the power of dynamic dispatch. By using virtual functions and interfaces, we can invert the dependencies. In OO-languages when we make a call we don’t know which object will handle that call. This is because of polymorphism or dynamic dispatch. So, the key to achieving a good architecture is to manage the dependencies well. And here we reach the point when we’re ready to talk about SOLID principles.
SOLID principles are five principles which can be referred to as dependency management principles. They are all about relationships and operations between objects.
In this volume, we are going to dive deeply into the SOLID principles. The SOLID acronym was firstly introduced by Robert Martin aka Uncle Bob. SOLID implies five principles of software development:
- SRP – Single Responsibility Principle
- OCP – Open/Closed Principle
- LSP – Liskov Substitution Principle
- ISP – Interface Segregation Principle
- DIP – Dependency Inversion Principle
All these principles are based on the classic work of Bertrand Meyer. We are going to discuss all the principles one by one looking at examples of poor design and how to fix it applying an appropriate principle. We will also notice the difference between Mayer’s and Martin’s definitions of some principles what is also important for deep understanding.
What I also want to emphasize is that SOLID principles are not bound to any technology. You can apply them in any programming language, in Java for example.
Another point is that SOLID is not a goal by itself. The thing is that Fully SOLID code is an oxymoron. It’s impossible to write software which conforms SOLID in every single line.
It’s impossible to measure the “SOLIDness” of the code base. SOLID are the five principles which help us to create better software. They involve a great deal of philosophy, and you might think that this is bad. Well, you can treat it as a flaw, but actually, it’s not. It’s very important to feel this philosophy of designing software to become a better developer.
I’ll write from time to time posts on SOLID. Stay in touch.
You can take the full video course “Software Architecture: Meta and SOLID Principles” with a huge discount clicking here.
Also, consider the option to become a patron on Patreon, thank you in advance!