Saturday, February 21, 2015

Service-Oriented Architecture (SOA) : 9 Principles of Service Design

Introduction

Service-Oriented Architecture (SOA) is a specific design approach to building a system based on recognizably different pieces of software providing application functionality as services to other applications and/or services via standard Protocols 1.

The Open Group's definition of SOA:
Service-Oriented Architecture is an architectural style that supports service-orientation. Service-orientation is a way of thinking in terms of services and service-based software development and the outcomes of services.
A service:

  • Is a logical representation of a repeatable business activity that has a specified outcome (e.g., check customer credit, provide weather data, consolidate drilling reports)
  • Is self-contained.
  • May be composed of other services
  • Is a “black box” to consumers of the service.
From the definitions above, it should be clear that SOA is primarily about services.

So, what is a service?
Within a SOA environment,  a service is a piece of software that provides some useful functionality to clients. A service is comprised of a set of well-defined elements, namely: contract, interface, and implementation.

  • The contract element specifies what clients can expect from a service based upon their anticipated needs, and what a service provider needs to offer. 
  • The interface element defines how clients can make use of the service. 
  • The implementation element is the actual realization of the service. 
  • Typically, the contract and interface elements are visible to the outside world, but the implementation is more a black box to clients.

The service must be well design around these three elements (contract, interface and implementation) to make it clear for all clients to ascertain: what value the service offers, how much it costs to use the service and most importantly how to use the service.

In this article I outline some general steps/actions in designing services and then take a look at nine key principles of service design in a SOA environment.

Steps in Designing Services

Below are the main steps/actions in designing services in SOA.
  1. Define the functionality/capabilities that the service offers
  2. Design the service  interface
    1. Design the operations and the functionality the operations offer.
    2. Design the parameters of the operations.
    3. Design the return value or the effect of the operation.
    4. Design test cases for the operations.
  3. Design the service contract 
    1. Define who is allowed to use the service and who can use what operation.
    2. Decide how often the service is available.
    3. Define the load the service should be able to handle.
    4. Define other relevant quality of service attributes.
  4. Design the service implementation
    1. Decide what tool, language or framework to use for the implementation.
    2. Design the components needed for the implementation.
    3. Decide what tools to use to test the implementation.
While executing these steps/actions, there are  several basic service design principles that should be adhered to and followed. These principles are covered in the next section.

Principles of Service Design

Service design principles indicate what attributes a service should have in order to be a usable building block in the SOA environment. Services that are poorly designed or implemented, in the overall architecture, will be of little value for the client. Utilizing solid service design principles will help to create a service that is useful, reusable, and help service client to judge if the services are well designed.

The following sections lists nine service design principles that should be considered when designing/creating services.  The importance of each principle depends on the nature and need of the enterprise creating the service. These principles covers both technical and non-technical aspects of service design. Now lets look into these nine principles:

1. Provide value

  • A service should provide value
  • For every service, consider if and why it is needed. 
  • If a service doesn't provide value to someone or something - organization's clients, internal departments, other IT systems, and so on -  then it is probably not a good service, or only part of a service and not a service by itself.

2. Meaningful

  • A service should be meaningful
  • It should be easy for (future) clients to use a service. 
  • The service interface needs to be meaningful to the clients and not too abstract or complex.
  • If a service is not meaningful, the required effort to consume a service will increase.
  • If a service is not meaningful clients will not be able or are reluctant to use such services since they don't understand them or it is too expensive or difficult to use and integrate them into their applications or services.

3. Implementation hiding

  • A service should hide its implementation. 
  • Clients don't care about the actual implementation behind the service; this should be a black box for them. 
  • Clients focus on the contract and interface of a service to decide whether to use it and to be able to actually consume it. 
  • A service and its interface and contract, should be self-describing and understandable.
  • Hiding the service implementation details is crucial in a SOA environment in which there are differentiation between contract, interface, and implementation. 
  • The service interface should abstract away or hide the specifics of the underlying technologies and systems that do the actual work. 
  • Implementation hiding makes it easier to change, upgrade, or swap the implementation without breaking interoperability since the interface can stay the same. 
  • Implementation hiding doesn't burden clients with the need to know about the specifics of the implementation in order to utilize the service.

