Pragmatic Service Orientation

There is a lot of industry buzz around service orientation and
“SOA” and a number of prominent voices within Microsoft are trying
hard to articulate the approach the company is taking in this area.
I think it is important, first of all, to emphasise that there is
no Microsoft product that represents the hub of service orientation
– there isn’t anything that you have to buy to be “doing” service
orientation. In this post I want to outline my thoughts on how to
consider your application in terms of services in a pragmatic way
and as important point out what I don’t think service orientation
means.

In the late 80’s and early 90’s languages came to the fore that
allowed you to represent your data as classes together with the
associated operations that could be run with that data. This was a
shift from the block structured programming that was in favour
previously where code and data was kept apart and code modules were
formed around areas of functionality independent from where and how
data was stored. Today writing code using objects and classes is
the norm but it took a number of years for it to become mainstream:
C programming gave way to C++, Turbo Pascal introduced class-like
types, and bit by bit Visual Basic adopted object-like constructs.
This progression was how we entered the world of object
orientation.

Service orientation is an evolution of object orientation. Just
like the way object orientation didn’t mean one specific language,
platform, or technology, service orientation represents an approach
to building systems in a technology agnostic way. Object
orientation got us a long way down the road to building more
manageable and maintainable systems but as we moved to building
more and more distributed applications it became clear that
thinking about everything in terms of objects didn’t work any more.
While the concept of both local and remote code appearing in our
programming models as instances of objects was attractive, it
turned out that to build reliable, scalable and performant
distributed applications it really did matter where code was
located. We needed to treat remote objects differently from local
objects because of the speed and reliability of the network.
Starting to consider different aspects of our applications as
independent services helps to address these issues.

Another problem that we ran into with distributed objects was
one of versioning. Because the different distributed object
technologies typically exposed implementation details, it became
difficult to update and extend parts of an application without
impacting other areas. For example, how many times have you broken
a DCOM or COM+ application by deploying a change to a server
component and then finding that there is a compatibility issue with
some of the applications that rely on that code? What cumbersome
processes have you put in place or what annoying compromises have
you made to try to reduce the headaches caused by binary
compatibility? Service orientation is about reducing the coupling
between different parts of your application so that these problems
are easier to solve.

Okay, so I’ve talked about object orientation and some of the
problems with distributed or remote objects and that somehow
service orientation solves these problems but what is it? What do
we mean by service orientation? Well, service orientation is an
approach to building distributed applications by creating
independent services that cooperate through loosely coupled
interfaces to deliver the desired application functionality. A
service is a logical unit of code that operates in a well defined
area of the application with clear responsibilities through a well
known interface. In fact, we have four tenets that guide us in
building service oriented systems:

  • Services have explicit boundaries
  • Services are autonomous
  • Services share schema and contract and not class
  • Service compatibility is governed by policy

There has been a lot already written about these so I only want
to cover them quickly.

Explicit boundaries: it is important for services to define
their areas of responsibility and to expose their functionality
only through explicit interfaces. Because crossing service
boundaries impacts the performance and scalability of our systems,
we want to be explicit about when we make those calls and don’t
want them masked by technology that hides the difference between
local and remote code.

Services need to be autonomous so that, in a changing world, we
can extend and enhance both the functionality of a service and of
its consumers in an independent way and deploy those services as we
see fit. Autonomy also means we need to plan for and accommodate
failures when consuming other services. This is something that is
usually discouraged by object remoting technology.

Sharing schema and contract not class means exposing the “shape”
of the data we deal with rather than the implementation detail of
our service. Typically when we use DCOM or COM+, we install type
libraries and proxies on the client that expose details of the
class id’s used on the server. With .NET Remoting, we usually have
to make the types we expose on the server available on the client
for the CLR to make the remote calls. Service orientation breaks
this coupling and allows clients to be implemented independently
from the service.

Finally, we want to allow the way we communicate with services
to be governed by deployed policy. This means that I can expose my
service end-points using a variety of technologies and allow the
client to select the one it prefers and to understand the
requirements for that end-point, for example determining what to
use for security and reliability. This is an area that is pretty
weak in most of today’s protocol stacks but is being improved and
will become increasingly important.

It’s taken a fair amount of time for me to arrive at the point
of this post. Sorry about that. What I’ve written so far is really
background information. The key take away is that service
orientation is an approach to building systems and provides a
roadmap towards building loosely coupled distributed applications.
Nobody should be able to argue that loose coupling is a bad thing –
if you go back and read those block structured programming guides
from the 80’s, you’ll see them talking about high cohesion within
and loose coupling between application modules.

It is really important that you keep this in mind as you
consider whether and how service orientation applies to the systems
you are building. Don’t try to interpret the four tenets too
strictly: take a pragmatic view. I’ve seen too many people dismiss
service orientation arguing that it doesn’t apply to their
application. Take the fundamental principles of service orientation
and apply them as it makes sense. Think about how you will version
and deploy the parts of your application. Work through how you will
maintain a loose coupling between those parts. Don’t throw the baby
out with the bath water.

Service orientation doesn’t mean you have to deploy different
services using completely independent databases. Don’t dismiss
service orientation because you think it means having to kill
application performance by doing cross database joins at the
application tier. That’s taking the autonomy story too far. By all
means keep the data in the same database and do joins if
appropriate with SQL, just make sure you understand and have
documented which service is responsible for managing which data. I
recommend only doing this cross service data access in a read-only
way.

Service orientation doesn’t mean that you have to throw out all
your existing applications and start over. On the contrary, one of
the defining properties of service orientation is that by building
a service facade around existing applications, you can start to use
them in new and interesting ways that were never conceived of when
the application was originally built. You don’t have to have a huge
company-wide revolution to adopt service orientation – evolve your
applications, choose to build services as you write new code, think
about the lifetime of the systems you are building and how you will
manage change, pull out subsystems and expose them as services when
it makes sense.

How many times have you worked on systems that just can’t
sustain further development? Why does this happen? Usually it is
because of the tightly coupled nature of the different application
modules. Service orientation promotes loose coupling and asks you
to consider how things will evolve. The promise of service
orientation is that you will be able to rebuild and extend smaller
parts of your application one at a time in future without having to
consider a big bang rewrite. It will also allow you to leverage
your infrastructure in new ways allowing your business greater
agility in the marketplace.

I’ve used the same word a few times and it is the purpose of
this post: “pragmatic” service orientation is about understanding
the benefits of this approach and applying them in a sensible and
flexible way. Please be pragmatic.