Saturday, July 12, 2008

Decorator pattern in Action

This time we are going to solve logging problem.
Requirement is as simple as that:
Login story: System should log all informational as well as failure messages into text file.

That sounds way simple, right? Even without using any existing logging framework.

All it takes is just one static class.
public static class Log
{
public static void Write(string message)
{
//code to write in text file
}
}

And the usage looks like
Log.Write(“something weird happen here”);

So far so good.
The solution works so far and meets our requirement.

Next, lets consider following some OOPs. Here is what I got from Head First OOA & D.
• Make sure your software does what client want it to do
• Apply OOP to make it maintainable.
• Re-factor to improve any duplication.

We have already satisfied first bullet line. So let’s proceed to second one.

One of the OOP says “Depend upon abstraction”. But in our solution, we are tightly binding client with static class. So let’s instead use interface and push all the concrete code behind it.

Our new implementation looks like this:
public interface ILogger
{
void Write(string message);
}

public class TextFileLogger : ILogger
{
private readonly ITextFileWritter _textFileWritter;

public TextFileLogger(ITextFileWritter textFileWritter)
{
_textFileWritter = textFileWritter;
}

public void Write(string message)
{
_textFileWritter.Write(message);
}
}

If we look at closely here, rather than writing code for IO into logger class, I have pushed them into their own class. Why????? Remember Single Responsibility Principle? Class should have only one reason to change, right? So our logger should be responsible for logging not for writing to text file. This also gives me good opportunity to unit test my logger. To achieve this goal, I have used one of my favorite Inversion of Control techniques called Dependency Injection [This might sounds like weird but I am favoring this approach because it gives me, unit testing benefits plus we have textFilewritter, which can be used anywhere else too].

Now, at this stage, our solution looks great. It perfectly meets client need as well as follows OOP from the maintainability point of view.

It’s been well said for software: The only constant in software is Change. So what if we have requirement coming up later: need to feed all these log messages to xyz MQ, so that somebody can take corrective action on them.

With our new code it should be that difficult as all we have to do is CHANGE TextFileLogger class. Add one line there, to make call to some class which will write into MQ.

Remember though, key here is our ability to reach at this file and CHANGE code in it. We may not be lucky to get access to source file every single time (This is the case, almost every single time when code that we wrote, is shipped as part of some framework). And again its always risky to change somebody else’s code. Now you have to test not only your new functionality but existing one too and make sure you haven’t broke any thing (Isn’t that very common, breaking existing code while making change. People working on maintenance project, knows this better than me)

Certainly, our solution is failing at this last litmus. We are in trouble again. Need Help!!!
I heard, one of our old friends, whom we never bother to call so far, can help here. So let’s knock her door. By the way, her name Decorator. Here we are at the door

Me: (Knock knock)
Someone from inside: Who is this?
Me: Hey I was looking for Decorator. Is this a right place where I can find her? I seriously need her help.
Door Opens.
Decorator: I am decorator. I am glad that you came here to help. Many programmers ignore me, either because they don’t know me or my power.
Me: What power you are talking about?
Decorator: Ability to add behavior without touching existing code.
Me: Sounds interesting. I am looking for something like that only. Could you elaborate on this.
Decorator: why not, here is what GoF says about me:
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
Me: As always, that was big bumper for me ?
Decorator: Don’t worry. Let me simplify it for you. Remember me, when you have requirement to add extra behavior on top of existing one, without changing original code.
Me: I am with you. Go ahead
Decorator: So when it comes to add behavior, all you have to do is implement existing interface, in your case, ILogger, and keep reference to original one in your new class. So the new class looks like this
public class DecoratedMSMQLogger : ILogger
{
private readonly ILogger _logger;
private readonly IMSMQWritter _msmqWritter;

public DecoratedMSMQLogger(IMSMQWritter textFileWritter, ILogger logger)
{
_msmqWritter = textFileWritter;
_logger = logger;
}

public void Write(string message)
{
_msmqWritter.Write(message);

if (_logger != null)
_logger.Write(message);
}
}
Me: Ok, and now all I am doing is passing each calls to that logger, after I am done with mine
Decorator: Exactly. And by doing this, what you just followed is called, OCP.
Me: you solved my problem. Thank you so much and I promise to visit you again and again
Decorator: my pleasure, bye bye
Me: bye

PS: sample code already uploaded in my google repository.

13 comments:

Paul T said...

Hi Mahendra,

Great article but just noted that your Decorator files are not on the SVN repository on google.

The project file has the links to the Decorator files:

DecoratedLoggers.cs
ILogger.cs
Writter.cs

but they cannot be downloaded.

Cheers,
Paul

Mahendra Mavani said...

@Paul

Thanks for pointing this..
I missed them.. fixed it

You can get it from Repository now

Paul T said...

For completeness, you probably want to checkin the unit tests too!

Thanks,
Paul.

Anonymous said...

Who knows where to download XRumer 5.0 Palladium?
Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!

Anonymous said...

I inclination not concur on it. I think polite post. Expressly the title-deed attracted me to review the whole story.

Anonymous said...

RX symmetrel 50mg zetia Generic xeloda Order trandate Side-effects female viagra Order zestril

Anonymous said...

Good post and this enter helped me alot in my college assignement. Thank you on your information.

Anonymous said...

