Sunday, August 09, 2009

 
Let us look into a pattern which will help us learn how to decorate our classes at runtime using a form of object composition. Yes, we will talk about Decorator Pattern today. It is influenced by the design principle which says "Classes should be open for extension, but closed for modification." That is, by applying this pattern our classes need not be modified for extension. Let us now jump into a real time example.

Let us say we got an offer to develop an object oriented system for a fastfood chain. The system has to calculate the price for each order that is placed at the counter. This system will be installed on the macros placed at the counter.
This may sound simple, but the issue is there are N number of combination for an order. For analyzing this requirement further let us track few of the orders to understand the combination.

Order No. 1: One Turkey Breast + without cheese + with dark chocolate toppings.
Order No. 2: One Oven Roasted Chicken Breast + with extra cheese + dark chocolate topping.
Order No. 3: One Black Forest Ham + with extra cheese + fruit cream topping.

If we see orders above, you would see that each order is different and each person could choose any one ham and any combination of toppings out of given list of toppings. The good thing is that we have a list of hams and a list of toppings.

Now can you think of an object oriented design to solve this?

Well, let us try solving this with our conventional inheritance patterns.

Solution 1: We could create one abstarct class named Burger with an abstract method named Price() and specific classes dedicated to various combination of orders possible. Each such order implementing its Price() method to calculate the price for the order. But, as you might have already realized it is not a clean solution. It has too many disadvantages like it leads to class explosion, next, each time a new ham or topping is added to the menu it leads to changing the combinations, which leads to rewriting code and biggest disadvantage is that when ever a price change for any one items, all methods will have to undergo modifications. Well, in all a bad design.

Solution 2: We continue to have this abstract class Burger with properties to identify toppings like extra cheese, chocolate topping etc. That is, attribute could be bIsCheese, bIsChocolate. And setter methods to set properties to identify the toppings. The Price method now is no more abstract. The Price method of Burger class calculates price based on properties set. And the concrete classes like TurkeyBreast or OvenRoastedChickenBreast overrides the Price() method of parent class (Burger). The Price() method calls parent Price to get the Price for toppings and then adds its specific Price for the Ham.
Again not a clean solution.
OK, now we are sure that such solutions, using inheritance is not a feasible solution. Let us try now applying object combination.

Solution 3: Applying Decorator Pattern:

Let us apply decorator pattern which allow building order with combination of various items at run time. Let us see what is decorator pattern first.
The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub classing for extending functionality.

Now let us apply this to our problem. To do this we will define an interface named Burger. This will be implemented by TurkeyBreastHam, OvenRoastedChickenBreastHam and BlackForestHam. The Price() method of each of these classes will return the Price of its own. This interface Burger, is also implemented by abstract class, which will be responsible for applying decoration to our class. This class is named ToppingsDecorator. It has an abstract method named Price(). The reason behind its implementing the interface Burger is to apply same type as that of the objects to be decorated. The decorator should of same type as that of the object being decorated.

Now each of out Toppings viz., DarkChocolate, Cheese and FruitCream will inherit the abstract class ToppingsDecorator. It has an reference to Burger as an attribute, which gets initialized by its constructor.

Let us see the class diagram:



The Price() method will have following definition:

return 0.30 + objBurger.Price();

i.e., it returns the addition of its own price and add Price of the Burger it decorates.

The complete class definition for some of the classes are as follows:

public class TurkeyBreastHam implements Burger
{
public double Price()
{
return 0.99;
}
}

public abstract class ToppingsDecorator implements Burger
{
public abstract double Price();
}

public class DarkChocolate extends ToppingsDecorator
{
Burger objBurger;

public DarkChocolate(Burger objBurg)
{
objBurger = objBurg;
}

public double Price()
{
return 0.30 + objBurger.Price();
}
}

Let us see one of the implementation to understand it better

public class FastFoodSystems
{
public static void main(String args[])
{
Burger objBurger = new TurkeyBreastHam(); //order a TurkeyBreastHam
objBurger = new Cheese(objBurger); // on this order a Cheese toppings
objBurger = new DarkChocolate(objBurger); /// and then a DarkChocolate Topping
System.out.println("The Total Price for the order is " + objBurger.Price()); //the price of order TurkeyBreastHam + Cheese + Dark Chocolate
}
}

So, this is our solution. It is clean and a scalable solution. We need not modify the class to add new items in menu, we simply add new classes.

That's all for the day. Do let me know what you feel about it.

Bye for now....

Labels: , ,


Sunday, March 15, 2009

 
Coupling & Architecture:

We all have read about tight and loose coupling. We all are aware that there exists two major type of couplings but, how many times did we try to depict and use the concept of loose coupling in our architecture? I am sure we are more driven towards tight coupling atleast practically. The reasons are:
1. Tight coupling is obvious option when scope of software application is small.
2. When development is required at rapid pace.
3. When debugging needs to be made easy for atleast new team members.

But, when this small application tries to add features and when complexity increases, we are often struck with evil called tight coupling. The reason?
The reason is straight forward. Each change in one component calls for changes in almost all other components, due to inter-dependency factor, known to us as tight coupling. It is because, each of our interacting components known more that what it needs, about the other component and hence, maintains some form of data or functionality dependency about the other component, with which it is interacting. This dependency obstructs our maintenance and feature building within our present architecture. And the intensity of evil increases when we add more new developers to the team. All new developers added, are hardly aware of already present complexity and their main aim is to some how manage, and get the feature working. This further accelerates the already complex situation.

When such situation arises, we are often seen compromising with many critical factors like: a) Optimization b) Resource utilization etc etc.

Then what is the way out?

The only way out is, while architecting a system always try to design a loosely coupled system. I agree, often during the initial phases, it will feel like a burden, from both architect and developers perspective. But, as an architect our aim is to NOT only think of present, but also of future. In most of the cases, we see that all system/application grows with time and hence desiging a loosly coupled system will always pay in long term.

But what exactly is loosely coupled design?

A loosely coupled design is one, where components does not bear complex assumptions while interacting with each other. For example, if we have two components say, a web-service and a scheduler, where web-service feeds the scheduler with some kind of data. In such scenario, the scheduler should not expect a particular order of data ie, assumption like, the first node will always hold the Primary ID and next node will holds the API name etc. Rather, it would be a wise choice to expect that where ever a Primary ID key is encountered, it is assumed to be holding Primary ID and so on. In such case, within the web service even if I change the order of my data, Scheduler need not change. Another good example could be in a web-application scenario, where, even if I change a database field my inteface component need not change. It is because, while designing the system I decided to create a component called Model. Which is positioned between Interface and my database layer, which takes care of data and always sends data in the same manner, irrespective of database structure, to the consumer component, which is interface in this case. So, we are no more concerned about the changes in one component effecting the other. So our initial effort pays later.

Please let me know, if you have some other view on this, and any feedback that you might have for me.

Labels: , ,


This page is powered by Blogger. Isn't yours?