SOA World - My Design Time Is Your Runtime PDF Print E-mail
 

By Jim Murphy
May 28, 2007

You've deployed a Web Service. It's been designed, built, tested, and published to your registry for use and is now a critical component in a strategic business application. Your SOA is beginning to show signs of return but what happens when other architects discover your service and begin to design new applications with it? On one hand, you're seeing the benefits of reuse, yet how can you manage a service that's undergoing continuous testing? What happens to your initial business application when one of its key services undergoes a load test for another composite application?

 

In a SOA, the characteristics of traditional design time and runtime are changed. The rules about ensuring quality are changing as well. No longer is it sufficient to follow design, build, test, deploy, and manage phases. Testing is continuous and can have a drastic impact on production applications. This article will examine the impact of SOA on traditional SDLC thinking and how testing can be done in production environments. We'll also explore the role collaborative SOA quality plays in lifecycle governance.

At the center of an SOA solution is the relationship between service consumers and service providers with distinct lifecycles. Separation of application functionality across lifecycles has profound effects on the development process and serious implications on managing system quality.

A Young Person's Guide to the SDLC
Wikipedia describes various process models that define a Software Development Lifecycle (SDLC) as a series of activities related to the development of software systems. The specific tasks vary between the process models that define specific software development processes but they are more the same than different. They boil down to the same basic steps:
*  Analyze the Requirements
*  Design the Architecture and Implementation
*  Code and Build
*  Test to Verify
*  Deploy and Maintain (Figure 1)

Make no mistake this *is* your father's software development process but it's the basis for many approaches to organized software development.

Agilists (AgileManifesto) have refined this model to make it fit the dynamics of software development and the needs of the business better by adding feedback loops, iteration, deferred requirements gathering, and continuous testing. Defined processes like the Agile Unified Process (AmblerAUP), XP Lifecycle (AmblerXPLifecycle) and the Agile SDLC (AmblerAgileSDLC) are examples of agile refinements to the basic software development process itself.

Traditional or agile the SDLC process has a start, a middle, and an end.

This is not the case with an SOA designed to meet business needs over time. An SOA has no practical notion of start and end much like the Internet has no clearly delineated analysis, design, build, and test activities but is a composite of several interacting components that are constantly coming and going, changing and evolving, and to a greater or lesser extent interacting.

The Impact of SOA on the SDLC
It's important to realize that the SDLC pertains to the service construction process not to the overall SOA evolution. SOA activities focus on higher-level concerns across a service inventory like granularity, coupling, reuse, and governance. This difference is often missed by teams accustomed to building distributed systems or integrations following an SDLC process.

Building SOA like traditional distributed architecture is identified in Thomas Erl's SOA systems report as the #1 obstacle in SOA adoption. The assumption in traditional projects is that you can change the client and the server simultaneously through development. Design, coding, refactoring, and test occur across the boundary of consumer and provider as needed to make the whole system work. The fact that there are clients and servers separated by a network is more an implementation detail that traditional technologies often try to hide for the sake of the programmer.

Service-oriented solutions, as the name implies, focus on providing services to service consumers and that an exhaustive list of consumers and their requirements are not identifiable upfront. This is the essence of why SOA is interesting in business computing. It's incumbent on service providers to understand and anticipate the problem domain and build services that fit naturally in the larger service inventory to provide a valuable capability to a range of future consumers.

This service-oriented focus results in a separation of the service development and consumer development cycles. (Figure 2)

Consumer developers are separated from service developers in time and space. Since there is a clear separation of lifecycles the terms design time and runtime depend on your point of view.

Often service providers follow a design, build, test, and ultimately publish phases where service metadata is made available in registry/repository.

At some future point service consumers discover services as part of a build vs. reuse design process. Services that fit the need are selected for reuse while missing or mismatched services are built. The service consumer project can then follow the recognizable lifecycle phases of build, test, and deploy.

Consumer Design Time at Service Runtime
Several thorny issues arise, in this common case, when a consuming application's design time occurs during its dependent services runtime. The challenges depend on the capabilities provided by the service provider.

An obvious first question is "What endpoint should consumer development use?" When a consuming application depends on external service managed by other people, how should development and test interactions happen? What techniques are available from all of the dependent services? Will you use live production service instances or is there service stand-ins available? What's the expected level of similarity between stand-ins and production systems if they do exist? These determinations need to be made for each service used by the consumer application. What expectations should the consumer team have about the consistency of approach between all of the services used? Do they all have staging instances or do they use different techniques?


For services that don't have staging instances available what is the external effect of development and test messages? How should load testing the consumer application or service? Are there chargebacks based on service use that apply? There are several techniques to manage the development and test interactions of consumers on dependent services.

