tags:

views:

52

answers:

3

I am on a project where I will be creating a Web service that will act as a "facade" to several stand alone systems (via APIs) and databases. The web service will be the sole method that a separate web application will use to communicate with these external resources.

I know for a fact that the communication methodology of one of the APIs that the web service must communicate with will change at some undetermined point in the future.

I expect the web service itself to abstract the details of the change in communication methodology between the Web application and the external API. My main concern is how to design the internals of the web service. What are some prescribed ways of using OO design to create an appropriate level of abstraction such that the change in communication method can be handled cleanly? Is there a recommended design pattern?

+1  A: 

As you described, it sounds like you are already using the facade pattern here. The web service is in fact the facade to the other services. If an API between the web service and one of the external resources changes, the key is to not let this affect the API of the web service itself. Users of the web services should not need to know the internals of how the web service communicates with the external resources.

If the web service has methods doX and doY for example, none of the callers of doX and doY should care what is going on under the hood. So as long as you maintain the API between the clients of the web service and the web service, you should be set.

Jeff Storey
Thanks, Jeff. I definitely intend to use the API of the web service itself to hide the internals of how it communicates with external resources. My concern is how to design the interals of the web service itself, so that I can handle the change when it occurs. I have edited my original question to make it clearer
bpil
@bpil One way of handling this is to be sure that your communication layer between the web service and its external resources is defined in an interface at the highest level possible. For example, sendMessage or sendRequest. There can be various implementations of the interface so the web service is unaware of the communication details. I recommend checking out Patterns of Enterprise Integration http://www.eaipatterns.com/eaipatterns.html
Jeff Storey
A: 

I've frequently faced a similar problem, where I would have a new facade (typically a Java class), and then some new "middleware" that would eventually communicate to services located somewhere else.

I would have to support multiple mediums of communication, including in-process, and via the net (often with encryption).

My usual solution is define a notion of a data packet, with its subtypes containing specific forms of data (e.g., specific responses, specific requests), etc. The important thing is that all the packets must be Serializable in some form (Java has a notion for this, I'm not sure about C++).

I then have an agent and a provider. The agent takes program-domain requests, creates packats. It moves them to a stub-skeleton that is responsible only for communicating. The remote stub takes the packet and gives it to a provider. The provider translates it back to a domain object which it then provides to the actual services. It takes the response, sends it back to the agent via the skeleton-stub, etc.

The advantage of this approach is that I create several layers of abstraction. The agent/provider are focused on domain level and its translation into packets and back. The skeleton-stub pair is responsible for marhsalling and sending packets back and forth. By swapping my skeleton-stub pair with subtypes, I can have the same program communicate in different ways (e.g., embedded in the same JVM, via something like JMS, directly via sockets, etc.)

Uri
Uri, help me understand. I get that the Agent translates from program-domain to packet and the Provider translates from packet to [external API]-domain. I am unclear on the skeleton-stub pair. Is this just a serializable data container class?
bpil
Imagine that you have a packet on one machine and a packet on another machine. Your goal is to transmit the packet from one to another. The skeleton and stub take a packet and are responsible to somehow communicate it to one another. You could think of various implementations of this pair (e.g., via sockets, via a messaging framework, via disk files, etc.)
Uri
The purpose of separating the skeleton/stub from the agent/provider is to abstract the means of communications. The agent/provider work against a skeleton/stub interface, but the actual dynamic types of the skeleton and stub are responsible for the communication.
Uri
A: 

This shouldn't affect the service you create at all (from the user's perspective). Services are about contracts - your service will provide a contract with its users - they send you a specific request and you send back a specific response. You also have a contract with this other API. If they change how they want to communicate, you can handle that internally, but as long as your contract with your users does not change they wont notice a thing.

One way to accomplish this is to not simply pass through the exact object that you get from the "real" API. You can create your own object that you send back in response. You then translate their object into your object. That way if the "real" API changes things on their end you can choose how to send that back on your end.

As the middle man you should be set up so that your end users need to know nothing about the originating API.

Ryan Elkins