Why REST is Better – Part 2 – Contract Based Protocols

Share the article!

So let’s go over a quick summary of interoperability guidelines that we derived in the previous article. These are:

  1. Named, optional, default arguments.
  2. Coarse grained document passing (i.e. minimize method invocations).
  3. Uniform interfaces.

The uniform interface allows us to have Decorator like capabilities. Examples of this can be found in unix command (i.e. the piping operator) and functional languages (i.e. functional composition). Java employs this pattern heavily in io package. So, not only do you have ease of composition, you also am able to leverage steaming behavior (see: lazy evaluation). So in code, you combine decorators and invoke the like this:

Decorator a = new DecoratorA( new DecoratorB ( new DecoratorC( args ) ) );
Request req = ...
Result resp = a.invoke( req );

The Adaptor program would look identical however the it would be more difficult to add a new Adaptor in the chain. So for example if you had this:

Adaptor a = new AdaptorA( new AdaptorB ( new AdaptorC( args ) ) );
RequestA req = ...
ResultA resp = a.method( req );

and you need to add functionality between A and B, then you would need to write a new adaptor with interfaces that transform your from B to A. (note: one cannot remove AdaptorB without AdaptorA implementing support for AdaptorC). One may argue that you will have to write a new Decorator from B to A also. The core difference is that when you write an adaptor you have to be specify completely the transformations from one interface to another. In addition the new adaptor would most likely share the same interface of AdaptorB otherwise you would have to reimplement AdaptorA. In short the chain itself it tightly coupled and therefore is more cumbersome to modify.

Adaptor a = new AdaptorA ( new AdaptorC( args )); //valid?

class AdaptorB2 extends AdaptorB { ... }; // Coupled to definition of AdaptorB
Adaptor a = new AdaptorA ( new AdaptorB2 (new AdaptorB ( new AdaptorC( args ) ) ) );

The decorator approach provides better modularity. With a decorator you can also ignore certain features and allow it to pass along the chain (see Chain of Responsibility). Just as we had default and optional arguments to reduce the cognitive bandwidth of invoking a method, decorators lower the cognitive overhead by allowing one to ignore certain features in a request. The Decorator chain is loosely coupled and affords greater freedom.

Decorator a = new DecoratorA(  new DecoratorC( args ) );  //ok!

class DecoratorB2 implements Decorator { ... } // not coupled to DecoratorB
Decorator a = new DecoratorA( new DecoratorB2 (new DecoratorB ( new DecoratorC( args ) ) ));

The question in most people’s minds when they see this uniform interface requirement is “is this be used for complex interactions?” The answer to this can be found in earlier work study of complex interactions found in human and agent sytems. These are known as speech acts (a.k.a Communicative Acts.

The list of speech acts is obviously more than the four required by REST. One could therefore easily argue that REST is insufficient. However, there is a hierarchy in speech acts. That hierarchy looks like this: ( Perlocutionary -> Illocutionary -> Propositional -> Utterances ). REST verbs are Perlocutionary utterances (i.e. intention to affect behavior). REST resources are composed of Illocutionary (the intention to interact) and Propositional utterances (references to other things). Utterances of course are the syntax you used to express your request.

The paper “Bringing Speech Acts into UMM” shows how to adapted speech acts in the context of business contracts. Where they define a pragmatic action as a triple (Intention, Action, REAObject ). Where Intention = {propose, accept, reject, declare, query, reply, assert}, Action = {create, change, cancel, none} and REAObject = {Agreement, EconomicContract,
EconomicComitment, EconomicEvent}. The paper shows that complex interactions based on variations of this triple can model a variety of complex business scenarios.

So in code, a general form of a class that can model complex business scenarios would be.

class PragmaticAction
      {
         Intention intention;
         Action action;
         REAObject reaObject;
      }

and its invocation would be:

PragmaticAction pa = ...
Protocol.invoke( pa );

The action attribute is isomorphic to REST four verbs (POST, PUT, DELETE, GET). Therefore if we modeled resources as followed:

class RESTResource
      {
      Intention intention;
      REAObject reaObject;
      }

and invoke REST like verbs like:

RESTResource res = ...
HTTPProtocol.put( res );

Once you treat REST resources as Contract like objects you begin to discover how complex interactions can be modeled. For example, Bill de Hora’ HTTPLR protocol for reliable HTTP using only RESTful constructs is in fact a negotiation of a contract where the contract is the reliable delivery of a resource. The exercise to show this is left to the reader. ;-)

Aside from the semantic elegance of associating REST verbs with perlocutionary utterances there’s an added quality benefit. Remember that chain of decorators we constucted earlier, if you new at the top most call that the invocation was read-only (i.e. GET) then you could make all kinds of cacheing assumptions to avoid having to call down the chain.

This shows that you can in fact model complex interactions with RESTful constructs. In fact, Contract based semantics as shown by Winograd and Flores has been shown to model workflow effectively.

I stumbled upon this developerWorks article “Resource-oriented vs. activity-oriented Web Services“. The author makes a completely absurd claim:

The point to all of this is simple: the choice of REST versus SOAP comes down to a basic understanding of what is most important to your particular application. If your application is focused primarily on the ability to access informational resources (as is the Bloglines service), then you have a primarily resource-oriented service and should likely turn to the REST-style design pattern for your application. There is significant precedence for this considering the service API’s offered by Amazon, del.icio.us, Flickr, Safari and others (see Resources). However, if your application is focused primarily on actions that might be performed orthogonally to the resources upon which they act, then your service is activity-oriented and should likely make use of the SOAP-style design pattern.

It’s becoming extremely tiresome listening to SOAP proponents continually shift the argument. I need to emphasize again, the only 3 valid reasons are “Interoperability, Interoperability, Interoperability”. API structure as I have shown has a big effect is supporting interoperability. The casual observation that SOAP is more suited for “activity-oriented” problems because it exposes more verb is naive at best.
SOAP adherents would have you believe that additional complexity needs to be surfaced. That claim as argued here is clearly inaccurate.

I’ve again run out of time! The next time, I’ll try to cover how asychronicity allows for better interoperability and why the SOAP envelope structure is wrong.


Share the article!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>