Showing posts with label design principle. Show all posts
Showing posts with label design principle. Show all posts

Tuesday, May 24, 2011

The Square and Rectangle problem OR Circle and Eclipse Problem

Most people would think that a Square is a special kind of Rectangle and therefor intuitively inherit their Square class from the Rectangle class to be able to reuse code. Similar way goes for Circle and eclipse, where circle is considered eclipse's extension and special case.


Notice that the Rectangle have a couple of traits that the Square does NOT and vice versa. First of all the Square has only *ONE* attribute; size, while the Rectangle have *TWO* attributes; width & height. And this fact may for some problems be quite tricky to discover sometimes. And if you do the capital sin of inheriting your Square class from your Rectangle class, then you might currently get around it by hiding the width property of the Rectangle somehow, maybe by convention, and then just let the size property of the Square forward the call to height or something similar, but this is always wrong!

So consider the rectangle class:
public class Rectangle   
{
private double width;
private double height;
public void SetWidth (double w) { width = w; }
public void SetHeight (double h) { height = h; }
public void GetWidth () { return w; }
public void GetHeight () { return h; }
public void GetArea () { return width * height; }
}

Consider the square class:
public class Square  
{
private Rectangle r;
public void SetWidth (double x) { r.SetWidth (x); r.SetHeight (x); }
public void SetHeight (double x) { r.SetWidth (x); r.SetHeight (x); }
public void GetWidth () { return r.GetWidth; }
public void GetHeight() { return r. GetHeight; }
public void GetArea () { return r. GetArea; }
}

But Square has to somehow guarantee that its width and height are same or in other words height is redundant. So if client changes height, it has to change width accordingly.
Why is it that the client code gets affected by the derived class object reference being given in place of a base class object reference? Because the derived class's post-condition is weaker than that of the base class. The base class promises that if you call the SetHeight function, it will change the value of the height, but will do nothing to the value of width. But nothing like that happens in derived class and therefore, a client who is relying on the above base class gets affected when it gets a derived class object reference instead.

Therefore, inheritance is not the right approach in this situation. Delegation is the right choice. See here for solution to this problem.

Thursday, May 19, 2011

Design Principles

The principles of design include following:

These all principles help us manage dependencies and coupling among the software modules in a better way. These principles expose the dependency management aspects of OOD as opposed to the conceptualization and modeling aspects. This is not to say that OO is a poor tool for conceptualization of the problem space, or that it is not a good venue for creating models. Certainly many people get value out of these aspects of OO. The principles, however, focus very tightly on dependency management.

Dependency Management is an issue that most of us have faced. Whenever we bring up on our screens a nasty batch of tangled legacy code, we are experiencing the results of poor dependency management. Poor dependency managment leads to code that is hard to change, fragile, and non-reusable. On the other hand, when dependencies are well managed, the code remains flexible, robust, and reusable. So dependency management, and therefore these principles, are at the foudation of the -ilities that software developers desire.

The first five principles are principles of class design. They are:

SRP The Single Responsibility Principle A class should have one, and only one, reason to change.
OCP The Open Closed Principle You should be able to extend a classes behavior, without modifying it.
LSP The Liskov Substitution Principle Derived classes must be substitutable for their base classes.
DIP The Dependency Inversion Principle Depend on abstractions, not on concretions.
ISP The Interface Segregation Principle Make fine grained interfaces that are client specific.

The above 5 principles are called SOLID, derived from their first name.

Principle of least knowledge or Law of Demeter (LOD)

The principle states: Each unit should only talk to its friends; Don’t talk to strangers. A method of an object should invoke only the methods of the following kinds of objects:
    1. itself 2. its parameters 3. any objects it creates/instantiates 4. its direct component objects

Violation of above principle

Below is an example of some code breaking this principle:
Interface : IOrderManager

public interface IOrderManager
{
void AddItemToOrder(IItem item);
void RemoveItemFromOrder(IItem item);
void ChangeItemName(IItem item, string name);
}


Interface: IItem


public interface IItem
{
int Id { get; set; }
string Name { get; set; }
}

Class: Item : IItem

