Microsoft released the beta version of its awesome IDE Visual Studio today! :) Check this out:
Can’t wait to start tinkering! :)
Btw, you can also get it free of charge from Microsoft. And, if you want to know more about what’s baked inside this new release, here is the blog post you should be reading.
This is an article was first published in the antique Barbarian Meets Coding website
When you start learning any object-oriented programming language, you usually go through the
very basic OOP concepts: abstraction, encapsulation, messaging, modularity, inheritance and
polymorphism. You learn these concepts, these mechanisms for code reuse and maintainability,
how to use them, the syntax but they don’t usually teach you how to leverage them. In other words,
you don’t really learn how to use them well. So in this post, I’ll try to remedy that by giving an
introduction to the principles of object oriented design as devised by Robert C. Martin (a.k.a. Uncle
Bob).
##Introduction
I’ve been thinking it for a while, and I believe it would be a great idea to start a series of posts about
programming best-practices, do’s and dont’s, conventions, and design patterns, both to create more
awareness and share this wonderful knowledge with other developers that might not have heard of
them yet, and also so I have a nice quick reference that I can come back to at any given time. Let’s
jump into it!
##The Principles of Object Oriented Design. Classes
The principles of object oriented design are condensed under the famous and catchy acronym of
acronyms SOLID which stands for:
S - The Single Responsibility Principle (SRP)
O- The Open Closed Principle (OCP)
L - The Liskov Substitution Principle (LSP)
I - The Interface Segretation Principle (ISP)
D - The Dependency Inversion Principle (DIP)
These principles represent a set of rules that allows us to improve the way we design and set up the
dependencies between our classes and, in term, allow us to create more flexible, reusable and robust
code. In the next following paragraphs I’ll be explaining shortly what they are all about, and how they
can improve the code we write.
The Single Responsibility Principle
“A class should have one, and only one, reason to change or, there should never be more than one reason for a class to change.”
This principle is based upon the fact that whenever a class handles more than one responsibility then
there will be more than one reason for it to change. The consequences are pretty clear, if we need
to change a given class for a number of different reasons, then this class is not going to be robust nor
easy to maintain. In this case, there is what we call a coupling of responsibilities that will lead to a
number of problems: modifying one of them, may have a negative effect on the others, it will imply
the need to recompile code that wouldn’t be necessary if the responsibilities were decoupled, and
it will allow the client of the class to access other responsibilities which it might not care for, are just
some examples.
Applying this principle, may be hard at first, as we usually tend to group functionalities within our
classes in the abstraction phase of our development cycle, but it is a great guideline nonetheless
when we refactor. Use this principle, and you’ll end up with smaller, well-defined, robust and
maintainable classes.
An example of a SRP violation could be a given Rectangle class which has a Draw method and
a CalculateArea method. In this context, the class is handling two responsibilities, it has two
reasons to change and thus is violating SRP. A way to decouple these responsibilities would be to
extract separate interfaces, and make the clients depend upon these interfaces.
The Open Closed Principle
“You should be able to extend a class behavior, without modifying it. or, A class should be open for extension but closed to modification.”
If you have been working in any brand of software development for any reasonable amount of time
you’ll have notice that one thing that characterises most projects is that your software, for one
reason or another, is going to change during its life cycle. Thus, it is pretty important to design your
software so it will be flexible (i.e. receives changes well) but also so it is robust (it doesn’t break, a
single change doesn’t result in an endless chain of changes). The Open Closed Principle does just
that, it leads our efforts when tackling this particular problem, saying that, whenever our application
needs changes, we should never modify old code that already works and is tested, but extend it with
brand new functionalities and code.
The Open Closed Principle is comprised by two main concepts or corollaries:
A class should be open for extension, which basically means that you should be able to
extend the behavior or functionality of this given class.
A class should be closed for modification, which means that you should never modify the
existing code of a class
But how do we obtain classes that adhere to the OCP? How do we achieve this? The answer is
through abstraction. Using interfaces or abstract classes we can define a fixed contract to follow
whilst being able to extend the behavior with as many implementations of those interfaces as we
want or need. It is to be noted though, that designing a class that is completely closed to any possible
change, it is quite an impossible task. Most of the times, you’ll have to decide strategically which kind
of changes your class will be prepared to handle (strategic closure).
As Robert C. Martin states, there are a great number of heuristics and common practices we use
daily that derive directly from this principle. For instance, never use global variables, as no module
that depends on a given global variable can be closed in relation to other module that might write
into it. Also, making all members of a class private (alas encapsulation) prevents others classes from
depending on these members and thus closes them.
You can get some extended information within this OCP article.
As a last note of interest, although I have been mainly talking about classes, you should know that
you can apply the OCP not only to classes, but to any software entity that you can think of, methods,
modules, anything. Use this principle, and you’ll improve the maintainability of your code drastically.
The Liskov Substitution Principle
“Derived classes must be substitutable for their base classes or, What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.”
As mentioned in the previous section, we make use of abstractions (and polymorphism) to let our
classes adhere to the Open-Closed Principle. In order to make a proper use of inheritance, so our
derived classes will still subscribe to OCP, we guide ourselves by the Liskov Substitution Principle.
The whole point here is that a derived class should work as expected i.e. should behave (at a
minimum common denominator) as portrayed by the base class, so that, classes or methods that
have a reference to the base class, will be able to use instances of the derived classes without being
aware of it(thus avoiding hard-coded dependencies).
If you listen to Hanselminutes podcast featuring Robert C. Martin, Robert puts the classical example
of the Rectangle base class and the Square class that derives from it. So you have a Rectangle class
in your application, and you want to use a new Square class, so you think… well a Square “is-a”
Rectangle isn’t it? (it just has the same width and height) So you make it derive from the Rectangle
class and wire it up so when you set the width, the height will be set as well and vice versa. Bang!
Problem is that another developer that is working with Rectangles, doesn’t need to know what
Rectangles really are at runtime, but still expects them to behave according to the base class
definition. In this case, Square doesn’t conform to LSP and may end up causing problems based on
unfulfilled assumptions. The point here is that, while it is a valid logical premise to relate a square
with a rectangle, it might not be as useful from a code perspective. This example is also known as the
circle-ellipse problem.
This was a pretty subtle violation of LSP. However, in practice, any time you use the common switch
statement to check the type of an object at runtime in order to do this or that, you are violating LSP
and OCP (new derived types will force you to modify that switch block).
The Interface Segregation Principle
“Make fine grained interfaces that are client specific or, Clients should not be forced to depend upon interfaces that they do not use”
This principle may be one of the least importance due to its very focused field of application: fat
interfaces. The whole point is that, when we have a class that has a fat interface (an interface with
a lot of methods) and a series of clients that depend upon this interface, we should refactor our
solution so that, any given client only depends on a new interface that comprises only those methods
of the original interface that the client needs to use. This is, the solution is to group the methods of
the fat interface, into smaller and more cohesive interfaces.
The problem of using fat non-cohesive interfaces is that, they create a coupling between its clients,
i.e. a given client may force changes on the interface that will impact another client even if they use
non-related methods. Again, the solution to this problem is to extract smaller interfaces for each
client to depend upon. This way, changes will be more contained and decoupled, as clients will only
depend on their respective interfaces.
The Dependency Inversion Principle
“Depend on abstractions, not on concretions or, A. High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details B. Abstraction should not depend upon details. Details should depend upon abstractions.”
When I introduced the OCP before in this article, I said that the way to implement it was to make
use of abstractions and polymorphism. I also introduced LSP in order to guide the implementation of
inheritance so our derived classes won’t break OCP. So, if you use both OCP and LSP strictly, you will
notice how a new pattern or structure emerges from it that can be generalized into what is known as
the Dependency Inversion Principle.
This is one of the most useful principles, as it allow us to design software that is flexible (easy to
change or extend), robust (reacts well to changes i.e. doesn’t break everywhere) and reusable (the
parts of the system are very decoupled and we can extract them and use them in other projects),
and whose main aim is to address bad design. The cause of bad designed software - software that
is rigid, fragile and inmobile (opposite to flexible, robust and reusable in this case) - is the heavy
hard-coded dependencies between its modules. These dependencies can in turn force the need of
a cascade of changes when we want to introduce a tiny little change in the system (rigidity), or can
result in a chain of unexpected errors (fragility), and of course, make impossible to reuse code in
other applications because everything is so entwined that we might as well bring together the whole
system.
The DIP addresses this problem saying no to hard-coded and top-down dependencies. The high-
level modules should not depend upon the low-level modules, everything has to depend upon
abstractions (thereby we get and “inverted” dependency). This way, the high level modules don’t
know exactly what they depend upon, they just know they are using something that must adhere
to a given interface, and thus, everything that follows that interface contract can be plugged in
(or plugged out). If you extend the principle to the whole system you end up with a set of highly
decoupled modules, that are completely isolated from changes in other modules and that can be
easily reused. You end up with a well defined set of interfaces or abstractions that define the policy
of your system, and a set of concrete implementations that are connected via these abstractions.
Where Can I Find Out More?
As you might have inferred already, the main reference within this field is Robert C. Martin. You can
find a lot of extra information and examples at his object-oriented design website and the related
Object Mentor website. You might also want to take a look at his best-practices books:
And last but not least, there is also a very interesting Hanselminutes podcast featuring Uncle Bob and
the SOLID principles.
Afterword
So, I hope you have enjoyed this introduction to the principles of OOD, and learnt a little in the
process. I’ll be writing more best-practices stuff in the non-too-distant future ^_^.