views:

53

answers:

3

Hi

I am currently designing the API for an existing PHP application, and to this end am investigating REST as a sensible architectural approach.

I believe I have a reasonable grasp of the key concepts, but I'm struggling to find anybody that has tackled object hierarchies and REST.

Here's the problem...

In the [application] business object hierarchy we have:

Users 
 L which have one-to-many Channel objects
 L which have one-to-many Member objects

In the application itself we use a lazy load approach to populate the User object with arrays of these objects as required. I believe in OO terms this is object aggregation, but I have seen various naming inconsistencies and do not care to start a war about the precise naming convention .

For now, consider I have some loosely coupled objects that I may / may not populate depending on application need.

From a REST perspective, I am trying to ascertain what the approach should be. Here is my current thinking (considering GET only for the time being):

Option 1 - fully populate the objects:

GET api.example.com/user/{user_id}

Read the User object (resource) and return the User object with all possible Channel and Member objects pre-loaded and encoded (JSON or XML).

PROS: reduce number of objects, no traversal of object hierarchies required
CONS: objects must be fully populated (expensive)

Option 2 - populate the primary object and include links to the other object resources:

GET api.example.com/user/{user_id}

Read the User object (resource) and return the User object User data populated and two lists.

Each list references the appropriate (sub) resource i.e.

api.example.com/channel/{channel_id}
api.example.com/member/{member_id}

I think this is close to (or exactly) the implications of hypermedia - the client can get the other resources if it wants (as long as I tag them sensibly).

PROS: client can choose to load the subordinates or otherwise, better separation of the objects as REST resources
CONS: further trip required to get the secondary resources

Option 3 - enable recursive retrieves

GET api.example.com/user/{user_id}

Read the User object and include links to lists of the sub-objects i.e.

api.example.com/user/{user_id}/channels
api.example.com/user/{user_id}/members

the /channels call would return a list of channel resources in the form (as above):

api.example.com/channel/{channel_id}

PROS: primary resources expose where to go to get the subodinates but not what they are (more RESTful?), no requirement to get the subordinates up front, the subordinate list generators (/channels and /members) provide interfaces (method like) making the response more service like.
CONS: three calls now required to fully populate the object

Option 4 - (re)consider the object design for REST

I am re-using the [existing] application object hierarchy and trying to apply it to REST - or perhaps more directly, provide an API interface to it.

Perhaps the REST object hierarchy should be different, or perhaps the new RESTful thinking is exposing limitations of the existing object design.

Any thoughts on the above welcomed.

Many thanks

Paul

+4  A: 

There's no reason not to combine these.

  • api.example.com/user/{user_id} – return a user representation
  • api.example.com/channel/{channel_id} – return a channel representation
  • api.example.com/user/{user_id}/channels – return a list of channel representations
  • api.example.com/user/{user_id}/channel_list – return a list of channel ids (or links to their full representations, using the above links)

When in doubt, think about how you would display the data to a human user without "API" concerns: a user wants both index pages ({user_id}/channel_list) and full views ({user_id}/channels).

Once you have that, just support JSON instead of (or in addition to) HTML as the representation format, and you have REST.

Piet Delport
Great way to put it.
Darrel Miller
Piet - many thanks for this, it is very useful. I would like to clarify the point about traversing the data from a human perspective. My thought is that if I provide a list of 'next' resources rather than a 'full view' I allow the user to peruse what they want to peruse, and therefore providing a list of links is 'more' RESTful (conforms better to HATEOS). I could understand that providing a populated list is useful for performance reasons however. I know this is somewhat use-case dependent, but I wonder if I'd be better to keep the interface simpler (and maybe slower) for the time being?
paulkmoore
+1  A: 

The best advice I can give is to try and avoid thinking about your REST api as exposing your objects. The resources you create should support the use cases you need. If necessary you might create resources for all three options:

api.example.com/completeuser/{id}
api.example.com/linkeduser/{id}
api.example.com/lightweightuser/{id}

Obviously my names are a bit goofy, but it really doesn't matter what you call them. The idea is that you use the REST api to present data in the most logical way for the particular usage scenario. If there are multiple scenarios, create multiple resources, if necessary. I like to think of my resources more like UI models rather than business entities.

Darrel Miller
Darrel - thanks for this - also very useful. I suspected that there was some subtlety around the object mapping that I was missing. I am concluding that whilst I may call on my existing object framework, I need to design carefully my 'resource view'. Thanks.
paulkmoore
A: 

Here's my conclusions from many hours searching and with input from the responders here:

Where I have an object that is effectively a multi-part object, I need to treat that as a single resource. Thus if I GET the object, all the sub-ordinates should be present. This is required in order that the resource is cacheable. If I part load the object (and provide an ETag stamp) then other requestors may receive a partial object when they expected a full one. Conclude - objects should be fully populated if they are being made available as resources.

Associated object relationships should be made available as links to other (primary) resources. In this way the objects are discoverable by traversing the API.

Also, the object hierarchy that made sense for main application site may appear not be what you need to act in RESTful manner, but is more likely revealing problems with the existing hierarchy. Having said this the API may require more specialised use cases than had been previously envisaged, and specialised resources may be required.

Hope that helps someone

paulkmoore