Twitter Feed: @definition6

DEFINING INSIGHTS

Architectural Diary - Refactoring Minefields

Monday, March 28, 2011 by Jonathan Taylor

Change sucks. I’ve heard the glib rhetoric and seen the shiny happy bumper stickers proclaiming the staunch opposite. They're often paired with an equally shiny sticker of a cat skeleton with a smiley face stuck to the front of it. "Change is good," but apparently not for the cat.

Now, I’ll admit, for some things, change is a genuinely welcome event – underwear, socks, cat litter, and most immediately my empty pint glass come to mind. However, with web application development change sucks! Change means long nights rolling in new code to replace old. Change means endless cycles refactoring someone else’s code, often on shoestring documentation and littered with dependencies you don’t know about until you trip over them. How often have you fixed one bug and 3 more pop up? Poorly written code, like it or not, is a fact of life.

Blame it on too many requirements in not enough time, or whatever you want to, but the sad truth is most developers build what they have to without thought of what it takes to support it once it’s running. If it’s your task to have to go back in and add a new feature or change existing functionality, yeah, change sucks. And the number one culprit in contributing to code sucky-ness is dependency. Updating heavily dependent code is like planting corn in a minefield, you might get a few new stalks in ok, but it’s only a matter of time before something’s going to blow up.

So, how can we, as developers, do eachother right and make sure the code we write won’t blow somebody’s refactoring effort to smithereens? Especially if it might actually be us doing the refactoring? Limit dependency in our own code! Right! Ok, so how exactly do we do go about building projects that aren’t refactoring minefileds? Glad you asked.

The easiest way to reduce dependency between two pieces of code is through a façade. Let’s go with an example. Take a look at the code in Segment 1.

Code Segment 1.

    class Example

    {

        //Default constructor

        public Example()

        {

 

        }   

        //Public method

        public void DoSomething(String thing)

        {

            //process thing

        }

    }

    public class Caller

    {

        String stuff = "stuff that needs to be done";

        Example xmpl = new Example();

        xmpl.DoSomething(stuff);

    }

 

Pretty standard stuff, right? A simple Caller class that instantiates a version of our Example class, then calls the Example class’ DoSomething() method. Pretty standard, you’ve probably written hundreds of similar code sets. But what if we had to update DoSomething()’s code to include some new functionality once it had been pushed into production? We’d have to change both our Example class, our Caller class, and anybody else that was dependent on Example to do something. Total pain.

Now, there are lots of ways we can reduce our caller class dependency in our example class. We could setup a factory to handle the instantiation of the example class, throw in some dependency injection, or heck, even define an interface we could program all our caller classes to [Love interfaces. Love them. Separate declaration from implementation in one easy step. But sadly, it’s another post…JT], but our intent here is relate to you just how easy it is to separate the declaration of our DoSomething() method from its processing through a simple façade, and in so doing significantly reduce the dependency any class implementing our Example class has to deal with. Let’s get to it.

What we’re going to do is use a really easy implementation of the Façade Pattern which Microsoft itself uses extensively throughout its .NET framework – a Non-Virtual Interface (NVI).

Oooo. Aaaahh.

Ok, big name for really simple solution to break dependency between entities. Basically what an NVI is a public method declaration that calls a private internal method to carry out its processing. I know, sounds too easy right? Right! It is! But what it does for us is cleanly separate declaration from implementation.

Oooo. Aaaahh.

Ok, I’ll stop, but this is wicked cool stuff. Check out Segment 2

Code Segment 2

    class Example

    {

        //Default constructor

        public Example()

        {

 

        }   

        //Public method

        public void DoSomething(String something)

        {

            DoSomethingElse(something);

        }

        //Private method to do processing

        public void DoSomethingElse(String somethingElse)

{

            //process something else

}

    }

 

    public class Caller

    {

        String stuff = "stuff that needs to be done";

        Example xmpl = new Example();

        xmpl.DoSomething(stuff);

    }

 

Again, it looks too easy, doesn’t it? In fact, if you don’t stop to think about what this code is doing for us, you’ll miss it, it’s that easy. Say we had to support some new corporate mandate in our DoSomething() method once it had already been released? [We have to log everytime someone does something! Log it! Log it I say!] Well thanks to our tidy NVI, all we have to do is go into our code, and add the new logging functionality to the private DoSomethingElse() method, and we’re done. Done! Our Caller class doesn’t have to be touched because its method call into DoSomething() hasn’t changed!

It’s starting to make sense, right?

So, exposing a public interface which calls a private implementation is the core of what a Façade Pattern is, and a Non-Virtual Interface is a neat trick you can use to keep your own code separated and dependency-Free.

Oooo. Aaaahh.

Sorry, couldn’t resist. Imagine how much easier your refactoring efforts would be if all your existing projects implemented NVIs throughout their codebase? Would certainly reduce the number of senseless refactoring minefield injuries, wouldn’t it? Oh yes it would.

Life might acutally be pretty good. Change would still definitely suck though.

.
blog comments powered by Disqus
 
The Content Marketing Platform Powered by Compendium  |  Sitemap