Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Refactor to Functions

0.00/5 (No votes)
16 Oct 2014 1  
Get rid of dependencies through the use of Functions

Introduction

Sometimes, I just want to get rid of my own dependencies and rely only on base classes, primarily because I don't have to test them, they are well tested, and secondly they don't change.

Background

The other day I was asked to implement a solution to this problem:

This company has several .dlls that have to be translated from Spanish to other languages, meaning every message that comes up from the code now has to be replaced with some sort of code that allows the operation of translating to other languages.

What I Learned

I learned in the process that I could refactor my code to be less dependent. The code I would like to share is in C# but it could be Java 8 as well.

Story

As I mentioned earlier, the company has several .dlls that have to be translated from Spanish to other languages, meaning every message that comes up from the code, now has to be replaced with some sort of code that permits the operation.

The initial idea was to inject an interface called Translator with the next signature:

interface translator {
    String translate(String code);
}

So far, it seems a correct solution, it is easy to implement and easy to test or even Mock.
But, what about the .dll having an extra dependency on the package or namespace where the translator lives.

I thought about this for a while and I came up with this solution:

First of all, the act of translating is pretty much unique, it has an input code and an output message. As simple as String->String function.

So instead of injecting a translator interface, why don't I inject a function.

Func<String, String>

I had the legacy code:

class DLL_Code {
    public DLL_Code(Dependency1 dep1, Dependency2 dep2) {
        this.dep1 = dep1;
        this.dep2 = dep2;
    }
    private Dependency1 dep1;
    private Dependency2 dep2;
}

Now I have:

class DLL_Code {
    public DLL_Code(Dependency1 dep1, Dependency2 dep2, Func<String, String> translate) {
       this.dep1 = dep1;
       this.dep2 = dep2;
       this.translate = translate;
    }
    private Dependency1 dep1;
    private Dependency2 dep2;
    Func<String, String> translate;
}

This is not only C# compatible but also JDK8 has similar Interface Function<T, R> signature.

I felt good about not adding dependencies of mine but instead, rely on .NET base classes. This is not a big deal, but personally I always prefer relying on base classes rather than depending on user classes. Just my personal preference.

Hours later, I asked myself:

What Design Patterns Could Be Refactored to Functions?

Suppose we have a typical decorator pattern, let's say:

interface Tracer {
    void trace(String info);
}

class NormalTracer : Tracer {
    public NormalTracer(String fileName) {
        this.fileName = fileName;
    }
    public void trace(String info) {
        // Code to trace
    }
    private String fileName;	
}

class BufferedTracer : Tracer {
    public BufferedTracer(Tracer tracer) {
        this.tracer = tracer;
        listOfTraces = new List<String>();
    }
    public void trace(String info) {
        listOfTraces.Add(info);
    }
    public void flush() {
        foreach (String s in listOfTraces) {
            tracer.trace(s);
        }
    }
    private Tracer tracer;
    private List<String> listOfTraces;
}

On the other hand, we have this legacy piece of code that makes use of Tracer.

class LegacyClass {
    public LegacyClass(Tracer tracer) {
        this.tracer = tracer;
    }
    private Tracer tracer;
}

If I want to get rid of the class dependency Tracer which I do, then I would refactor LegacyClass to:

class LegacyClass {
    public LegacyClass(Action<String> tracer) {
        this.tracer = tracer;
    }
    private Action<String> tracer;
}

At first, it does not look like a great leap, but since in every company the code is definitely not homogenous as anyone would like.

Now you can use the refactored LegacyClass with Log4Net, Log4J or the fast buffered tracer without worrying about the isolated class in the .dll.
Now what happened to the other patterns, do they behave equally?

Think of an Observer Pattern

class IsolatedClass {
    public IsolatedClass(Action<IsolatedClass> notify) {
        this.notify = notify;
    }
    public void someProcess() {
        // Some code
        notify(this);
        // Some code
    }
    private Action<IsolatedClass> notify;
}

class Obvserver {
    public void someMethod() {
        new IsolatedClass(z => someOtherMethod(z));
    }
    public void someOtherMethod(IsolatedClass ic) {
        // act in consequence
    }
}

From the testing point of view, the IsolatedClass is easy to test and refactor in the future.

Other Patterns?

Think if I want to convert the above Observer into a Mediator. I don't have to change the signature or dependencies on the IsolatedClass.

So far I don't see any drawbacks, some feedback will be really appreciated.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here