9

In comparing REST [api] structure with a OO model, I see these similarities:

Both:

  • Are data oriented

    • REST = Resources
    • OO = Objects
  • Surround operation around data

    • REST = surround VERBS (Get, Post, ...) around resources
    • OO = promote operation around objects by encapsulation

However, good OO practices do not always stand on REST apis when trying to apply the facade pattern for instance: in REST, you do not have 1 controller to handle all requests AND you do not hide internal object complexity.

Simple object relation between 2 concepts

Analogy between OO and REST

On the contrary, REST promotes resources publishing of all relations with a resource and other on at least two forms:

  1. via resource hierarchy relations (A contact of id 43 is composed of an address 453) : /api/contacts/43/addresses/453

  2. via links in a REST json response:

>> GET /api/contacts/43
<< HTTP Response {
   id: 43, ...
   addresses: [{
      id: 453, ...
   }],
   links: [{
      favoriteAddress: {
          id: 453
      }
   }]
}

Basic complexity hidden by objectA

Coming back to OO, the facade design pattern respect a Low Coupling between an objectA and its 'objectB client' and High Cohesion for this objectA and its internal object composition (objectC, objectD). With the objectA interface, this allow a developer to limit impact on objectB of the objectA internal changes (in objectC and objectD), as long as the objectA api (operations) are still respected.

In REST, the data (resource), the relations (links), and the behavior (verbs) are exploded in different elements and available to the web.

Playing with REST, I always have an impact on code changes between my client and server: Because I have High Coupling between my Backbone.js requests and Low Cohesion between resources.

I never figured out how to let my Backbone.js javascript application deal with "REST resources and features" discovery promoted by REST links. I understand that the WWW is meant to be served by multi servers, and that the OO elements had to be exploded to be serviced by many hosts in there, but for a simple scenario like "saving" a page showing a contact with its addresses, I end up with:

GET /api/contacts/43?embed=(addresses)
[save button pressed]
PUT /api/contacts/43
PUT /api/contacts/43/addresses/453

which lead me to move the saving action atomic transactional responsibility on the browsers applications (since two resources can be addressed separately).

With this in mind, if I cannot simplify my development (Facade design patterns not applicable), and if I bring more complexity to my client (handling transactional atomic save), where is the benefit of being RESTful ?

migrated from stackoverflow.com Nov 29 '13 at 10:07

This question came from our site for professional and enthusiast programmers.

  • 1
    Let me understand. You are saying that you have to update a Contact with a "embedded" (composition) linked address using two REST calls, one for the Contact and another for its Address. You have a Facade to handle updating contacts. What is the issue with making PUT /api/contacts/43 cascade the updates to inner objects? I had a lot of APIs designed like this (master URL reads / creates / updates the "whole" and sub urls updates the pieces). Just make sure that you don't update address when no changes are required (for performance reasons). – Anthony Accioly Nov 28 '13 at 20:57
  • @AnthonyAccioly, you understood correctly. I tried to clarify my question by adding some images. Your suggestion is good and that is also the conclusion I came with: manually controlling my request and use an embedded object to send only one request for keeping atomic my update. Still: Why everything in REST push me away from OO qualities or enforcements (encapsulation, ...) by flattening my model (implying many controllers). Using your solution gives 1 atomic update. Not using your solution brings a developer new responsibility and no rules on the api to prevent him doing it. – Alain Nov 28 '13 at 21:23
  • Just a note: the "resource hierarchy relations" you mentioned is a matter of how one might decide to encode relationship information in a identifier (in this case, a URL). I'm not sure this exposition of information is something that is part of REST or something it promotes, just a decision one makes on his own when coming up with the URLs of a system. If you believe otherwise, do you have any references of Roy Fielding discussing this matter as part of REST? – Thiago Silva Nov 30 '13 at 18:43
6

I think objects are only built correctly around coherent behaviors and not around data. I will provoke and say that data is almost irrelevant in the object oriented world. In fact, it's possible and sometime common to have objects that never return data, for example "log sinks", or objects that never return the data they are passed, for example if they calculate statistical properties.

Let us not confuse the PODS, (which are little more than structures), and the real objects that have behaviors (like the Contacts class in your example)1.

PODS are basically a convenience used to talk to repositories and business objects. They allow the code to be type safe. No more, no less. Business objects, on the other hand, provide concrete behaviors, like validating your data, or storing it, or using it to perform a calculation.

So, behaviors are what we use to measure "cohesion"2, and it's easy enough to see that in your object example there is some cohesion, even though you only show methods to manipulate top level contacts and no methods to manipulate addresses.

Regarding REST, you can see REST services as data repositories. The big difference with object oriented design is that there is (almost) only one design choice: you have four basic methods (more if you count HEAD, for example) and of course you have a lot of leeway with the URIs so you can do nifty stuff like pass many ids and get a larger structure back. Do not confuse the data they pass with the operations they perform. Cohesion and coupling are about code and not data.

Clearly, REST services have high cohesion (every way to interact with a resource is in the same place) and low coupling (every resource repository does not require knowledge of the others).

