Click here to Skip to main content
15,512,053 members
Articles / Programming Languages / C#
Technical Blog
Posted 30 Aug 2010

Tagged as

Stats

20.9K views
20 bookmarked

Getting rid of procedural code

Rate me:
Please Sign up or sign in to vote.
4.79/5 (14 votes)
30 Aug 2010CPOL2 min read
This post talks about how you can replace your conditional statements with inheritance to allow improved extensibility of your application's behaviour.

I came across a piece of code similar to the following this week:

C#
if(cmdLine[0] == "-option1")
{
    // load some objects from XML
}
else if(cmdLine[0] == "-option2")
{
    // load some objects from database
}
...
if(cmdLine[0] == "-option1")
{
    // lots of code to save to xml here
    // manipulating the DOM directly
}
else if(cmdLine[0] == "-option2")
{
    // code to save to database here
}
...

The idea behind this is that the application was supposed to keep backwards compatibility with another system that used XML files to pass data back and forth and also support a newer version of that system, that uses special database tables to do that.

So what’s wrong with it? Well, not taking repetition of similar blocks (this if statement occurs many many times in the code) into account and even closing one eye at the need to refactor this code into smaller methods, there’s still one bad thing left.

This code is procedural.

Adding New Requirements

You can see that the code above switches methods of receiving and transferring data to another system, depending on command line parameters used. What if later we get a new requirement to use flat files for storing the data, by keeping the backwards compatibility? And then later, we’ll need to support sending data through web service. And later… I hope you see the point.

With the method shown above, every new way of data transferring will require a new “else if(…)” branch with more code inside. Thus, we have to change the code and risk breaking it with every new requirement.

How to Refactor this Code?

No, using case statement won’t make it any better. That’s just syntactic change. The answer here is inheritance. Yes, that means we’ll create a couple of new classes (that’s how we solve problems in object-oriented languages, isn’t it?).

Let’s start by defining what the code should do. It should provide a means to load and save objects as part of the integration process. We already know that there are different kinds of implementations needed – XML and database based – so we can use Strategy Pattern here. Let’s see what the interface of these classes looks like in our case:

C#
public interface IIntegrationStrategy
{
    object LoadObject();
    void SaveObject(object someObject);
}

That’s the interface that we’ll program against. The code using it will have no idea what persistence medium the implementation is using. The first example in this post would then be rewritten like this:

C#
...
object someObject = integrationStrategy.LoadObject();
...
integrationStrategy.SaveObject(someObject);
...

It’s that simple! There’s no conditional logic – it is moved into a factory that decides what implementation of IIntegrationStrategy to create for application’s needs:

C#
public class IntegrationStrategyFactory
{
    public IIntegrationStrategy CreateByCommandLineParameter(string parameter)
    {
        if(parameter == "-option1")
            return new XmlIntegrationStrategy();  // XML-based implementation
        else if(parameter == "-option2")
            return new DatabaseIntegrationStrategy();  // database based implementation
 
        // if parameter is not recognized, return a stub object that does nothing
	// - implementation of Null Object pattern
        return new NullIntegrationStrategy();
    }
} 

At some point in our application (in the Main method, for example), we’ll have code like this:

C#
IIntegrationStrategy integrationStrategy = 
	new IntegrationStrategyFactory().CreateByCommandLineParameter(cmdLine[0]);
MainForm form = new MainForm(integrationStrategy);  // the integration service 
				// is injected into the form's constructor

Now, whenever we need to add a new integration strategy, we implement the interface and change code at one place only – the factory. The code that used the interface remains untouched and works fine. This is the point of the Open/Closed Principle – we extend the behavior of our application without modifying the existing code.

This article was originally posted at http://thedevs.com/2010/08/getting-rid-of-procedural-code

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Lithuania Lithuania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSuggestion Pin
Rui Jarimba18-Mar-12 15:55
professionalRui Jarimba18-Mar-12 15:55 
GeneralMy vote of 4 Pin
Abinash Bishoyi25-Nov-11 3:32
Abinash Bishoyi25-Nov-11 3:32 
GeneralExcellent Pin
KeithAMS16-Sep-10 1:38
KeithAMS16-Sep-10 1:38 
GeneralNothing wrong with procedural code Pin
Leslie Satenstein9-Sep-10 17:14
Leslie Satenstein9-Sep-10 17:14 
GeneralRe: Nothing wrong with procedural code Pin
Gediminas Geigalas9-Sep-10 21:07
Gediminas Geigalas9-Sep-10 21:07 
GeneralMy vote of 4 Pin
dmjm-h7-Sep-10 6:37
dmjm-h7-Sep-10 6:37 
GeneralMy vote of 5 Pin
kschulz7-Sep-10 5:05
kschulz7-Sep-10 5:05 
QuestionMore of the same? Pin
baruchl6-Sep-10 22:06
baruchl6-Sep-10 22:06 
Hi Gecka,
thanks for the good example. The code is undoubtly more elegant and in a more OO fashion. However, the problem somewhat remains the same - you just moved it to the factory class. if you have a new option then you need to add an additional if.

You may take your approach further, by having some mapping between the parameter and the class of the desired startegy, say in config file or DB (to avoid need to recompile each time you have new option) and using dynamic type loading in te factory method to return the required type. This will make your code more robust and you will never need to compile again this code whenever there is a new option.
Busi

AnswerRe: More of the same? Pin
Gediminas Geigalas7-Sep-10 1:03
Gediminas Geigalas7-Sep-10 1:03 
GeneralVery good example Pin
Rethmeier6-Sep-10 21:26
Rethmeier6-Sep-10 21:26 
GeneralMy vote of 5 Pin
Rethmeier6-Sep-10 21:21
Rethmeier6-Sep-10 21:21 
GeneralSame here... just formatting needed... Pin
Sandeep Mewara29-Aug-10 0:45
mveSandeep Mewara29-Aug-10 0:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.