Say you have a set of services that your application (the server side) exposes. These could be categorized by feature:

  • Account Service – contains methods for Creation, Deletion, Updating of Account Info
  • Security Service – contains methods for authenticating users, controlling access to objects etc.
  • Other Services….

In addition to having these ‘by feature’ services, your services also support multiple platforms (e.g. multiple devices (mobile versus desktop), multiple database platforms (oracle versus sqlserver)). For this article, we will assume that you are trying to support multiple devices – and are interested in a mobile version of each service as well as a desktop version of each service.

So – here is our problem statement. We need to accommodate:

  • Feature based variation (example Account Service, Security Service…)
  • Platform based variation (example Mobile service, Desktop Service…)
  • Possible Common Functionality between different platforms – Chances are, a good chunk of your service methods will be doing the same thing for each of the different platforms –and only doing a little bit of platform specific stuff.

Overview of Solution (full solution download available at the end)

We will use an interface based approach to model the various feature based services (since each feature based service is completely unrelated to the other) – and inheritance to model the platform specific services (since these share some amount of common code).

services_architecture_object_model

Client Code

It is always instructive to start with the Client Code. What the client has to do relates directly to how the service code is structured. The client needs to have:

a) Easy access multiple feature based services (Account, Security…).  All the client should need to say is GetService() – and it should have the correct service. A simple Service Factory can be used to accomplish this.

b) Easy access to specific platform based services.

Here is all a client should have to do:

class Client
   {
       static void Main(string[] args)
       {
           ServiceFactory.MobileServiceFactory mobileFactory = new ServiceFactory.MobileServiceFactory();
           IAccountService acctService = mobileFactory.GetService<IAccountService>();

           acctService.CreateAccount();
       }
   }

Feature Based Variation

We simply capture the set of feature based services in their own interface – IAccountService, ISecurityService…  For the client to get a handle to any of these services, we will use a simple ServiceFactory. All the client will need to do is say GetService()  – and it should be able to get the desired service back.

Platform Based Variation (with common functionality across platforms)

We use a combination of interface implementation and inheritance. We define an abstract base class which implements the feature specific interface. This base class will contain the common functionality (in the form of virtual methods). The child classes will contain the platform specific functionality. The common functionality may be spread out over different parts (see the example below) – where we have common code at the start of a method – and common code again toward the end of the method (or elsewhere). To account for this, we use a Template pattern as shown below.

Common Functionality

Problem: Common Code – Spread out over the method

public void CreateAccount()
{
      //  common code – e.g. initialization

      // Platform specific code – e.g. calculate resolution of UI
      // common code again – e.g. cleanup
}

Solution: Template Pattern to the rescue

This pattern simply defines a template method that contains all the spread out common code – and a method call to the Platform specific code. The Platform specific code is moved out to its own method.

public virtual void CreateAccount()
{

           //  common code - example - Initialize
           Console.WriteLine("Account Service: Common Initialize Code");

           // Platform specific code
           SomePlatformSpecificOperation(); // example - calculate resolution of UI

           // common code again - example - cleanup()...
           Console.WriteLine("Account Service: Common Cleanup Code");

 }
protected virtual void SomePlatformSpecificOperation()
{
   Console.WriteLine("Base: Platform specific operation");
}

Summary

To deal with the multiple features we followed an interface based approach – where each service exposed its own interface. Then, to account for the different platform implementations of each service, we defined an abstract class which implements the feature interface to start out. The particular platform specific code is defined in child classes which inherit from this base abstract class.  This proves to be an elegant solution for a common, real-world problem in Object Oriented projects. There are a multitude of possible applications of the above architecture. Almost every app today follows a service oriented architecture which exposes multiple services. If our app was limited to just that, the above interface based approach coupled with our Service Factory (to return a specific service) would be all that is needed. However, today’s services are not just feature based – but also tend to support multiple platforms.  These multiple platforms could be multiple databases (e.g. SQLServer and Oracle on the backend), multiple devices (e.g. Desktop and Mobile), multiple OSes  etc. 

NOTE: If your service needs to work against multiple database platforms on the backend (e.g. SQLServer and Oracle), ideally, you would want to design a Data Access Layer that was agnostic of the underlying database. This layer would generate all your SQL statements (CRUD) without caring about what the underlying database platform was. Such a database agnostic data access layer is described in an earlier post here.

Anuj holds professional certifications in Google Cloud, AWS as well as certifications in Docker and App Performance Tools such as New Relic. He specializes in Cloud Security, Data Encryption and Container Technologies.

Initial Consultation

Anuj Varma – who has written posts on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.