1.  Staging Instances: A service provider can make a separate service instance available with an identical service interface that's not connected to the live back-end. Well-mannered interaction with this staging system isn't important. Consumer development can have its way with the staging system that may even automate refreshing its back-end data periodically. It's expensive to build and maintain but there's not substitute for running the same code in a safe environment.
2.  Simulations: Instead of building a full-fledged duplicate instance of a service a mock service-style simulation provides many of the same benefits as a service stand-in. The fidelity of the simulation is less likely than a full staging instance but it can be created and maintained by anyone if the service provider doesn't offer an alternative.
3.  Special Accounts: Using a live service endpoint it's possible to identify your intention by using an explicit test account during authentication. A test account issued by the service provider lets the service provider handle test messages differently or at least correlate transactions with a test account.
4.  Message Header: A custom SOAP header can assert that a message is intended as a test message. The message can trip the service implementation to operate in an idempotent mode or to correlate transactions for post processing and possible compensation.
5.  Data Partitioning: A degenerate case of two-four is the use of specific application data to partition development and test requests from "real" requests. Domain-specific options include using a distinguished warehouse name in an inventory service or a particular book title/ISBN in an online store to indicate a test request.
6.  Compensating Transactions: If none of the above techniques are suitable live transactions may need to be performed and followed up with compensating transactions to return the system to a base-level state. In HR systems hiring a long running test might involve "test employee," giving them a raise then firing them. Keeping the transaction state manually during development and test is probably more trouble than it's worth. It seems plain that sooner rather than later something will fail to get cleaned up properly.

Service Design Time & Consumer Runtime
This is the service provider's chance to break all its consumers and make them wary of ever using that service, or any service, ever again.

Clearly service providers need to keep their consumers in mind when making changes to the service's interface or even its implementation particularly if the new service version drops in at the existing endpoint. Of course this is easier said than done.

Understanding consumer expectations of service behavior is a complex analysis that begins with analyzing changes to the service interface description but must also include runtime semantics like data coherency and consistency. It may also include understanding how your service is used with other services you've never heard of.

Knowing when you're about to break a consumer is very difficult in practice. Analyzing the service interface changes is only the beginning. Service providers likely don't know how their consumers are using the service in conjunction with other services. The best way for service providers to know is for consumers to tell them very specifically by sharing their tests. When service consumers assert the precise nature of service usage, service providers can include their consumer's perspectives in their regression suites. Consumer-provided shared tests form a folksonomy of semantic expectations from the consumer community.

Once a mechanism for sharing tests exists it's a natural extension to begin testing for behavior that doesn't exist yet as a way to drive enhancements in service behavior. Voila, test driven development for SOA!

Consumer applications make build-versus-reuse decisions of services based on what's available in the service inventory and how well it matches requirements in much the same way we buy software from vendors.

Some reuse decisions will be simple. However; we're all human and have imperfect knowledge of future requirements so consumers will eventually need changes to a service interface, its implementation, runtime characteristics like availability or SLA, or even back-end data access and consistency.

This feedback flows as new requirements to the service provider team and can influence future development the same way new features appear in commercial software applications: when the next version ships. This can tie the delivery schedule of a consumer application to the delivery schedule of its dependent services. Schedule coupling rewards service providers who anticipate the future as much as possible and productize service delivery by following the Software as a Service (SaaS) model where the service is productized.

By treating your services as products delivered as services you can take a more holistic approach including:

  1. A mechanism for gathering consumer feedback
  2. Notification of upcoming versions
  3. Forward and backward compatibility expectations
  4. Old version support expectations
  5. Impact analysis of change

Metadata Design Time?
Once services and consumers have cycled through their respective lifecycle phases and are both at runtime there's still room for change. New policies and policy changes that manifest in changes to runtime metadata can drastically affect deployed services and applications. Security, transformation location, and routing changes can change the way service availability, semantics, or performance in catastrophic or insidiously subtle ways react.

Overall SOA Quality
When a system exists in a single lifecycle its overall quality is under the direct influence of the development team. Time and resources can be added or changes made to improve system quality. For service consumers application boundaries are vague and no longer in their direct control so assessing and assuring quality becomes a distributed problem. Depending on the actions of each dependent service and changes to intermediary metadata the consumer application's quality is now a function of time and no longer isolated to any identifiable test phase.

This raises the question of "Who is responsible for overall SOA quality?" The individual services in the service inventory certainly have their place but who ensures the consistency and the framework to make SOA quality happen?

There are two sides to the SOA-quality coin. The first is in creating well designed and implemented service and applications in the first place. The second is in providing a resolution mechanism when the inevitable happens. There will be problems between consumers and services no matter what. Plan for the inevitable when consumers and providers need to find runtime problems and avoid figure pointing.

Lifecycle governance is the constraint framework to connect loosely coupled development processes. Extending current notions of lifecycle governance to include the provision of a quality framework lets consumers and providers manage the quality concerns of the other. High-quality service components are necessary but insufficient for healthy and holistic service-oriented architectures.

References
From a talk given by Amr Elssamadisy on SOA, Agile, and TDD at SD West:

"Here's the problem in a nutshell. Agile requires that you fix what you break. So if you change the service your team is writing, you must fix whatever that change breaks in the clients using that service. You're responsible for your own messes. SOA, on the other hand, usually assumes that there will be no collective code ownership. So you can't fix someone else's code. What's needed is a way for the team developing the service to run a test to see if their change will break any clients.

For that to work, though, the service team's test suite needs to know what breaks the clients. If they don't own the code then how does this happen? By sharing tests. Everyone shares all their tests with everyone else. That way the client's tests become part of the server team's regression test suite throughout the development process."

 

About Jim Murphy
Jim Murphy is vice president of product management at Mindreef, Inc., and is responsible for overseeing the complete suite of Web services testing and SOA Quality products. He has been with Mindreef for more than four years, most recently as lead software architect. Jim brings more than 12 years experience designing, implementing, testing and debugging distributed software architectures using Java, .NET, C++ and XML. Prior to Mindreef, he was an independent consultant and has served as a director, software architect and senior software engineer at several early-stage product and consulting organizations.