Sunday, May 11, 2014

Session 4 - Liskov's substitution Principle, Interface Segregation Principle and the Dependency Inversion Principle

<Meh>

In this session, I shared Liskov's substitution Principle, Interface Segregation Principle and the Dependency Inversion Principle.

The last two principles are very straight forward so I'll stick with the LSP for this entry.

This principle, although very simple, is sometimes extremely difficult to implement properly. It comprises both the OCP and the SRP and in most cases, is violated when using inheritance and is, again in most cases, solved by using composition.

It always starts with a great idea: why don't I create a base class that can encapsulate all the common functionality to everything that will inherit it. A noble idea, but sometimes very misguided.

What I've found is that if you're the kind of person who loves base classes and think that everything can be solved using base classes, you've most likely violated this principle in horrific ways. Why? Simply because inheritance is not always the answer. As simple as that. The LSP clearly shows when inheritance is not suitable to solve a particular problem.


One of the things that also makes this principle a tricky one is that it can be violated before it gets violated. One of the most important things when it comes to good code, is cohesion. How easy is it to understand the code. A good developer knows how to properly show his intent in the code that he writes. Now, in this case, the intent, not just the code, can be a violation of the principle. The trick is to identify when you're starting to go down a path that will eventually lead to violating the principle.

In order to identify whether your intent is true or not, I've reworked the original definition.
Orig: functions that use reference to base classes must be able to use objects of derived classes without knowing it.
My version: you must be able to apply the same code in a function, where that function references the base object as a parameter, to all super instances of that base class without having to make distinction between them

for ex: I have a base DAL class. I use this sucker to persist my entities to the database. Now, for new entities, I need to update the createdDate property and for existing entities, I need to update the updatedDate property. Now, following the original definition, this code is fine. Following my definition, it's not. Why? Because you're distinguishing between whether the entity is new or now.

Now, you may ask, surely that does not actually violate the rule.. and you're right. It doesn't... not yet in any case. Lets have a closer look at what we did. We introduced a business rule. A business rule into the base class. Is it starting to make more sense? What's the intention of the LSP? It's to keep your base class clean and less prone to change. Do you know what changes? Business rules.

The moment we start introducing business rules into our base class, we run the risk of making something that should be very stable, very brittle and when your base class is brittle, everything that implements it, is as well.

That, I feel, is the true intention of the LSP. To keep your base classes stable by removing everything that might cause it to change.

You can now see why the example violates the rule and also why it's sometimes so difficult to spot these violations. The sad thing is that for the most part, you won't spot the violation until its too late and you're sitting with a maintenance nightmare.


Anyways, enough of that. Below are the links to the various slides and what not

Presentations:
http://www.slideshare.net/DeonMeyer/code-like-a-ninja-session-4-liskov-substitution-principle
http://www.slideshare.net/DeonMeyer/code-like-a-ninja-session-5-interface-segregation-principle-34406317
http://www.slideshare.net/DeonMeyer/code-like-a-ninja-session-6-dependency-inversion

Code:
https://github.com/SheepWorx/Training/tree/master/LiskovSubstitutionPrinciple
https://github.com/SheepWorx/Training/tree/master/InterfaceSegregationPrinciple
[no code sample for DIP since we kinda covered it in the SRP. Refer to the 2. ExposingUtilsAntiPattern code sample there]

Next up we'll be tackling some design patterns, starting with the Factory Pattern (Abstract Factory and the Factory Method).

</Meh>

No comments:

Post a Comment