The basic fact remains, though, REST is essentially a single repository pattern for your data. This has consequences, because it's a paradigm built around easy accessibility over a slow medium, where there is a high cost for "chattiness": clients typically want to perform as few operations as possible, but at the same time only receive the data they need. This determines how deep an data tree you are going to send back.

In (correct) object oriented design, any non-trivial application will do much more complex operations, for example through composition. You could have methods for doing more specialized operations with the data -- which must be so, because while REST is an API protocol, OOD is used to build entire user facing applications! This is why measuring cohesion and coupling is fundamental in OOD, but almost insignificant in REST.

It should be obvious by now that analyzing data design with OO concepts is not a reliable way to measure it: it's like comparing apples and oranges!

In fact, it turns out that the benefits of being RESTful are (mostly) the ones outlined above: it's a good pattern for simple APIs over a slow medium. It is very cacheable, and shardable. It has fine grained control over chattiness, etc.

I hope this answers your (quite multifaceted) question :-)


1 This problem is part of a larger set of problems known as Object-Relational impedance mismatch. Proponents of ORMs are generally in the camp that explores the similarities between data analysis and behavior analysis, but ORMs have fallen under criticism of late because they seem not to really resolve the impedance mismatch and are considered leaky abstractions.

2 http://en.wikipedia.org/wiki/Cohesion_(computer_science)

  • You are right, I had hard time to explode my question in many aspects, to nail down a specific point, as the question address a "wrong" conclusion based on the accumulation of these aspects. I will try now to answer to your points in many comments. – Alain Nov 29 '13 at 22:20
  • [text 1] I used the word "data" to abstract from OO and REST world. Which word would you used to abstract properties in OO and data structure in REST ? – Alain Nov 29 '13 at 22:32
  • @Alain "data" is fine, but my point is not to confuse PODS and business objects. When we talk about OOD we generally speak about the second. The first are a convenience, and it could be almost as easily thought of a dictionary or struct or tuple. – Sklivvz Nov 29 '13 at 22:37
  • Yes, I agree, I use Backbone.js where saving a model is using a simple json structure. This is where the text reflect my actual coding experience. – Alain Nov 29 '13 at 22:40
  • [text 3] This is new to me. I thought that cohesion was measured by number of time methods use a specific relation... I prefer your way of viewing it. – Alain Nov 29 '13 at 22:49
1

With this in mind, if I cannot simplify my development (Facade design patterns not applicable), and if I bring more complexity to my client (handling transactional atomic save), where is the benefit of being RESTful ?

The answer to "where is the benefit of being RESTful?" is thoroughly analyzed and explained here: http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

The confusion in this question though is that it is not about characteristics of REST and how to cope with them, but assuming the design of the URLs you came up for your example system has something to do with being RESTful. After all, REST states that there are things called resources and an identifier should be provided for those that need to be referenced, but it does not dictate that, say, entities in your E.R. model should have 1-1 correspondence with the URLs you created (neither that the URLs should encode the cardinality of the E.R. relationships in the model).

In the case of contacts and addresses, you could have defined a resource that jointly represents these informations as a single unit, even though you may want to extract and save these informations in, say, different relational DB tables, whenever they are PUT or POSTed.

1

Thats because facades are a 'kludge'; you should take a look at 'api abstraction' and 'api chaining'. The api is a combination of two sets of functionality : I/O and resource management. Locally, the I/O is fine but within a distributed architecture (ie proxy, api gate, message queue, etc) the I/O is shared and thus the data and functionality becomes duplicated and entangled. This leades to an architectural cross-cutting concerns. This plagues ALL existing apis.

The only way to resolve this is to abstract I/O functionality for the API to a pre/post handler (like a handlerIntercepter in Spring/Grails or a filter in Rails) so functionality can be used as a monad and shared across instances and external tooling. Data for request/response also needs to be externalized in an object so it can be shared and reloaded as well.

http://www.slideshare.net/bobdobbes/api-abstraction-api-chaining

0

If you understand your REST service, or in general any kind of API, just as an additional interface exposed to clients so they can program your controller(s) through it, it suddenly becomes easy. The service is nothing more than an additional layer on top of your biz logic.

In other words, you don't have to split biz logic between multiple controllers, like you did in your picture above, and more importantly, you shouldn't. The data structures that are used to interchange data do not need to match the data structures you use internally, they can be quite different.

It is state of the art, and widely accepted, that it is a bad idea to put any biz logic into UI code. But every UI is just an kind of interface (the I in UI) to control the biz logic behind. Consequently, it seems obvious that is is also a bad idea to put any biz logic into the REST service layer, or any other API layer whatsoever.

Conceptually speaking, there's not that much of a difference between UI and service API.

  • I agree on the layer notion, but what do you mean by "program your controller through it" ? – Alain Nov 29 '13 at 22:53
  • 1
    I want to emphasize the fact, that the controller itself is the real service. The interface wrapped around the whole thing is merely a means to achieve something. Any interface exists to ease access to the wrapped functionality, in one way or another. A GUI does this for human users, a service API is used by clients. Both target audiences want to achieve something with the things wrapped behind the interface. I agree that "program" may be not the best wording for that, but "control the controllers" sounds awkward either ;-) – JensG Nov 30 '13 at 2:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.