Interface Segregation Principle

Before the Kurukshetra War, Lord Krishna had a conversation with Arjuna, one of the things he said:

Therefore I tell you: be humble, be harmless, have no pretension, be upright, forbearing, serve your teacher in true obedience, keeping the mind and the body in cleanness, tranquil, steadfast, Master of ego, standing apart from the things of the senses, free from self; aware of the weakness in mortal nature, its bondage to birth, age, suffering, dying;

One of the wonderful results of writing about right coding and better code philosophy is the oportunities it provides to be humble. I frequently write bad code and don’t follow the principles I know to be correct.

First, let’s define the Interface Segregation Principle (see the excellent Uncle Bob Article)

Clients should not be forced to depend upon interfaces that they do not use.

Frequently, when you look at C# code, you’ll see interfaces defined that have a lot of members defined (Try implementing a Forms Authentication Provider and you’ll see what I mean!). The downside of this is that it’s confusing for the client to know which methods to use. It also forces each alternate implementation of the interface to implement a bunch of methods that maybe are not relevant (in the example of forms authentication, you have to handle email addresses even if you only want to implement a username/password).

The Interface Segregation Principle suggest sthat our interfaces should be simpler and more focused, supplying only the members needed for a specific use. If one object implements more than one interface, that’s fine, but an object that supports multiple uses should provide targeted interfaces for each of those uses.

Let’s look at how I violated this principle in the my UI code:

Each endpoint on the Login Controller has a corresponding method on the interface. It’s impossible to change our just one implementation. You have to provide a replacement for the whole login service in order to implement any changes.

The fix is easy:

And suddenly, each individual service can be swapped out separately. It’s also much easier for me to refactor my LoginService implementation to comply with the Open-Closed Principle and Single Responsibility Principle.

There is always room for better code, and the SOLID principles are wonderful tools in learning to write better patterns.

Dependency Injection Principle

Remote controls are fantastic. The ability to stand over here and control something over there is like magic. Since the first remote controls, which only controlled a single device, were made we’ve extended the idea of the remote control quite a bit. Your remote for your TV can control your Blu-Ray player. You can buy a remote control from Logitech that can be programmed to turn on your TV, set the sound on your stereo, and dim the lights in your TV room….all at the press of one button. You can buy a keychain remote control that turns off all the TVs in a restaurant or bar. In the movies, Adam Sandler made a movie where he found a remote control that controls the whole universe.

The magic of remote controls is in the gap between the controller and the thing controlled. There isn’t a wire. They are not wired together. They are loosely coupled.

We have a good habit of loosely coupling the top side of our code. Anybody can call one of our methods. They aren’t hard wired for only one consumer.

However, on the underside of our code, we fail to couple loosely. We create new instances of database connections and proxy classes. We use Static methods to get resources and get information from the server context. Each time we do this, we break the magic of the remote control. These tight couplings prevent us from changing the implementation of our dependencies (the database connections, proxy classes, and resource systems).

The Dependency Injection Principle protects us from our urges to tightly couple to our dependencies. It states:

1. High Level Modules Should Not Depend Upon Low Level Modules. Both Should Depend Upon Abstractions.

2. Abstractions Should Not Depend Upon Details. Details Should Depend Upon Abstractions.

Frequently, Dependency Injection is implemented by using the constructor. In our classes constructor, we pass in references to the database connection or service proxy. This provides the loose coupling in one easy step. Using a IOC container, like Autofac or StructureMap then automates constructing the object by providing a central point where we can define all those dependencies and compose them into objects.

If you’d like to know more, read the excellent Uncle Bob article.

Liskov Substitution Principle

If you were an infantryman in the 14th century, charging up a hill with your rifle (they weren’t really called rifles yet, but let’s not quibble), you’d not only have to deal with the mud and the thunder of the battlefield, but the difficult task of reloading your rifle. Powder. Padding. Bullet. Wadding. Priming. Worst of all, eventually you’d put your hand into your bullet pouch, and find it empty.

Once that happened, you were done shooting for the day. You couldn’t borrow a bullet from the guy next to you. It either wouldn’t fit, or it would cause your gun to explode. You see, each and every rifle in use by your army had been made by hand, and no two barrels were the same. You had to find a bullet that would fit, and that took some time. Eventually with bore width for gun barrels was standardized, even centuries before Honore Blanc demonstrated the first true interchangeable parts to Thomas Jefferson. Today, we take it as a given that we can use similar parts interchangeably without risk, but that’s due to centuries of effort to make sure that our common assumptions are followed by everyone.

