In search of REST

I believe there is hardly any developer these days who has not heard of REST (Representational State Transfer), and many have worked with it in some shape or form.  And more amazingly, there is probably no one this planet who is not positively affected by this architecture. I fall into the dabbled-with-some-cloud-apps camp.  For a long time, I have been uncomfortable with how a (seemingly) tight coupling exists between REST and HTTP.  I wanted to find out if that is indeed a fair statement.  A  geekation was in order.

To understand REST, I started right where it all started, Roy Fielding’s dissertation paper – chapter five.  A 30,000 foot level view of REST  is good place to start too.

REST is an architectural style to connect distributed systems (REST calls them connectors). Historically, software designs and architecture styles have mirrored patterns and practices in the real world. I expect the same to hold true for REST too. To understand and appreciate the strengths of REST, I will apply it’s principle to analog worlds. The example, I picked for applying REST principles is “banking”.  A client will interact with his bank in a local branch (we can draw parallel’s to a client application interacting with a REST service in the digital world).

Note: In most of this article, I rephrased many of REST’s terminology to make it readable. However, I provided a link to the official terminology as much as possible.

Resource

The foundational building block in a REST compliant architecture is a resource.  In the simplest terms, anything that can be looked up by a name could be considered a resource. It could be information or a service. In our example, the resources could be people like  “teller”,  things like “savings account # 123”, “checking account # 456”. And possibly services offered by the bank like “current balance”, “deposit funds” , “withdraw funds”.

The fundamental philosophy of REST is to standardize (within a context – for us it the bank) and minimize assumptions to the extent that resources and their consumers can evolve in vacuum (strong word, but you get the point) but still integrate (in real time) when needed.  REST achieves this by requiring all connectors to conform to an uniform interface.

Uniform Interface

The term interface has a special meaning to us developers. REST uses interface to mean something different when its says uniform interface.  It is not a strict and complete specification of behaviors that a connector will have. Rather, it is a set of (minimum) constraints that the connecters must satisfy.

Constraint # 1: Resources must have identifiers

A resource is known by its resource identifier. It is a unique and and unambiguous name of a resource within a REST ecosystem.

A few examples of resource identifiers are:

  1. savings account # 123
  2. checking account # 456
  3. And possibly…
    • current balance of account #123
    • deposit funds into account #123
    • withdraw funds from account #123

