If S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that

Sounds confusing? It sure does to me at least.

Here is an easier version

If you have sub-classed a given class- in that case any program that uses your parent class via  a pointer or a reference – should continue to be able use any of the sub class that it may get instead of the Parent class- without any change in behaviour.

Now why is this important ?

Polymorphism was designed to provide a run-time binding that would make possible to use a different set of behavior depending upon the context. Which is all nice and cool- except that when you switch the behavior with another behavior which is semantically not compatible with the behavior of the parent class

Example- when its violated

We have a class Product. This has a method- order().The behavior of this method is that it places an order with  the vendor.

Now your inventoryControl System uses many Products and uses this method to order goods.

We decide to introduce a new range of products- Guns.

And since this needs authorization- the Guns class instead of placing the order with the vendor- sends an email to the Manager.

This would serve the purpose of informing the Manager that someone wants to purchase a Gun and may initiate a sequence of events leading to that. But it would create confusion for the system which would be waiting for a conformation from the vendor that the order was placed or may start a check as to why the Vendor hasn’t received an order yet…

Whenever you extend a class and override an already implemented method- watch out.You need to make sure that you are not violating the contract established by the Parent class. In contrast – its OK to override abstract methods.

Design by Contract (Dbc)

This principle leads to a very parallel concept- Design by Contract

What this basically says is – that whenever you subclass-

A) You should not impose newer or  stricter preconditions. Example : The method in the parent class accepts an int type parameter and has no problem with a negative value. If the method in the child class is unable to handle negative parameters while the parent class can- we are violating Dbc.

B) You cant weaken the post-conditions. Example: The method in the base class- places an order with a vendor and send you a confirmation email. If the method in your child class- simply places an order- but fails to send a confirmation email- it is violating Dbc.

On the same lines- a method in the child class- cant throw an exception- which is not in the throws class of the Prent class. The obvious reason is that the programs using references to parent class- would not be coded to handle this exception .

Who do we thank for this ?

Barbara Liskov: http://en.wikipedia.org/wiki/Barbara_Liskov

Interactive Software Engineering for Design by contract

 

“Only talk to your immediate friends”

Let’s get one thing clear- we are making software- not looking for enlightenment

In Software development- sometimes ignorance can be bliss.
The lesser your class knows- the less complicated it will be.The more it knows- more it has to worry about.

Lets start with an example
I have a class OrderManager. This class is responsible for Order creation.
It calls another class- OrderValidator- who is responsible for Order validation -i.e. whether the order is good to go or not. There could be many validations that need to be done. e.g. ( A) whether the input is correct. (B) Do we have enough inventory ? (C) Can we deliver the order by the date requested?
Now all these tasks may in turn be done by different classes- because you wouldn’t want to overload one class with multiple responsibilities.

So we end up with three classes
OrderManager- who oversees the complete operation
OrderValidator who gives a go ahead for the order creation. It will in turn call another set of classes to take this decision.
InventoryValidator – who validates the inventory

Now lets talk about “friends”
OrderValidator is a friend of OrderManager
InventoryValidator is a friend of OrderValidator
As long as Ordermanger is not aware of the existence of InventoryValdiator- you are following this rule
However if we expose the InventoryValidator to OrderManager- you are guilty of breaking the rule

Code Example I – Following the rule

class OrderManager
{

public void createOrder ()
{
orderValidator.validateOrder();
}

}

class OrderValidator
{

public validateOrder (Order anOrder)
{
inventoryValidator.validateInventory (order.getRequestedAmount());
}

}

Example II Breaking the rule

class OrderManager
{

public void createOrder ()
{
orderValidator.validateOrder();
inventoryValidator= orderValidator.getInventoryValidator()
inventoryValidator.validateInventory (order.getRequestedAmount());
}

}

class OrderValidator
{

public validateOrder (Order anOrder)
{
}

public InventoryValidator getInventoryValidator ()
{
return inventoryValidator ;
}

}

Why do we have this rule ?
Like I said earlier on- the less you know the better you will be.Consider the previous example.Lets say down the road the Inventory Management got more complex and you need to look at a dstributed inventory .Now the Order creation process hasn’t really changed. We are still checking for inventory- the only difference we are checking inventory in more places or in a different fashion

If we have designed the system as per the first example- you will not see any change made to the OrderManagement system- but the second system will almost definately impose a change on the OrderManagement

What can we do to follow this rule ?
Any method in your class can invoke only the following types of methods

A) Methods in the same class.

B) Methods on the parameters  to the method

C) Method of the objects that were instantiated in the method

D) Method of the objects owned as member of the class

If you follow the above- you will be a true protector of this rule

 

But isnt this too restrictive?
It sure is and takes lots of discipline to follow it. And like any other priciple- its a friendly guideline.

And who do we thank for this?
NorthEastern University.

 http://www.ccs.neu.edu/home/lieber/LoD.html

 

“A class should have only one reason to change.”

Every class exists for  a specific reason. When you design a class- its essential that you know what that reason is and you know it well. And that reason should be the only reason that the class exists and there should be no other reason for that class to exist.

Lets start by some examples
e.g. We have a class OrderValidator. Now this is a class which is written to validate an Order.
Now this class shall change only when a validation rule changes- and not for any other reason
If we change the name of the column in the table in the Database and you have a direct impact on this class- you are not following the Single responsibility principle
If you change the client from web to a desktop based swing client- and you feel the need to change this class. You are violating the Single responsibility principle

Another example – You have a class which sends a message to an external system.
This class should change only when the communication mechanism changes. Like you are adding more capabilities to send messages in different formats or via different channels.
If the message generation logic changes and you need to change the class which sends the message- you are guilty of violating the Single responsibility Principle.

But why do we have Single Responsibility Principle?
-More the reasons to change a class- more often will that class change. This will give rise to greater opportunities for defects to creep in.
-The more a class does- more complicated it will be and hence harder to maintain in the long run.

How do we enforce it ?
- Keep your classes concise. If you need to accomplish two tasks- write two classes. Don’t be shy about writing multiple classes. Number of classes doesn’t increase complexity as would by overloading the same class with multiple tasks.
- Good communication.Put the objective of the class on top of the class to remind yourself (and the poor souls who will work on the class after you are long gone) – what the objective of the class is.
Many times the class looses its objective- simply because it was not well communicated to all.
- Ask yourself questions. What all situations will warrant a change to this class? What can change in the requirements that I will have to revisit and change this class ?

What causes this rule to be broken ?
-Shortcuts.Often a developer feels too lazy to write a new class and would rather add another rmethod to the same class. A class may have had a specific purpose when it was written- but over time things might get muddled. As more and more people contributete to the project- each may not understand exactly what the purpose wa and may see the class in a different light.
-Ill-defined responsibility for the class. When the class is first conceived- that is the only time its responsibility is decided and it should be well defined in clear terms. and that reason should be embedded as comments on top of the class for all to see and honor.

But…
“I dropped a column from the table and now I have to change the Validator,the DAO layer, UI layer”
That’s OK. This principle doesn’t prohibit that a single change can cause multiple classes to change
If you have dropped an attribute from the Model- you have basically dropped the validation referring to that attribute. And since its a change in the validation- its OK to change the OrderValidator.

Finally…
As always- Single Responsibility Principle is a guideline for writing robust class. Not the law.There will be exceptions- always.

So who do I thank for this down-to-earth principle?
http://en.wikipedia.org/wiki/Tom_DeMarco

Good Luck !!!

© 2011 Technology Cafe Suffusion theme by Sayontan Sinha