In software, the Liskov Substitution Principle is meant to bring the same benefits to our code. It states that Methods that use references to base classes must be able to use objects of derived classes without knowing it. This is a simple concept, but it is easy to accidentally violate the principle if you don’t give sufficient thought to your derived classes.

An obvious failing is to not use virtual/override keywords on your methods. This would mean your subclass code never gets called when someone is using a reference to the base class. A more significant issue is when the subclass changes behavior in a way that violates the assumptions of the base class. “Square” could be a subclass of “Rectangle”, but when you change the height of a square, the width changes automatically. This is not true of a rectangle. Unintended side effects can break your code at runtime, often unpredictably. Following the Liskov Substitution Principle means you can avoid some problems. (If you want to research more, the Uncle Bob article is great, and “Design By Contract” is a similar concept with a lot of coverage.)

Commonly we use the language feature of inheritance for things that it was not designed for. If you need to re-use code, there are other ways of including it than putting it in a base class, composition is frequently better than inheritance. Similarly, polymorphism can be made more granular by implementing interfaces, rather than having a over-broad base class that may or may not be fully implemented by its inheritors.

The Open Closed Principle

The first sun-dried bricks were made in Mesopotamia (what is now Iraq), in the ancient city of Ur in about 4000 BC.

The Romans made use of fired bricks, and the Roman legions, which operated mobile kilns, introduced bricks to many parts of the empire. Roman bricks are often stamped with the mark of the legion that supervised their production.

In 1949, a carpenter from Denmark named Ole Kirk Christiansen started selling the Lego. Like previous bricks, the Lego was immutable, and could be used to create large structures. Unlike the bricks that came before it, Legos can be detached and replaced with other Legos, allowing structures to be redesigned and extended without destroying what came before.

The Open-Closed Principle (see the wonderful Uncle Bob article) describes a way of making our code more like Legos. The basic statement is that once a class is written and tested, it should never be changed. Changing our code turns our bricks back into mud, and can create huge cascades of failure. However, code that doesn’t change can be trusted to work the way it was previously written and tested to work.

The problem is this: requirements change. How do we change our programs if we can’t change our classes?

Our classes should be:

1) Closed for Modification….the source code for a module doesn’t change. Ever.

2) Open for Extension….the behavior of the class can be added to as requirements change.

You’ve seen this done throughout .NET. Controls fire events, and when those events are fired, all sorts of changes can be made. If our classes allowed others to listen to events, we could extend their behavior without changing them. A number of other patterns, including Façade, Command, and Chain of Responsibility, as well as simple inheritance and polymorphism can be used to provide openness for extension.

The use of re-usable, unchangeable bricks can make our coding easy, just like playing with Legos.

Single Responsibility Principle

On the day I was born, the Egyptian military surged across the Suez Canal with 100,000 men and 1,350 tanks into the Sinai Peninsula. Simultaneously, the Syrian army sent 800 tanks into the Golan Heights. This simultaneous attack against a surprised Israel led to an amazing conflict over the course of the next several weeks that changed the state of affairs in the middle east.

At the time this was happening, Robert C. Martin (“Uncle Bob”) had already been in the software business for three years. Today, he is still a practicing programmer, working with code every day, and extending his knowledge of the art and skill of modern software development.

One of Uncle Bob’s largest contributions to our understanding of object oriented programming is a set of principles known as SOLID, which I’d like to share with you.

Today, I’m going to talk briefly about the Single Responsibility Principle, which is the ‘S’ in SOLID. This principle is very easy to remember. It simply states that any class that you write should only have one reason to change. We frequently change our classes after we write them, because the customer changes directions on us, or because our understanding of the technical requirements change.

Where we get into trouble is that our classes have too many things in them. Changing one thing causes a change to something else. Changing one thing requires us to re-test something else. Changing one thing requires us to change things somewhere else. We create extra work for ourselves. We create extra bugs for ourselves.

The Single Responsibility Priniciple is a discipline which can keep us from creating extra, unnecessary work for ourselves. By writing our code more simply, in smaller chunks, we can insure that WHEN change comes, it affects the smallest amount of code possible.

Uncle Bob’s book chapter on the Single Responsibility Principle provides a deeper view into the subject.