A resource itself is encapsulated by its provider.  A bank’s client will never know how the bank internally represents “checking account # 456” resource. Only the resource identifier, the account number # 456,  is exposed to the client. . Here are some features of resource identifiers:

  1. Each resource must be identifiable by an unique  identifier.
  2. The identifier should be immutable.
  3. There is no rigid syntax for identifiers. However, URI is a widely accepted REST compliant identifier scheme.
  4. Some resources are “well known” and some need to be “discovered” (covered by a later constraint # 5)

It is important to emphasis that a resource (identifier) is very different from an entity (identifier). Multiple resources, (for example: “deposit funds into account # 123” and  “withdraw funds from account # 123”) could manipulate a single entity (for example: account  # 123).

Constraint # 2: All resources in a portfolio must bear the same interface “commands”

The client expects to the following with his/her account:

Commands … applicable to these resources
  1. Withdraw money
  2. Deposit money
  3. Current balance
  4. Request statement
  5. Help
  1. Savings Account
  2. Checking Account

* I provided the Help command, so that the client can learn how to or what is needed to successfully work with a resource. REST does not suggest we provide this, but I think it is an important cog to further client self sufficiency and decoupling.

Contextual commands means coupling and dependency. REST eliminates this by mandating that all resources respond to the same commands, however, their behavior could vary wildly. This is similar (only slightly) to polymorphic behavior in object oriented design.

However, there is a tension between the variety of resources in the ecosystem and how many “commands” we can standardize on. The more resource variety we to the ecosystem,  fewer uniform commands we can afford. For example, if we added a semantically different resource ( like a credit card) to our bank’s resource portfolio, it will have dramatic affect on the resource-commands balance. This is because, a client can increase his credit limit, which he/she cannot do with a savings or checking account.

Commands … applicable to these resources
  1. Do
  2. Help
  1. Increase limit of credit card
  2. Current balance of savings account
  3. Current balance of checking account
  4. Current balance of credit card
  5. Deposit from savings account
  6. Deposit from checking account
  7. Deposit from credit card
  8. Request statement of savings account
  9. Request statement of checking account
  10. Request statement of credit card
  11. Witdraw from savings account
  12. Withdraw from checking account
  13. Withdraw from credit card

REST does not specify what the uniform commands should be offered, it only requires that all resources have the same set of commands.  It is up to us evaluate our domain and come up with a reasonable and static list.

Constraint #3: Messages must be self descriptive

Clients and resources communicate with each other using messages.

For example, “I need to deposit 200.00 USD. I will pay by a cheque“, is a message the client would give to the “savings account # 123” resource.

This constraint helps the client & resource to choose a mutually convenient message structure for communication. This further eliminates assumptions and decouples the two systems.  REST breaks down a message into three parts, viz.,

Example Message Component Role
200.00 USD Data This is the soul of the message. Resources/clients act on this.
Cheque Metadata  In the spirit of eliminating assumption, the component describe how the recipient (resource or client) should interpret the data.  More on this in constraint # 4.
Deposit Control data  How the client intends to modify the resource. See constraint # 2.

Constraint # 4:  Use “representations” to manipulate resources

Our client has a few possible ways to give 200.00 USD to the bank. Choices could be:

  1. 2 Benjamins
  2. 40 Lincolns
  3. 200 Washingtons
  4. 20,000 cents
  5. A cashiers cheque

These are how the client could get money into or out of say “checking account # 456”.

Some representations, even though possible, may not be acceptable to one party or both parties.  For example, your bank might refuse to accept 20,000 cents, and might request to get the money in 2 Benjamins, but your friend might want 200 Washingtons.

A few things to pay attention to:

  1. Representations lend concreteness to the abstract resources.
  2. Representations can be chosen on a per transaction basis.
  3. Representations are reusable, to work with more that one resource. In our example, they can be used to “deposit into checking account # 456” and “withdraw from checking account # 456”.

Constraint #5:  Resources are progressively discoverable

In a RESTful eco-system, some resource identifiers are like  the “north star” – guaranteed to be there for clients (for example, a teller in a bank). The moment you walk into the bank, you expect find a teller.  There will (and should) be very few resource identifiers of this kind.

On the other hand, many resource identifiers are ephemeral – new ones created, old ones destroyed or moved around (for example, the products offered by a bank,  customers accounts). This constraint is about not coupling the clients to these ephemeral resources identifiers. Instead, rely on the north-star resource identifiers to guide the clients to their desired ephemeral resource identifiers.  For example, the teller could tell you about the bank’s money market accounts and give your the resource identifier that can help you create one.  This type of organization of resource identifiers is called hypermedia.  The most well known example of  hypermedia is the “world wide web” .

A few things to pay attention to:

  1. Resource include resource identifiers to other contextual resource identifies in its response message.
  2. Once the client receives these resource identifiers, it will use the resource’s standard interface commands to work with it.

References on this constraint

  1. http://www.peej.co.uk/articles/hypermedia-as-the-engine-of-application-state.html
  2. http://blog.programmableweb.com/2012/08/01/rest-hypermedia-and-the-future-of-enterprise-web-apis/
  3. http://blueprintforge.com/blog/2012/01/01/a-short-explanation-of-hypermedia-controls-in-restful-services/
  4. http://www.slideshare.net/trilancer/why-hateoas-1547275
  5. http://www.infoq.com/articles/mark-baker-hypermedia
  6. Distributed Hypermedia

Post Geekation Blues

Like any good architecture, REST provides facility for various implementations. REST based on HTTP is the most common pattern, but does not have to the only pattern.  This coupling is so prevalent that even Fielding is frustrated with it.

Leave a comment