SOA: How to design a service

I find myself in the situation of having to set down a design standard for SOA services.

The thing is: SOA Services are much more than a technical artifact.  They are a solution to a business architecture requirement for shared services, and the business architecture needs to exist first, or at least be tacitly understood and described, in order for the service to have any lasting value.

So, first step in designing a SOA Service is to refer to the business process diagrams that your business architect has produced.  For each interaction between roles, look for the data needed to make decisions.  For example, if you are looking at the process flow for a new purchasing agreement, you may see steps where three different collaborating systems need data.  Consider, for each system, what data they have and what data they need to get, from the flow, in order to do their work.  Consider the timeliness of the connection, the direction of the flow (event-push, or call-pull).    

You are collecting data for your service contract.  Before you write the contract, however, you need to write out the "high level service design."  This design starts with some key design questions that you must answer:

  • What is the responsibility of the service?   This provides the basic description of WHY the service should exist.  Services are expensive.  If you cannot stand in front of an executive and make a purely business-oriented case for the existence of a service, you need to rethink it.  You are doing something wrong.
     
  • What rules does the service own?   This provides the basic scope of the service.  In a well devised, Enterprise SOA, you will have a rule implemented in a relatively small number of services (hopefully in one service) which makes it easier to change that rule.  This means that you need to describe the collection of rules owned by a service.
     
  • What style of EAI are you implementing?   I've written about trusted services in the past, which is part of the "Messaging" style of loosely coupled services.  The alternative is the "RPC (Remote Procedure Call)" style.  If you are passing a block of self-describing and complete data to a service, and all that returns is "thanks... got it," then you are using the messaging style.  If you are passing a command (with or without parameters) and are expecting either a set of data in response or an "OK... operation complete" message back, then you are using the RPC style.  Note that RPC style services are more typical but, IMHO, less powerful because they assume a real-time binding between the interacting systems.  In other words, with an RPC style interaction, if either system is unavailable, then the channel is not useful.  With messaging style, both systems do not have to be running at the same time.  Let me be clear on this point: it matters!  If you are presenting an RPC-style service, you are not achieving the full benefits of loose coupling because of the real-time binding between systems.
     
  • Is the service itempotent?   In other words, if a call to the service is duplicated, and instead of being called once, the service is called twice with identical parameters/payload, will the service detect the duplication and prevent any effects on the underlying systems?  This is very important in messaging style services, but it turns up in RPC services as well.  A service that provides idempotency is more loosely coupled than one that does not, but it also adds to the complexity of the service implementation.
     
  • What preconditions and postconditions apply to this service?   Just as in use case development, you must be able to describe the factors that must be in place for this service to be used.  Unlike typical use case development, however, you must describe the behavior of the service when these preconditions are not met.  You also must describe the limitations and constraints of the service.  For example, if a service is designed to be used only during a specific business process, then this must be described and included in the service design.
     
  •  What actors may use this service and how will they be authenticated?   There are two questions here.  First question: define the actors and/or roles that a calling system may play or represent when calling this service.  This is an optimistic statement, because you (a) may not know, and (b) may not want to limit your implementation.  However, you need to consider all of the actors who can use the business rule that you are encapsulating.  If one of those actors cannot use your service, you need to either find a suitable interaction where that actor can use the rule, or create another service that meets that actors needs (I prefer the former). 

The second question above: "how will your actors be authenticated," must be answered.  Too few people will take this into consideration in service design and that is a huge mistake.  Even within the firewalls of the data center, it is imperative that the communications between systems be understood to be secure from mal-intentioned people.  If your answer is "pray," then you may want to consider a new line of work.

  • What data elements will be required in order to call the service?   Do not define the format of the calling sequence.  Define the semantics of the data element itself.  Is there an Enterprise-wide Unique identifier for the data item you are submitting?  If there is a numeric value, what does it mean?  At what point in a process is it meaningful? 
     
  • What data elements will be returned by the service in its acknowledgement / receipt / return?   Answer the same questions as the preceding question.  Think of these questions as the services "data dictionary" but with more constraints.  Data dictionaries describe data a rest.  These points describe data in process.  It's tougher.
     

OK.  Now it is time to formalize your service contract.  This is the more technically oriented part of the design.  You will define the rules for interacting with the service.  All of the points above were more concerned with the behavioral aspects of the service.  Now you come to the technical aspects.

The data points you need for the service contract are:

  • What message format will the service use?  Typical answers here include SOAP, Proprietary XML, and various RPC mechanisms.
     
  • What protocol will the caller use to communicate with the service? Typical answers here include HTTP and various RPC protocols.
     
  • What level of availability should the caller expect for the service?  Will the service be available 24x7?  Whats the service level agreement that the hosting team is willing to sign up for?
     
  • What is the expected interaction on the part of the caller when the service is not available?  Should he call again later?  Try again right away?  Discard the call?  Return an error to the calling system?
     
  • If the service call is part of an expected sequence of service calls, define the sequence.  This may include call-back mechanisms.  Note that call-back mechanisms require the reflected service to be as well defined as the initial service, using all of the rules described here.
     
  • What latency should the caller expect for the synchronous return from the service call?  (In messaging systems, this is the time that the caller should expect to wait for the acknowledgement or receipt.)

These are the technical aspects of the service.

Once you have defined all of these points, you have the high level design of your service.  You need to publish the service contract and all of the rest of the design elements above in a place where the calling systems (and their programmers / administrators / support teams) can get access to them.

And that's how you design a SOA Service.