4. Trust

  • A service needs to provides a high level of trust i.e. confidence in the reliability of the service.
  • Clients need to have confidence in the service they consume. 
  • Clients want services to be accurate. 
  • Services should do what they are supposed to do, especially in a SOA environment where services can be outside your own span-of-control in case of external services. 
  • Important factors in trust are applying sufficient security, fault-prevention and handling, and auditing capabilities to the services to increase trust.
  • Security of the Service
    • Apply message-level security like signing and encryption of messages to provide end-to-end security from the client to provider when passing sensitive data. 
    • Explicitly state security in the service contracts so providers and clients know and agree on the level of security that is provided.
    • Security is part of the way that services are accessed and provided and so it is part of the service interface. For example, if a service is accessed over SSL/TLS, it needs to be defined if the service input and service output require signing. 
    • The security of a service should be based on recognized standards especially when interoperability is a requirement.
  • Fault Prevention and Fault Handling of the Service  
    • Faults can be seen as situations in which the outcome or effect of a service invocation is different than the 'happy path flow'. 
    • Fault handling and prevention should be implemented at the level of services and operations, as is the case for security.
    • Services need to deal with the different types of faults differently. The types of faults are:
      • Business faults: Expected faults that have meaning to the clients: a failure to meet a particular business requirement.
      • Faulty user input: Faults in the input of service operations so operations are unable to execute correctly or have an undesired outcome.
      • Technical and software faults: Unexpected and undesired failures that cannot be easily recovered from by clients such as a network failures, software programming errors, and corrupt disks.

5. Idempotent

  • Service operations should be Idempotent
  • An idempotent operation is one that has no additional effect if it is called more than once with the same input parameters.
  • A service should be predictable; invoking a service operation with the same input more than once should result in the same outcome.
  • Idempotency can be broken when service clients are dependent on a particular instance of a service with or without knowing this dependency. This is mostly the case for services that are stateful, meaning a service instance maintains state (data) that is specific to a particular client.
  • Services should either be stateless or the state should be accessed and persist in a shared datastore, so it is accessible and the same for all instances of a service to guarantee idempotency.

6. Isolation

  • A service should strive for isolation.
  • Isolation means that an operation that is invoked by a client does not rely on the same client to have to invoked other operations prior or after its own invocation to deliver the promised functionality. 
  • Services only provide flexibility and can only be easily changed if their operations are independent of other operations within the same or another service; this is called isolation
  • If a change to an operation results in changes to several other operations that are tightly coupled to the original changed operation, then the service is not flexible. 
  • Service operations need to be separate building blocks that provide capabilities within  themselves.
  • It is very important from a client perspective that operations of services are self-sufficient. 
  • This principle is also known as "loose-coupling" or "decoupling", as opposed to operations that are tightly coupled to other operations, either in the same service or another service.
  • Clients want to invoke only one operation to achieve what is agreed upon in the service contract for that operation, they don't want to be burdened with the task of invoking other operations to make the actual operation function properly.

7. Interoperable

  • Services should be interoperable
  • Interoperability is a measure for the amount of effort it takes to use and invoke services.
  • Services should be easy to integrate into the overall SOA landscape.  
  • Interoperability is achieved by using standards for describing, providing, and accessing services such as JSON, XML, WS-*, WADL, and WSDL. 
  • The use of standards increases the ease of consuming services since most platforms and vendors adhere to such standards. 
  • Only the service interface needs to be interoperable; the implementation itself can be proprietary. 
  • Interoperability is less of a concern when SOA is applied within your own organization consisting of a homogeneous environment in which you have standardized on one or a few platforms and open-source technologies.