Do You interesting of [b]Female use of Viagra[/b]? You can find below...
[size=10]>>>[url=http://listita.info/go.php?sid=1][b]Female use of Viagra[/b][/url]<<<[/size]

[URL=http://imgwebsearch.com/30269/link/viagra%2C%20tramadol%2C%20zithromax%2C%20carisoprodol%2C%20buy%20cialis/1_valentine3.html][IMG]http://imgwebsearch.com/30269/img0/viagra%2C%20tramadol%2C%20zithromax%2C%20carisoprodol%2C%20buy%20cialis/1_valentine3.png[/IMG][/URL]
[URL=http://imgwebsearch.com/30269/link/buy%20viagra/3_headsex1.html][IMG]http://imgwebsearch.com/30269/img0/buy%20viagra/3_headsex1.png[/IMG][/URL]
[b]Bonus Policy[/b]
Order 3 or more products and get free Regular Airmail shipping!
Free Regular Airmail shipping for orders starting with $200.00!

Free insurance (guaranteed reshipment if delivery failed) for orders starting with $300.00!
[b]Description[/b]

Generic Viagra (sildenafil citrate; brand names include: Aphrodil / Edegra / Erasmo / Penegra / Revatio / Supra / Zwagra) is an effective treatment for erectile dysfunction regardless of the cause or duration of the problem or the age of the patient.
Sildenafil Citrate is the active ingredient used to treat erectile dysfunction (impotence) in men. It can help men who have erectile dysfunction get and sustain an erection when they are sexually excited.
Generic Viagra is manufactured in accordance with World Health Organization standards and guidelines (WHO-GMP). Also you can find on our sites.
Generic [url=http://viagra.wilantion.ru]Viagra 100mg pills[/url] is made with thorough reverse engineering for the sildenafil citrate molecule - a totally different process of making sildenafil and its reaction. That is why it takes effect in 15 minutes compared to other drugs which take 30-40 minutes to take effect.
[b]viagra doses how many milligrams
natural viagra formulas
Viagra For Pulmonary
Lowest Price Viagra
viagra chemists
viagra delivered within 24 hours
viagra in india
[/b]
Even in the most sexually liberated and self-satisfied of nations, many people still yearn to burn more, to feel ready for bedding no matter what the clock says and to desire their partner of 23 years as much as they did when their love was brand new.
The market is saturated with books on how to revive a flagging libido or spice up monotonous sex, and sex therapists say “lack of desire” is one of the most common complaints they hear from patients, particularly women.

Anonymous said...

Es ist nicht jedermanns Sache, andere auf der Straße oder beim Ausgehen einfach so anzusprechen. Im Internet tappen wir nicht in diese Schuechternheitsfalle: Eine E-Mail an einen Fremden zu schicken ist zwar aufregend und vielleicht der Beginn eines interessanten Kontakts, aber wenn man hier einen Korb bekommt, tut das lange nicht so weh wie im wirklichen Leben.

[url=http://www.time4love.ch] [img]http://c1.ac-images.myspacecdn.com/images02/57/l_82c00371eb494acdb2e1cf51378a28ec.jpg[/img]

elitepartner
er sucht ihn
partnersuche
er sucht sie

[/url]

Anonymous said...

hi every person,

I identified mahendramavani.blogspot.com after previous months and I'm very excited much to commence participating. I are basically lurking for the last month but figured I would be joining and sign up.

I am from Spain so please forgave my speaking english[url=http://behindthescenesbr.info/bookmarks].[/url][url=http://liwhatweknow.info/forum].[/url][url=http://learnnewthingsnd.info/].[/url]

Anonymous said...

Edda hour, a construction circle turned up to start erection a obligation on the mad lot.

The [url=http://poa7.000space.com/yfd.html]567194[/url] 5md8p3vg 597093 [url=http://limaimenapolnostu.edublogs.org/2012/11/28/symbol-of-rome-in-danger-colosseum-okoltsuyut-iron-column/]4un2j4ps[/url] [url=http://daclac.000space.com/isu.html]698295[/url] teeny-bopper end's 5-year-old daughter as a consequence took an attracted next to in all the

oomph in the chips on next door and dog-tired much of each signal of then observing the workers.

Anonymous said...

Edda hour, a construction corpse turned up to start erection a forebears on the unfinished in lot.

The 194399 [url=http://poa7.000space.com/tda.html]328412[/url] [url=http://masuher.blogdetik.com/2012/11/29/end-of-the-world-in-the-russian-city-began-deficit-on-goods-saving-equipment/]8ym3q4zy[/url] 8vp3e7bt 777328 infantile people's 5-year-old daughter in actuality took an bestir in all the

vocation adjacent on next door and dog-tired much of each adulthood observing the workers.

Anonymous said...

Chestnut hour, a construction coterie turned up to start stratagem a forebears on the unfinished in lot.

The 3if1f9rt [url=http://kamachu.000space.com/ksd.html]183845[/url] [url=http://kamachu.000space.com/msu.html]528016[/url] [url=http://poa7.000space.com/tda.html]328412[/url] [url=http://masuher.blogdetik.com/2012/11/29/russia-has-withdrawn-from-the-market-sets-for-doomsday/]4hx2z5ji[/url] offspring relations's 5-year-old daughter in fact took an avail in all the

company active on next door and pooped much of each prime observing the workers.