I was struck by a statement that Pete Lacey made in his interview on infoq. The point was on SOA and coupling. Specifically:
PL: The second reason is that web services are too tightly coupled. Each participant needs to know a great deal about each of the others: the service and operation names, the messages they exchange, the datatypes of the message elements, the security context, the messaging semantics, etc. Thusly are non-scalable (and again I don’t mean transactional scalability) systems designed. One could argue that WSDL and the WS-Policy family of specifications addresses all this, but that’s not what I mean. Whether the tool knows or the programmer knows, the point is that one side of the conversation possesses intimate knowledge of the other, and should either side change, everything breaks.
What Pete is calling coupling, I call interfaces. Short of some magic that nobody has yet to explain, software components that interact need to have a contract and both sides have to know the contract. The client may not know about every detail of the contact, but it does know about the parts it needs. This is true whether the contract is exposed in SOAP or REST. And yes Peter, REST also exposes contracts that the other side needs to know. Move your resource to a new URI and see what happens to the clients.
If a contract is not coupling between applications, then what is? Coupling is about tying implementations together. Coupling occurs when it is not possible to change the implementation of the component without impacting clients. I will concede that there is very little in WSDL/SOAP that help prevent coupling. It's also unfortunate that for all of the complexity that comes with WSDL, the designers didn't include things like explicit constraint specification, that would have lead to better interfaces in WSDL.
The simple facts though is that REST doesn't make this any better. Resources have formats (schemas if XML). They are located by URI's which is a contract for where they can be found. Change the resource format in an incompatible way and clients break. Move the resource to a new location and the clients break. Contracts are contracts, break them and you break the software.
The challenge of coupling is much larger than the explicit interfaces exposed. An interface should clearly abstract the implementation. Everyone gets that. But what aspects of the interface are you explicitly stating and what aspects are being implicitly assumed? Is the response time part of the contract? Is the maximum throughput? Perhaps you say no, but then how can you be sure that no application, at Internet scale, has placed a concrete dependency on these aspects of your interface? And if either aspect were to change in a negative way, you'd break those applications. SOAP doesn't address this, but neither does REST.
If you're designing a good component with good contracts, then you are specifying aspects beyond simply the call interaction. You are specifying performance, availability, transactional assurances, data retention, manageability, and extensibility to name a few. You have to clearly state what promises you're making in each of these areas. You also have to be clear that those things that aren't specified are to be considered not part of any contract. In some cases, you may even specify aspects of the component that may not be depended upon.
Does this sound complex and heavyweight? Well, yes, it is definitely more involved than specifying a simple format at a URI. But if the goal is to achieve Internet scale, then failing to explicitly define your contracts will lead to real coupling. Non-obvious interactions that make both sides of the contract dependent upon each other and almost impossible to change in any manner at all.
Pete and I agree on one point. Coupling is bad for the Internet.
Technorati Tags: architecture, engineering, http, java, programming, rest, scalability, services, soa, software, to_read, toread, web
"Move your resource to a new URI and see what happens to the clients."
With a well-written HTTP client library nothing at all should happen as long as the server provides a 3xx response that points to the new location:
http://bitworking.org/projects/httplib2/ref/http-objects.html
Posted by: Joe | Tuesday, December 19, 2006 at 08:32 AM
The minute you have two systems that talk to each other you have some coupling - you need some knowledge as to what the other system will do, react or publish
The trick, so to speak, is to minimize that coupling but it will always be there unless you have isolated systems (or components for that matter)
Posted by: Arnon Rotem-Gal-Oz | Tuesday, December 19, 2006 at 10:44 AM
Dan, I've replied on my blog: http://wanderingbarque.com/nonintersecting/2006/12/19/coupling/
Posted by: Pete Lacey | Tuesday, December 19, 2006 at 11:50 AM
Resources are not located by URIs, they are identified by URIs.
What is the "location" of http://www.google.com/?
boo:~$ nslookup www.google.com
Server: 192.168.1.1
Address: 192.168.1.1#53
Non-authoritative answer:
www.google.com canonical name = www.l.google.com.
Name: www.l.google.com
Address: 216.239.59.147
Name: www.l.google.com
Address: 216.239.59.104
Name: www.l.google.com
Address: 216.239.59.99
Name: www.l.google.com
Address: 216.239.59.103
URIs are location independent.
What does it mean when a resource has two URIs, ie if we have URI aliases? Well this is considered a bad thing because the resource now has two identifiers which affects network effects, see http://www.w3.org/TR/2004/WD-webarch-20040705/#uri-benefits. However aliases can be resolved using HTTP re-directs.
The WS-* story on identification is not so clear, WS-Addressing can be used for the location of a Web Service but cannot be used to identify a Web Service - WS-Addressing provides no rules for comparing Endpoint References.
As to the question of contracts, in WS-* the contract is made early and is non negotiable: the WSDL. In REST part of the contract is made early: HTTP GET. But the rest is delayed for a late binding: content negotiation (clients says I understand these formats, with this set of preferences). This allows for independent evolution of client server, but of course cannot guarantuee interoperability.
WS-* cannot easily support independent evolution of client and server. The ultimate expression of loose coupling is mobile code.
Posted by: Mark Mc Keown | Wednesday, December 20, 2006 at 04:11 AM
Hi,
Some comments on contracts and coupling here:
http://jooto.com/blog/index.php/2006/12/25/contracts-and-coupling-in-resource-oriented-architecture/
Would love to hear your response! Thanks.
Alex
Posted by: Alex Bunardzic | Sunday, December 24, 2006 at 02:47 PM
You speak of REST as if it were a synonym for HTTP. REST is an architectural style, not a protocol, and one constraint within that style is that hypermedia is the engine of application state.
That means a REST-based architecture must use the control information within the data exchanged between client and server to guide the client's application through a network of simple states (simple when considered individually). This is very similar to a finite state machine, except that a combination of user configuration and standard media types define the set of transitions from this state to the next.
Because each state is dynamic in nature, the coupling in REST-based architectures is limited to the deployment of shared media types. Yes, that still means that some coupling does exist, but it is a comparatively easy to understand coupling and can be largely eliminated by shared media types that are general in nature.
In addition, the constraint that application "session" state be limited to that held on the client means that each state can be analyzed independently and eliminates most partial failure conditions that plague distributed services. This vastly simplifies the overall application by removing the inter-state coupling that is common to other architectures.
There is a lot more to REST than HTTP messaging.
Posted by: Roy T. Fielding | Sunday, December 31, 2006 at 03:06 PM
Coupling is not just the fact that endpoint A talks to endpoint B, but how frequently A talks with B and how dependent A is with B. Cyclomatic Complexity to a degree. If A calls B, B calls C, C calls A, A calls B, etc. until the whole thing unwinds ... that's bad coupling. Coupling of interfaces on their own is not a risk, it's the nature of the business. And it doesn't just occur with web services, but binary interfaces as well.
Posted by: Zeb | Friday, January 19, 2007 at 11:45 AM