8. Granularity

  • A service granularity should to be carefully considered.
  • Service Granularity is a design principle that identifies the optimal scope of business functionality in a service operation.2
  • Services are of different importance based on the degree of value or functionality they add. 
  • Differentiate vertically, based on functionality, providing a limited and independent set of capabilities exposed by operations that belong together.
  • Divide functionality in externally visible portions vertically before thinking how services are internally implemented in horizontal layers. 
  • Service granularity should also be reflected in the release management process that is responsible for promoting IT assets through development, QA/Test, and production environments. 
    • The granularity of releases in a SOA environment is based on the services that are release vertically, per services, instead of big horizontal releases that impact several services at once. 
    • Release per service makes release management easier since the impact of a release is small (has little impact on other systems and services). 
    • Release per service makes sure the focus is on releasing functional building blocks that are useful to clients instead of releasing based on technology (for example a complete horizontal layer) with less value and meaning to clients.
  • How granular should a service and its operations be? A service should be:
    • Big enough to provide value on its own. For example: a setProfile operation maybe too small since it provides no value in itself.
    • Small enough to be able to change, without changing the whole IT landscape in the department or organization. For example: Putting all ERP-related functionality in one big monolithic service with thousands of operations that are used by almost everyone is too big, since every change in ERP-related functionality requires a change in this one service.
  • Granularity should be derived from functionality. 
    • Functionalities that are unrelated should not be mix into a single service and 
    • Functionalities that belongs together should not be put into different services.
  • Granularity should go hand-in-hand with transaction boundaries. 
    • An operation defines a transactional unit. 
    • All activities as part of an operation are either successfully executed and committed together or
    • All activities as part of the operation are rolled back, in case an operation fails.

9. Reusability

  • A service should strive for Reusability, but not over-Generification 
  • Reusability means a service is used by more than one client or is meant to be used by more than one client in the future. 
  • A service may be designed with reuse in mind, but has not yet been used by more than one client.
  • The client of a service is the actual application, process, organizational unit, customer, or organization that uses a service. 
  • Typically, the more a service is reused the less flexible it often becomes. An increase in the number of clients results in more wishes and requirements that need to be agreed upon by all stakeholders. Therefore, there is additional need to analyze whether changes to the service to meet requirements for one client, impact other clients.
  • Often the more added value a service delivers, the more specific it is and the less reusable it becomes, and vice versa. 
    • Business services tend to add a lot of value, and are not very reusable, 
    • Elementary services are very reusable but are not as valuable. 
    • Composite services offer something in between.
  • Don't  make services more generic to increase their reusability. 
    • A service that is too generic is much harder to understand and use. 
    • First investigate if (future) reusability is necessary, before you end up with over-generic and non-understandable services and operations. 
  • Avoid creating over-generic  and non-specific services. 
    • Service clients don't know how to handle an over-generic service such as: SuperService.doThings, even though it is very reusable. 
    • An over-generic service requires too much knowledge of the implementation of the service in order to be able to use it correctly.
  • Reusability is different from ease-of-use or usability of services. 

Summary

In this article, I provide a brief outline of the typical steps in Designing Services and 9 basic Design Principles to guide service design in a SOA environment. The 9 SOA Service Design Principles covered are: Provide value, Meaningful, Implementation Hiding, Trust, Idempotent, Isolation, Interoperable, Granularity and Reusability. 

Adhering to these basic design principles will result in good services that are meaningful, provide value, easy to use, reusable and  flexible (but not over-generic),  and can be relied upon (trust) by clients.  Not all services have the same relevance, therefore in designing services in a SOA environment, the services must be categorized and different principles and guidelines should be apply to different types of services.


Additional References:
SOA Made Simple by Lonneke Dikmans and Ronald van Luttikhuizen
SOA Patterns by Arnon Rotem-Gal-Oz