Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Flexible Architecture With Interfaces

DZone's Guide to

Flexible Architecture With Interfaces

Learn how to create an architecture that is as flexible as possible by integrating three different cloud storage solutions into your application.

· Integration Zone ·
Free Resource

SnapLogic is the leading self-service enterprise-grade integration platform. Download the 2018 GartnerMagic Quadrant for Enterprise iPaaS or play around on the platform, risk free, for 30 days.

I have blogged a few times about interfaces, and how useful they are for producing good quality maintainable code. Let's look at a problem and the solution I came up with which I am quite proud of.

As previously mentioned, I am in the process of moving images from AWS to Azure blob storage. Now that the actual files themselves have been moved I need to change the code that references them.

Now, I could find all the code that uses the AWS API and replace it with the Azure API but I am not very good at predicting the future, we may stay on Azure for a while, we may move to AWS or Google Cloud, or we may want to go back to files sitting on a server.

Let's try and code a solution that is as flexible as possible. As you have probably guessed I am going to create an interface.

At first I thought about creating an interface called ICloudStorage, however, this isn't flexible enough, as what happens is we go back to sticking files on a server. So, instead, I created IStorage.

I created three classes that implemented IStorage: AWSStorage, AzureStorage, and, mostly for testing at the moment, FileStorage. I then created a class Storage that would call these three classes. Initially, I created it like this:

public class Storage
{
  private IStorage _repo;
  public Storage(IStorage repo)
  {
    _repo = repo;
  }
}

However, this would require I call it like Storage (new  AzureStorage()) and I would need to know everywhere in my code which implementation I want to use. This isn't too bad, as when we change from AWS to Azure we would need to do a find and replace throughout the code and replace all the instances of AWSStorage and make themAzureStorage.

However, we can do better than that.

public class Storage
{
  private IStorage _repo;
  public Storage()
  {
    Type obj = Type.GetType(ConfigurationManager.AppSettings["DefaultStorageRepository"]);
    ConstructorInfo constructor = obj.GetConstructor(new Type[] { });
    _repo = (IStorage)constructor.Invoke(null);
  }
}

This code will read from the web.config, which is the implementation to use, and that will decide which class to call. This means that to change from AWS to Azure we do not need to redeploy any code, all we need to do is change the web.config.

Let's look at the three lines and see if we can understand what is happening.

  • Type.GetType() - Looks straightforward and gets the type from the web.config.
  • obj.GetConstructor() - This gets the constructor for the type we have just found.
  • constructor.Invoke - This then invokes the constructor and it then gets cast to the interface so can be used by the _repo variable.

This is all fairly simple and makes sense, however, it has produced some very flexible code and allows the code to be extended without recompiling.

Let's look at a hypothetical example. We want to add support for Google Cloud Storage. All we need to do is create a class library which implements the IStorage interface, place the compiled binary in the website, and update the web.config to reference it. I haven't tried this hypothetical example so it might be more complex than I think but, in theory, it should work.

I am pretty excited at how flexible this code can be, hopefully, I will use code like this more often now that I understand it.

Download A Buyer's Guide to Application and Data Integration, your one-stop-shop for research, checklists, and explanations for an application and data integration solution.

Topics:
integration ,flexible architecture ,architecture patterns

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}