A look at some of the core values espoused by SOA in Thomas Erl's fantastic "Service Oriented Architecture: Concepts, Technology and Design," 5 years later.
SOA, 5+ Years on
One of my favorite books is Thomas Erl's "Service Oriented Architecture: Concepts, Technology, and Design" It was published in 2005 (5 years ago! Time flies!), right at the beginning of the SOA craze. As we know, SOA died in January 2009. SOA got very hot as a buzzword and it became very difficult to find a clear, guiding description of the tenants that embody SOA. We all knew that "SOA" meant loose, open systems. But what does that mean? Who knew? SOA became a buzzword. It became a vacuous, nebulous idea that nobody quite understood, but everybody wanted. It was born of the then nascent web services paradigm.
The book offers a pretty good rubric of the values espoused by SOA, many of which I think are right on, and generic enough to be useful, and timeless. I reprint them here:
loose coupling: services maintain a relationship that minimizes dependencies and only requires that they retain an awareness of each other
Service Contract : services adhere to a communications agreement, as defined collectively by one or more
services descriptions and related documents
Autonomy: services have control over the logic encapsulated
abstraction: beyond what is describe in the service contract, service hide logic from the outside world
reusability: logic is divided into services with the intention of promoting reuse
composability: collections of services can be coordinated and assembled to form composite services
Statelessness: services minimize retaining information specific to an activity
discoverability: services are designed to be outwardly descriptive so that they can be found and assessed via available discovery mechanisms
The book itself then goes on for around 800 pages and details the strategic business and architectural requisites to meet these objectives, these laudable principles, along with technical elaboration. It spends an agonizing 17 chapters dealing with these objectives in terms of the various Web service specifications which - even then, 5 years ago - were termed "WS-*"! Sure, hindsight's 20/20, but anytime you have to write a book on an umbrella technology platform so expansive that it can be meaningfully referred to as WS-<wildcard>, that should be a clue as to the viability of that platform. Clearly, some of the technologies are no longer relevant, or stagnant.
The book doesn't list explicitly list the WS-* initiatives as being a key part of SOA in the rubric above, but reading between the lines, "open systems" certainly didn't mean DCE, CORBA or EJB! The content covering on the various web service specifications seems not just a little outdated today, of course, but it's worth noting that it was written before we had a clearer idea of RESTful architectures. At the time, the web services stack du jour was indeed WS-*, so that's fine. Nowadays, you might argue that - in the world of mashups, RIA and more - SOA is as much about simpler RESTful services as it is about WS-*. So, we might as well specify "web services" as part of SOA. The implication is that - even in a federated, enterprise service tier, you're going to have heterogeneous consumers.
Another one that could afford a second look is "discoverability." Discoverability never really happened.. not in a real way. It's something that has proven at best a secondary concern. I can only speculate as to why: do services tiers not grow to the size that might require a directory? Is it possible that the much vaunted, rapid free-for-all, dynamic consumption of third party services supposedly brokered only by an reflective scan of the services capabilities is not here, yet? The only major specification that I know of is UDDI, which is long since irrelevant today. Even major, initial proponents of the convoluted specification have long since shutdown their registries. There's a renewed interest, of late, in more general-purpose service registries (called SOA registries today, or service repositories, or SOA repositories). One example is MuleSoft's Galaxy offering, which enables precisely this. It's worth mentioning that this isn't a standard, though, de-facto or otherwise.
I think we can generally agree that loose coupling is a reality, and an unarguable win. Reuse is, as always, a win.
Service composition is... not quite what it should be, yet. There are some problems. First, composition is not the same as reuse. Reusing a generic service is quite different from building a facade on top of a series of other services with the intent of providing a more granular result. In fact, we have patterns to describe just such an arrangement, like facade. If the services are of different protocols and platforms, then these kinds of "compositions" start falling into the realm of Enterprise Service Buses - they become an integration problem. An ESB consumes the other services and fronts them to the client, providing an appropriate, aggregate result.
Another barrier to composition (and reuse, for that matter) are transactional semantics. If the services being used are "read-only," as they often are in REST services, then there's no need for concern. If the services mutate state, then it is important to have some sort of compensation mechanism in place. This leads to thinking in terms of units of works, and "compensatory transactions." Often, services that compose other services are referred to as orchestration services, sitting right above the services tier (the top block on the architectural "tiers" cake). Orchestration - in practice - means BPM and workflow, which in turn means state. You can't "undo" a service invocation on the client if you don't "remember" what the original state was. A workflow engine keeps that state for you, and lets you model compensatory processes naturally. So, composition is rarely as simple as calling two methods from one method.
Depending on the volatility of the origin services, a lot of work is required of the client to resilient to failures in those services. Additionally, because web services are by their very nature distributed and thus out-of-process, you can make no guarantees about their availability. One workaround to volatile, networked services is to build in retry logic, but this presumes that service calls are indempotent. Another workaround is to build in temporal decoupling and queue requests against the target service. This notion - that you can dampen the delays caused by slower upstream services by using queues - is core to the stage event driven architectural (SEDA) pattern.
Statelessness is a very powerful concept, but, as we've just discussed, it can sometimes be at odds with other tenants and goals. An itinerary based routing (IBR) ESB - most of them are IBR - imposes, and infers, state on otherwise stateless services. You describe an integration flow in terms of correlations: "when message X emerges from queue A with correllation key XK, send to service Y and encode the correllation key as a request parameter" That state is thus decentralized. Any single operation is O(1) time and there's no "memory" - each service forgets as soon as it has responded. We infer process state simply by correlating. Individual services are stateless, but clearly state is important. Additionally, because we eschew keeping state in the bus (there's no centralized process manager), each invocation re-encodes the state we need, which - strictly speaking - is wasteful.
Service contracts and loose coupling are occasionally at odds with each other: a sufficiently descriptive service contract will prescribe enough that it can't be useful to some clients.
On the whole, REST negates a lot of the issues I raise here. With a RESTful architecture there are only 4 ways to do anything (GET, PUT, POST, DELETE) and the mechanism to do them is ubiquitous, so it's reusable. RESTful composition is still subject to the same issues I've described earlier, but discoverability gains some ground: just bookmark the URL! REST services are based on HTTP, and so they are stateless. REST services are loosely coupled because REST services can be versioned, and thus no client should ever be required to change. The payload of requests and responses can be negotiated at exchange time between the client and the service, so there is also no reason it couldn't be reused with ease by multiple clients.
Looking forward, I think the architectural lessons learned are valuable, and continue to be important in todays architectures. SOA provided us with a mechanism to build singly-focused, reusable services in a generic, adaptive fashion. As we move into the world of cloud - which is to network operations what SOA was to distributed computing - I think these lessons will be even more important.
Nice post. As I was reading the principles, discoverability and composability both jumped out at me. You hit the nail on the head. Discoverability is overrated and composability is very tricky to get right. Discoverability is nice in a dynamic environment but there are better ways to skin that cat than the technologies mentioned here. Composition can be at odds with loose coupling and service contract. Composing services in a flattened way (call A, Call B, ...) works fine. When services cascade, there are all sorts of challenges. Composing using an intermediary just moves the problem.
WS-* co-opted SOA and became equivalent in the minds of many. Too bad. DCE, CORBA or EJB are all examples of implementation technologies that can be service-oriented at least as much as WS-*. At some level, all of them are the same Spam, in a different can.
Transactional semantics are on the other side of the coin from statelessness. Many applications that use transactions or state don't need it and they lose a lot by insisting upon it. It pays to explore architectures that don't require transactions or state.
The REST Architectural Style certainly gets us closer to the principles than the other technologies. Of course, anyone can write broken 'RESTful' services. REST doesn't emphasize service contracts in the traditional sense (WSDL) but you can use them if you wish (WADL). Service contracts are overrated for the same reason discovery is overrated.
Computer science has tried for decades to make distributed computing programmable as if it were local computing. REST embraces principles of distributed computing and the technologies that are known to work. There's no invention involved, unlike the other technologies mentioned.
Finally, beyond being co-opted, SOA has certainly suffered from definitional problems. Beyond what Josh mentions, many seem to apply the SOA moniker to integration infrastructures which aren't necessarily service infrastructures. The RAD/auto-generate approaches that WS-* seems to do fairly well, are suited to integration problems, but not to service problems.
> Computer science has tried for decades to make distributed > computing programmable as if it were local computing. REST > embraces principles of distributed computing and the > technologies that are known to work. There's no invention > involved, unlike the other technologies mentioned.
This is great point. It seems to me that the fundamental flaw of so many distributed technologies is that they attempt to hide the fact that the application is distributed. I think no IT or software professional can be forgiven for ignoring "The 8 Fallacies or Distributed Computing" as stated by Peter Deutsch but it seems to almost be the norm.
> I am an SOA neophyte, but I have been intrigued by > "Intents" in Android. These seem to provide a form of > discoverability. Thoughts?
I've not seen a whole lot of evidence that 'discoverability' works in practice. It's at the bottom of my priority list when it comes to SOA. Discoverability sounds cool but what's the use case? Who will discover these services? Personally, I think discoverability is a red-herring. The obsession with it might even have something to do with the perceived failure and 'death' of SOA.
I'd like to get some decent services that actually abstract things running before having them discovered. Maybe one day the ideas around discoverability will be realized but I think it's an example of trying to run before you know how to walk.