0

My company has many WCF services which may or may not be replaced in the near future. The old web application is written in WebForms and communicates straight with these services via SOAP and returns DataTables.

Now I am designing a new modern web application in a modern style, an AngularJS client which communicates with an ASP.NET Web API via JSON. The Web API then communicates with the WCF services via SOAP.

In the future I want to let the Web API handle all requests and go straight to the database, but because the business logic implemented in the WCF services is complicated it's going to take some time to rewrite and replace it.

Now to the problem: I'm trying to make it easy in the near future to replace the WCF services with some other data storage, e.g. another endpoint, database or whatever. I also want to make it easy to unit test the business logic.

That's why I have structured the Web API with a repository layer and a service layer. The repository layer has a straight communication with the data storage (WCF service, database, or whatever) and the service layer then uses the repository (Dependency Injection) to get the data. It doesn't care where it gets the data from. Later on I can be in control and structure the data returned from the data storage (DataTable to POCO) and be able to test the logic in the service layer with some mock repository (using Dependency Injection).

Below is some code to explain where I'm going with this. But my question is, does this all make sense? Am I making this overly complicated and could this be simplified in any way possible? Does this simplicity make this too complicated to maintain? My main goal is to make it as easy as possible to switch to another data storage later on, e.g. an ORM and be able to test the logic in the service layer. And because the majority of the business logic is implemented in these WCF services (and they return DataTables), I want to be in control of the data and the structure returned to the client.

Any advice is greatly appreciated.

Update 20/08/14

I created a repository factory, so services would all share repositories. Now it's easy to mock a repository, add it to the factory and create a provider using that factory.

Any advice is much appreciated. I want to know if I'm making things more complicated than they should be.

So it looks like this:

1. Repository Factory

public class RepositoryFactory
{
    private Dictionary<Type, IServiceRepository> repositories;

    public RepositoryFactory()
    {
        this.repositories = new Dictionary<Type, IServiceRepository>();
    }

    public void AddRepository<T>(IServiceRepository repo) where T : class
    {
        if (this.repositories.ContainsKey(typeof(T)))
        {
            this.repositories.Remove(typeof(T));
        }

        this.repositories.Add(typeof(T), repo);
    }

    public dynamic GetRepository<T>()
    {
        if (this.repositories.ContainsKey(typeof(T)))
        {
            return this.repositories[typeof(T)];
        }

        throw new RepositoryNotFoundException("No repository found for " + typeof(T).Name);
    }
}

I'm not very fond of dynamic but I don't know how to retrieve that repository otherwise.

2. Repository and service

// Service repository interface
// All repository interfaces extend this
public interface IServiceRepository
{
}

// Invoice repository interface
// Makes it easy to mock the repository later on
public interface IInvoiceServiceRepository : IServiceRepository
{
    List<Invoice> GetInvoices();
}

// Invoice repository
// Connects to some data storage to retrieve invoices
public class InvoiceServiceRepository : IInvoiceServiceRepository
{
    public List<Invoice> GetInvoices()
    {
        // Get the invoices from somewhere
        // This could be a WCF, a database, or whatever
        using(InvoiceServiceClient proxy = new InvoiceServiceClient())
        {
            return proxy.GetInvoices();
        }
    }
}

// Invoice service
// Service that handles talking to a real or a mock repository
public class InvoiceService
{
    // Repository factory
    RepositoryFactory repoFactory;

    // Default constructor
    // Default connects to the real repository
    public InvoiceService(RepositoryFactory repo)
    {
        repoFactory = repo;
    }

    // Service function that gets all invoices from some repository (mock or real)
    public List<Invoice> GetInvoices()
    {
        // Query the repository
        return repoFactory.GetRepository<IInvoiceServiceRepository>().GetInvoices();
    }
}
  • How is it best to handle communication between services? If Service1 has composite relation with Service2, how do I inject mock repositories for both of them? – Gaui Aug 19 '14 at 16:56
  • I created a RepositoryFactory that I inject into every provider, so they share repositories. – Gaui Aug 20 '14 at 16:00
  • "My main goal is to make it as easy as possible to switch to another data storage later on" - I have to ask the question, just how likely do you think this will be? I don't think I've ever had to change the data storage later on for any system. But if your aim is to separate concerns so that UI doesn't know about DB design then great. – Rocklan Aug 21 '14 at 0:27
  • @LachlanB Well there are many old services that we would like to switch out later on. These are old WCF services that we need to use for now because of a complicated business logic required. Later on we would like to go entirely through the Web API, connect it straight to a database, set up a ORM and use that for easy data access. Move the business logic. That's why I structured it to use the repository layer, so it doesn't matter where the service gets it data, just from some repository / data storage. The goal was also to make it easily mockable and testable. – Gaui Aug 21 '14 at 9:54
1

Since your goal actually IS to make it easy to change out the storage mechanism at a later point I think you are on the right track.

You might also consider actually making a separate model specific to your database and then map the object model back and forth between your domain object and your database objects.

This way you can use annotations and other technology specific attributes on your database objects without polluting the domain object with e.g SQL specific attributes if you are going for a NoSQL solution further down the line.

  • That's a very good point. I had the exactly same in mind, to create a specific model that the service layer works with. This makes it easy to replace specific services for data from a database using ORM or something. But I have never seen the repository pattern used with WCF endpoints, so I was wondering if I was making things more complicated and harder to maintain. – Gaui Aug 17 '14 at 21:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.