Following is a collection of some principles\suggestions\rules\guidelines- whatever you wish to call them- to be kept in mind while designing software.

Some of this was inspired by Head-First Design patterns book- which I concluded recently. An excellent read- BTW.

I would recommend every earnest programmer to keep these principles posted at a visible location in his/her work place.

A) The Single Responsibility Principle – A class should have only one reason to change.
B) Open Closed Principle – Classes should be open for design but closed for modification .
C) Liskov substitution principle
D) Interface Segregation Principle – The dependency of one class to another one should depend on the smallest possible interface.
E) Dependency Inversion Principle – High level modules should not depend upon low level modules. Both should depend upon abstractions.
F) Encapsulate what varies
G) Favor composition over inheritance
H) Program to interface ,not implementations
I) Strive for loosely coupled designs between objects that interact
J) Depend upon abstraction, do not depend upon concrete classes
K) Principle of least knowledge – Only talk to your friends
L) Inversion of control- Don’t call us, we’ll call you.
M) Tell, Don’t Ask

 

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

© 2011 Technology Cafe Suffusion theme by Sayontan Sinha