public class Item : IItem
{
private int _Id;
private string _Name;

public int Id
{
get { return _Id; }
set { _Id = value; }
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
}
Class :OrderManager : IOrderManager

public class OrderManager implements IOrderManager
{
private IOrder _Order;

public OrderManager()
{
_Order = new Order();
_Order.Items = new List<IItem>();
}

public void AddItemToOrder(IItem item)
{
if (_Order.Items != null)
{
if ( ! _Order.Items.Contains(item))
{
_Order.Items.Add(item);
}
}
}
public void RemoveItemFromOrder(IItem item)
{
if (_Order.Items != null)
{
if (_Order.Items.Contains(item))
{
_Order.Items.Remove(item);
}
}
}
public void ChangeItemName(IItem item, string name)
{
if (_Order.Items != null)
{
if (_Order.Items.Contains(item))
{
_Order.Items[_Order.Items.IndexOf(item)].Name = name;
}
}
}

In the above example the OrderManager has the responsibility of adding and removing Items to and from the List collection in the Order class, and even worse it has the responsibility of changing the name of a particular Item inside that collection. This tightly couples the OrderManager to the Order and Item class, if we would change how the Order class is maintaining her Items than we automatically have to change the OrderManager class. The Order should be responsible for its Items, not the OrderManager. Below is the Law Of Demeter implementation of this example:
Interface: IOrder



public interface IOrder
{
void AddItem(IItem item);
void RemoveItem(IItem item);
void ChangeItemName(IItem item, string name);
}


Class: Order : IOrder


public class Order implements IOrder
{
private List<IItem> _Items;

public Order()
{
_Items = new List<IItem>();
}

public void AddItem(IItem item)
{
if (_Items != null)
{
if (!_Items.Contains(item))
{
_Items.Add(item);
}
}
}
public void RemoveItem(IItem item)
{
if (_Items != null)
{
if (_Items.Contains(item))
{
_Items.Remove(item);
}
}
}
public void ChangeItemName(IItem item, string name)
{
if (_Items != null)
{
if (_Items.Contains(item))
{
_Items[_Items.IndexOf(item)].Name = name;
}
}
}
}

Class: OrderManager : IOrderManager


public class OrderManager implements IOrderManager
{
private IOrder _Order;

public OrderManager()
{
_Order = new Order();
}

public void AddItemToOrder(IItem item)
{
_Order.AddItem(item);
}
public void RemoveItemFromOrder(IItem item)
{
_Order.RemoveItem(item);
}
public void ChangeItemName(IItem item, string name)
{
_Order.ChangeItemName(item, name);
}
}

Now we can change how the Order class is keeping its Items without having to change the OrderManager. One nice rule of thumb is: One dot should be enough.

Liskov's Substitution Principle(LSP)

The Liskov’s Substitution Principle provides a guideline to sub-typing any existing type. It is L in SOLID principles.

Definition
 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 behaviour of P is unchanged when o1 is substituted for o2 then S is a subtype of T.

Here is an easier version:
Functions or methods that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
While checking for specific types is technically a violation of LSP, it's more commonly thought of as an OCP violation. LSP is more focused on the behavior of the specific instance itself, rather than types operating upon the specific instance. Below is an example of some code breaking this principle:

Example:
Example1
Violation of LSP - Consider the case of Rectangle and Square problem.

Right way to handle solve this problem - Solution to rectangle square problem.


Summary
This principle is just an extension of the Open Close Principle and it means that we must make sure that new derived classes are extending the base classes without changing their behavior.

Interface Segregation Principle (ISP)

The interface-segregation principle is one of the five SOLID principles of Object-Oriented Design.


Definition
Formally stated, the ISP reads:
Many specific interfaces are better than a single general interface.


Need
Couple of times, we see that we are bound to implement interfaces which are fat, what I mean is we have to implement the methods which we really don't need or would be of any help to us.

This coding tip explains how we can really identify a fat interface and refactor the code in order to make the interface thin without really breaking the application.


Example
Why is this? Look at the following example. Imagine that in your application you are required to write some Data Access Objects (DAO). These data objects should support a variety of data sources. Let's consider that the two main data sources are file and database. You must be careful enough to come up with an interface-based design, where the implementation of data access can be varied without affecting the client code using your DAO object. The following design is a good example of the above requirements (figure below).



There's another aspect that needs be to considered. What happens if the data source is read-only? The methods for inserting and updating data are not needed. On the other hand, if the DAO object should implement the DAO interface, it will have to provide a null implementation for those methods defined in the interface. This is still acceptable, but the design is gradually going wrong. What if there is a need to rotate the file data source to a different file once a certain amount of data has been written to the file? That will require a separate method to add to the DAO interface. This is just to add the flexibility to the clients using this FileDAO object to enable them to choose either the normal append feature to the file data source or to make use of the improved file rotation feature.
With the DatabaseDAO implementation now broken, we'll need to change it, to provide a null implementation of the new method added to the interface. This is against the Open-Closed Principle.
So, what went wrong? In the basic design, the fact that the file data access operation and database access operation can differ fundamentally must be considered. We defined the behaviors for both the data access operation, and the database access operation together in a single interface. This caused problems at a later stage in the development. It is not necessary to be a guru in Object Oriented System Design, to solve this problem nor is vast experience in designing software applications needed. What is necessary is to think of interfaces as the behaviors to be provided through particular objects. If two or more objects implementing the interface depict different sets of behaviors, then they probably cannot subscribe to a single interface.
When a single interface is designed to support different groups of behaviors, they are, by virtue, inherently poorly designed, and are called Fat interfaces. They are called Fat because they grow enormously with each additional function required by clients using that interface.
Thus, for the problem with the Data Access Objects, follow the Interface Segregation Principle, and separate the interfaces based on the behaviors. The database access classes and file access classes should subscribe to two separate interfaces. The following design is obtained by applying the Interface Segregation Principle (Figure below).
 
With this design, the Fat interface symptom is avoided and the interfaces clearly delineate their intended purpose. If any imaginary data access object requires a combination of operations defined in both of these interfaces, they will be able to do so by implementing both the interfaces.

I think the key is if you find yourself creating interfaces that don’t get fully implemented in its clients, then that’s a good sign that you’re violating the ISP. You can check out the link to this pdf for more complete information on the subject.

Open Close Principle ( OCP )

The Open-Closed Principle lies at the heart of the object-oriented paradigm. In a sense, we can say that its the goal of our object-oriented designs. Examining a myriad of patterns reveals its application often. It states the following:
Software entities should be open for extension, but closed for modification.

So it has 2 attributes:
  1. Open For Extension - It is possible to extend the behavior of the module as the requirements of the application change (i.e. change the behavior of the module).So classes can be extended
  2. Closed For Modification - Extending the behavior of the module does not result in the changing of the source code or binary code of the module itself.

Example - Violation of OCP
Consider the classes hierarchy:

class Animal
{
protected String sound;
}

class Cat extends Animal
{
//getters and setters
}

class Dog extends Animal
{
//getters and setters
}

Now consider the class, which manages the animals and make them sound.
SoundManager.java
public class SoundManager{
private List<Animal> animalList;

public SoundManager(){
animalList = new ArrayList<Animal>();
}

public void add(Animal a){
animalList.add(a);
}
public void makeSound(){
for(Animal a : animalList)
if(a instanceof Cat)
makeMew(a);
else if(a instanceof Dog)
makeBark(a);
}
public void makeMew(Animal a){
print(a.getSound());
}
public void makeBark(Animal a){
print(a.getSound());
}

}
Note that this is not a good solution because suppose a new class Lion comes into picture, and it has a sound called roar, you have to edit the code and another if else or switch() to make that work. So it is violation of OCP.

Solution
So a good solution would be to make makeSound function part of class hierarchy itself.

class Animal
{
protected String sound;
public abstract void makeSound();
}

class Cat extends Animal
{
//getters and setters
@Override
public void makeSound(){
print("mew");
}
}

class Dog extends Animal
{
//getters and setters
@Override
public void makeSound(){
print("bark");
}
}

Now it is much robust to write the above code, no matter how many animals you add.
public class SoundManager{
private List<Animal> animalList;

public SoundManager(){
animalList = new ArrayList<Animal>();
}

public void add(Animal a){
animalList.add(a);
}
public void makeSound(){
for(Animal a : animalList)
a.makeSound();
}
//makeBark, makeMew() functionr removed

}

Note of caution
It sems from the 80s and 90s when OO frameworks were built on the principle that everything must inherit from something else and that everything should be subclassable. So for example take a class called Stack in java, it subclasses Vector. So why on earth will you need push and pop if you can directly access element's index?
Joshua Bloch in his famous book "Effective Java" gives the following advice: "Design and document for inheritance, or else prohibit it", and encourages programmers to use the "final" modifier to prohibit subclassing.
So keep in mind, use inheritance only when its compulsory, otherwise try to make your classes final if you feel in future you won't be extending them.

Summary
It should be clear that no significant program can be 100% closed. So we may need to change the code depending on the requirement, but we can try to make our code as robust as possible. Though it comes with experience.

Dependency Inversion Principle ( DIP )

Theory:
The dependency inversion principle OR DIP states 
  • High level modules should not depend upon low level modules. Both should depend upon abstractions  
  • Abstractions should not depend upon details. Details should depend upon abstractions
This principle seeks to "invert" the conventional notion that high level modules in software should depend upon the lower level modules. The principle states that high level or low level modules should not depend upon each other, instead they should depend upon abstractions. This is best illustrated by an example.

DIP is "D" of SOLID in design principles.

Example
Example of this can be seen here.

Dependency inversion and dependency injection
Another practice often associated with the Dependency Inversion Principle is Dependency Injection. Dependency Injection encompasses a set of techniques for assigning the responsibility of provisioning dependencies for a component to an external source. The goal of Dependency Injection is to separate the concerns of how a dependency is obtained from the core concerns of a component.

The practice of dependency injection is often discussed alongside the Dependency Inversion Principle as a facilitating pattern for supplying implementations of the client interface to the client component at run time. While other patterns such as Service Locator and Plug-in can be used to facilitate the Dependency Inversion Principle, Inversion of Control in the more common solution due to its ability to decouple components from how their dependencies are obtained.

One potential stumbling block newcomers to these design approaches face is in the similarity of terms used in describing these approaches. For instance, taken at face value, the phrase “Dependency Inversion” might conjure up the idea that dependency requirements are being inverted (as in turned inside out) rather than the inversion of dependency (as in reversal) between higher-level components and lower-level components. While the former is an adequate understanding of what dependency injection is, it doesn’t describe the goal of the Dependency Inversion Principle. While certainly complimentary, how dependency implementations are obtained is orthogonal to the module dependency concerns set forth by the Dependency Inversion Principle.


Benefits and Consequences
The approach advocated by the Dependency Inversion Principle provides a useful option for decoupling components from their external dependencies. By following the guideline that higher-level components shouldn’t depend upon lower-level components, core functionality within an application can be more easily used in different contexts.
While applying the Dependency Inversion Principle enables higher-level components to be used in a different context, it unfortunately negatively impacts the ability to reuse lower-level components. While this may at times be an optimal compromise, it is not always the case that higher-level components possess the greatest need for decoupling.
The core business components within an application often encapsulate a rich set of behavior tailored to a specific context. While such components may be of tremendous benefit to applications requiring the same behavior, it is their specificity that tends to limit the context where reuse is possible. In contrast, lower-level components often encapsulate more generic functionality which is applicable across a wider range of contexts.
Consider for example the development of a custom logging component. Logging is generally a concern shared by many components across all applications within an enterprise. In following the Dependency Inversion Principle, the logging component would be developed to depend upon a client-owned interface package to allow higher-level components to remain decoupled from the specific logging implementation. While this enables a higher-level component to be reused without requiring the specific logging implementation, it doesn’t allow the logging component to be easily used by other applications.
While the Dependency Inversion Principle does account for the reuse of lower-level components by maintaining the client interface in a separate package, assigning ownership of this package to one or more consumers of a lower-level component can itself be problematic. In doing so, this creates a form of associative coupling between clients which may have diverging interests that affect the agreement upon, or stability of the interface contract. Additionally, the resulting contract, naming conventions, and deployment strategy may lack the objectively and elegance that might follow more naturally from assigning the ownership of the interface package to the lower-level component.

Wednesday, March 2, 2011

Single Responsibility Principle (SRP)

The Single Responsibility Principle.
  • Each responsibility should be a separate class, because each responsibility is an axis of change.
  • A class should have one, and only one, reason to change.
  • If a change to the business rules causes a class to change, then a change to the database schema, GUI, report format, or any other segment of the system should not force that class to change.
So in brief, principle states: There should never be more than one reason for a class to change. Below is an example of some code breaking this principle.

Case 1 : Violating SRP


 
public class WeatherDisplay
{
private int _Temperature;
private int _WindSpeed;

public WeatherDisplay(int temperature, int windSpeed)
{
_Temperature = temperature;
_WindSpeed = windSpeed;
}

public void DisplayWeather()
{
DisplayTemperature();
DisplayWindSpeed();
}

private void DisplayTemperature()
{
println("The current temperature is: " + _Temperature + " degrees celcius.");
}
private void DisplayWindSpeed()
{
println("The current wind speed is: " + _WindSpeed + " meters per second.");
}
}





As you can see there are 2 distinct responsibilities for the class WeatherDisplay (you could even say there are 3 responsibilities). You could say one is to display the temperature and the other is to display the wind speed. Now because we are talking about 2 responsibilities we can also say that there are at least 2 reasons why we would / could change this class in the future, the temperature should be displayed in Fahrenheit and the wind speed should be displayed in knots.

Case 2 : Following SRP


Below we see how we could solve this and be coding according to the Single Responsibility Principle.
WeatherDisplay

public class WeatherDisplay
{
private DisplayTemperature _DisplayTemperature;
private DisplayWindSpeed _DisplayWindSpeed;

public WeatherDisplay(int temperature, int windSpeed)
{
_DisplayTemperature = new DisplayTemperature(temperature);
_DisplayWindSpeed = new DisplayWindSpeed(windSpeed);
}

public void DisplayWeather()
{
_DisplayTemperature.Display();
_DisplayWindSpeed.Display();
}
}
}

TemperatureDisplay

public class DisplayTemperature
{
private int _Temperature;

public DisplayTemperature(int temperature)
{
_Temperature = temperature;
}

public void Display()
{
println("The current temperature is: " +
_Temperature + " degrees celcius.");
}
}

WindSpeedDisplay
public class DisplayWindSpeed
{
private int _WindSpeed;

public DisplayWindSpeed(int windSpeed)
{
_WindSpeed = windSpeed;
}

public void Display()
{
println("The current wind speed is: " +
_WindSpeed + " meters per second.");
}
}

In this second example you can see that I now re-factored the class WeatherDisplay into three classes. Weather Display still exists but now it is using the class TemperatureDisplay and WindSpeedDisplay to actually display the data.

 

Case 3 : Better implementation


As I said before you could even say that there were 3 responsibilities for the first example and they would be displaying the information, providing temperature text markup and providing wind speed text markup. So in that case we would probably re-factor our example in the following way:

Interface: ITextDisplay

public interface ITextDisplay  {
void Display(TextWriter writer);
}
DisplayTemperature

public class TemperatureDisplay implements ITextDisplay
{
private int _Temperature;

public TemperatureDisplay(int temperature)
{
_Temperature = temperature;
}

public void Display(TextWriter writer)
{
writer.WriteLine("The current temperature is: " + _Temperature + " degrees celcius.");
}
}

DisplayWindSpeed


public class WindSpeedDisplay implements ITextDisplay
{
private int _WindSpeed;

public WindSpeedDisplay(int windSpeed)
{
_WindSpeed = windSpeed;
}

public void Display(TextWriter writer)
{
writer.WriteLine("The current wind speed is: " + _WindSpeed + " meters per second.");
}
}

As you can see now instead of providing the class WeatherDisplay with a fixed number of parameters we can now provide it with an unlimited amount of ITextDisplay implementations. The class WeatherDisplay is now responsible for providing a proper TextWriter and telling each ITextDisplay implementation to display its information. The ITextDisplay implementations now only have to write its information to the provided writer, and thus also implementing the Liskov Substitution Principle.