Programming code abstract screen of software developer.

Decoupling Code

One thing you realise the more you write code is that the less “moving parts” you have the better or to put it another way the more you put your moving parts into one contained place the better. Pushing items which change or where there will be change in the future to places you can manage is really useful.

Interfaces help a lot here and if you can talk interfaces and just pass the implementation of what you want to do to specific areas, you code is more maintainable.

The following is a brief tutorial in pushing the return of a string depending upon a value in a settings file. This way you can change certain aspects of your code base from a simple text switch.

The Problem

We would like to return a SQL String but the content will vary depending on which area in the UK you are from (England, Scotland or Wales).

We want to push the logic for this into a separate core assembly which manages all the business.

 

Architectural Overview - New Page (2)

Step 1 – Define your Interfaces

In this case we want the application to know that we want to return a string which will contain a SQLQuery but we are not worried about what the content will be until it’s implementation at runtime. Interfaces define the core of the app and are visible by everything

namespace Intermediary
{
 public interface ISqlQueryable
 {
 String ReturnSqlQuery();
 }
}

Step 2 – Create your logic

Next we describe the implementation of Interfaces by inheriting them in the classes where we want to do the work in this case it will be English, Scottish or Wales specific query strings.

namespace Logic
{
    public class SqlEngland : ISqlQueryable
    {
        public string ReturnSqlQuery()
        {
            return "This is the query for England";
        }
    }
}

Example of the English Class which implements the query above.

Step 3 – Create your Service Layer

The service layer will contain 2 components and abstracts out connection between the Main Application and the Business. This useful in that in the future we can change Layers but because the interfaces stay the same, we won’t break much by doing so.

1. Where we resolve our dependency.
This is where we plumb in exactly which class in the logic layer we wish to instantiate. In this case we take text from the settings file which will either say “England”, “Scotland” or “Wales” and from this inform the complier which object, which implements the Interface, we need for this run.

namespace DecouplingCode.DependencyResolutions
{
    public class SqlQueryReturn
    {
        ISqlQueryable _theQuery;

        public ISqlQueryable ResolveDependency(String location)
        {
            switch (location)
            {
                case "England":
                    _theQuery = new SqlEngland();
                    break;
                case "Scotland":
                    _theQuery = new SqlScotland();
                    break;
                case "Wales":
                    _theQuery = new SqlWales();
                    break;
                default:
                    _theQuery = new SqlEngland();
                    break;
            }
            return _theQuery;
        }
    }
}

2. We use dependency injection to pass the ISqlQueryable Object to return the String.

namespace Services
{
    public class SqlQueryService
    {
        private readonly ISqlQueryable _retrieveSqlQuery;

        public SqlQueryService(ISqlQueryable QueryToReturn)
        {
            _retrieveSqlQuery = QueryToReturn;
        }

        public String ReturnSqlQuey() //same signature as Interface
        {
            return _retrieveSqlQuery.ReturnSqlQuery();
        }
        
 
    }
}

Step 4 – Plumbing it together in the Main.

For this console app, we first have to get the object we need which will implement the Interface. We then pass this Interface to the service to return the string we require.

namespace DecouplingCode
{
    class Program
    {
        static void Main(string[] args)
        {
            var dependency = new DependencyResolutions.SqlQueryReturn().ResolveDependency(Settings.Default.Location);
            string SQLQuery = new SqlQueryService(dependency).ReturnSqlQuey();
            Console.WriteLine(SQLQuery);
            Console.ReadLine();
        }
    }
}

You can find this example on my git repo
https://github.com/RazaToosy/DecouplingCode

Hope this will help loosen up your code up. Having this here helps me too as seeing patients take up  a lot of my time and I always need a reference to jog my memory of what I know now but frequently forget!

2 thoughts on “Decoupling Code”

  1. Hello! I love interfaces but love abstract classes too for different reasons. Obviously there have similarities and of course an abstract class can contain implementation for derived classes. However, and it’s often not stated explicitly, but interfaces (IMO) should be about behavioural abstraction not the structural. e.g. IClickable or INotifiable. You shouldn’t create an interface called IPerson. Why? Having a class called, say, Electrician marked by the interface IPerson doesn’t give you very much because there isn’t really any implementation to abstract out, assuming IPerson defined structural elements. It’s quite inflexible. You could have used an abstract class and that would follow OO quite well in that the electrician is a type of person. A good rule of thumb is to consider if the suffix “able” can be applied to the object. If not, you might be misapplying the interface. Interfaces are all about what we can do with the object and giving the consumer-developer the freedom to determine the appropriate course of action under the adherence of the contract.

Comments are closed.