Re: Link Relations

mike amundsen <[email protected]> Sat, 9 Nov 2013 20:25:47 -0500
Newsgroups gmane.comp.web.services.rest
Message-ID <CAPW_8m4DmN1c_Tp1YqL0VKX1uPdW74LQgyZ-1V9wghQCQ52X=g@mail.gmail.com>
<snip>
A key requirement for me is to reduce as much as possible coupling,
therefore I try to design resources as generically as possible (a list of
simple attributes and a list of relationships/states) with the goal to
allow for maximum evolvability of the API - given the mostly UI-driven
interactions against the API.
</snip>

If you favor JSON and want to reduce coupling between internal coding and
the shared messages, I highly recommend one of the recently-registered
hypermedia types such as HAL+JSON[1], Collection+JSON[2], and Siren[3]. I
find each of these has a unique strength and all of them do a good job of
leading you toward SoC between local components and shared state messages.

By treating the message as a structured format independent of your problem
domain (books, etc.) you get quite far down the path of decoupled
communications. HTML has been successful at this for more than a decade;
our servers continually transform local business objects in the this format
and enable applications running in a client app that knows nothing of the
problem domain, but *does* understand the message format and the protocol
details express _within_ the message (HTML.A, HTML.IMG, HTML.FORM).

<snip>What about the others experience with forms resources vs strongly
typed links?</snip>

Yes, this convo has gotten a bit narrow since I am dominating the thread. I
know there are several others here who have experience in this space, too.

Cheers.

[1] http://stateless.co/hal_specification.html
[2] http://amundsen.com/media-types/collection/
[3] https://github.com/kevinswiber/siren



mamund
+1.859.757.1449
skype: mca.amundsen
http://amundsen.com/blog/
http://twitter.com/mamund
https://github.com/mamund
http://www.linkedin.com/in/mamund


On Sat, Nov 9, 2013 at 7:14 PM, Philippe Marsteau <[email protected]>wrote:

> Thank you Mike. That clarifies a lot.
>
> I think I misunderstood link relationships vs. capabilities/states. Your
> proposed approaches help me see how to better design this.
>
> A key requirement for me is to reduce as much as possible coupling,
> therefore I try to design resources as generically as possible (a list of
> simple attributes and a list of relationships/states) with the goal to
> allow for maximum evolvability of the API - given the mostly UI-driven
> interactions against the API.
>
> Basically, I try to map the web pages one would interact with from a
> browser, but stripping out the UI elements (using generic JSON like format).
>
> By keeping the media type as low entry barrier (simple) as possible,
> assuming client will mostly render the data in its preferred technology,
> adding attributes or actions becomes highly dynamic without requiring
> consumer to "uptake" changes: attributes appear dynamically in UI front end
> and new interactions (think of "more actions" drop box) becomes added
> dynamically as well. I think your CJ media type is pretty generic too, so
> maybe this idea/goal is familiar to you...
>
> I also understand this might not fit for system to system type of
> interactions (scripted/automated integrations) and my goal might be too
> idealistic. Have you seen such type of REST APIs? Am I heading in the right
> direction?
>
> What about the others experience with forms resources vs strongly typed
> links?
>
> Phil
>
> Le 9 nov. 2013 à 18:51, mike amundsen <[email protected]> a écrit :
>
> <snip>
> Now how do I tell in this book representation that at this time, clearing
> the shopping cart or adding the book to the shipping cart is not allowed
> (eg based on authenticated user permissions) but reading it is allowed? I
> wish user could discover from the representation rather than having to call
> OPTIONS or learning after the fact (error message)...
> </snip>
>
> If you wish to communicate this level of detail to clients (not at all a
> bad thing) often people think of these as _actions_ instead of states and
> just communicate the possible action:
> rel="clear"
> rel="add-book"
> and so forth.
>
> I try to steer clear of that whenever possible (as a design goal) and
> express these things as "states" on the server that need to be
> communicated to the client. for example (just making this up here...):
> - "clear" (the resource can be cleared or removed)
> - "edit" (the resource can be appended-to or child records can be added)
> and so forth.
>
> this means representations can look like this:
> <shopping-cart>
>   <link href="..." rel="collection http://example.com/rels/shopping-cart"
> state="read clear" />
>   <items count="9">
>     <item href="..." rel="item http://example.com/rels/book" state="read
> clear">
>       ...
>     </item>
>     ...
>   </items>
> </shopping-cart>
>
> or you can use a much more explicit design:
> <shopping-cart>
>   <clear href="..." rel="collection http://example.com/rels/shopping-cart"
> />
>   <read href="..." rel="collection http://example.com/rels/shopping-cart"
> />
>    <items count="9">
>     <item>
>       <clear href="..." rel="item http://example.com/rels/book" />
>       <read href="..." rel="item http://example.com/rels/book" />
>       ...
>     </item>
>     ...
>   </items>
> </shopping-cart>
>
> These are just two possibilities. Note that i didn't include a protocol
> method in these designs, but that would be possible, too. an explicit
> example (one that might support more than one protocol) might look like
> this:
> <shopping-cart>
>   <clear href="..." rel="collection http://example.com/rels/shopping-cart"
> method="HTTP.DELETE"/>
>   <read href="..." rel="collection http://example.com/rels/shopping-cart"
> method="HTTP.GET"/>
>   <items count="9">
>     ...
>   </items>
> </shopping-cart>
>
> Again, this is design so there are many possibilities.
>
> <snip>
> Also where in this context fit the concept of forms, allowing user to fill
> in some parameters...
> </snip>
>
> yes, i use forms quite often. this is about what state needs to be
> transferred from the client to the server (usually we only think about
> transferring state from server to client!). I might have a server that
> requires additional data in order to add an item to a cart:
>
> <link href="..." rel="http://example.com/rels/shopping-cart">
>   <data name="quantity" value="1" />
>   <date name="stockid" value="q1w2e3" />
>   <date name="required-delivery-date" value="2013-12-24" />
> </link>
> and so forth.
>
> I am in the habit of including forms in responses[0]. However, some folks
> prefer to only include links to forms and keep the forms as stand-alone
> resources[1]. Still others think it best not to include this information at
> all and keep that information as part of the documentation[2]
>
> Again, these are design decisions you can make on your own when creating
> your own message format (media type) or one that you can use to guide which
> of the existing registered types will best fit your needs/aesthetics.
>
> Cheers.
>
> [0] http://amundsen.com/media-types/collection/format/#objects-template
>  [1] http://iansrobinson.com/2010/09/02/using-typed-links-to-forms/
> [2] http://tools.ietf.org/html/draft-kelly-json-hal-06#section-8.2
>
>
>
>
> mamund
> +1.859.757.1449
> skype: mca.amundsen
> http://amundsen.com/blog/
> http://twitter.com/mamund
> https://github.com/mamund
> http://www.linkedin.com/in/mamund
>
>
> On Sat, Nov 9, 2013 at 5:46 PM, Philippe Marsteau <[email protected]>wrote:
>
>> Interesting...
>>
>> Now how do I tell in this book representation that at this time, clearing
>> the shopping cart or adding the book to the shipping cart is not allowed
>> (eg based on authenticated user permissions) but reading it is allowed? I
>> wish user could discover from the representation rather than having to call
>> OPTIONS or learning after the fact (error message)...
>>
>> Also where in this context fit the concept of forms, allowing user to
>> fill in some parameters, before user can actually add the book in the
>> shipping cart (eg, number of books to add)? Would the representation
>> include a link to the form (instead of to the shopping cart directly), and
>> its doc states only GET is allowed? The idea is to let user discover which
>> attributes are need as input before a PUT (or POST or PATCH) can be called
>> on the shopping cart... Instead of having client to hard code editable
>> input fields to be requested to user ("knowing" the media type or profile
>> of the shopping cart resource).
>>
>> Thanks again, it helps.
>>
>> Phil
>>
>> Le 9 nov. 2013 à 16:53, mike amundsen <[email protected]> a écrit :
>>
>>  FWIW, you're getting in to "design" space here - and that's based on
>> context and preference. nothing right/wrong here so there are lots of
>> options.
>>
>> first, i usually indicate state properties of a resource using data
>> elements in the representation, not transition elements:
>>
>> <book>
>>   <in-stock value="true" />
>>   <link href="..." rel="http://example.com/rels/shopping-cart" />
>> </book>
>>
>> again, instructions on the link identified as the shopping cart might
>> look like this:
>> - HTTP.GET returns the state of the shopping cart
>> - HTTP.POST adds the current book to the shopping cart
>> - HTTP.DELETE clears all items from the shopping cart
>> and so on...
>>
>> now clients (humans) can see that the "state" of the book is "in-stock"
>> and then decide to take an appropriate action.
>>
>>
>> as for "I believe there are cases where the server dictates the steps
>> before"...
>>
>> yes, the server may have rules about what "state" server-side resources
>> need to have before a task can be executed. This can be viewed as dictating
>> that "state" of things on the server, not dictating the order in which
>> things happen on the client. This POV is close to the way programmers had
>> to (re)learn to design user interfaces with teh advent of the pointer
>> device (mouse). Suddenly, users could not be "led" from input to input in a
>> certain order. Users had be power (and audacity) to click around on the
>> screen, enter things in various order and so on. It was bedlam (grin)!
>>
>> eventually, we learned to build UIs that used things like progressive
>> disclosure, disabling items until certain "state" in the UI is achieved,
>> etc.
>>
>> we need to do that same for hypermedia services on the web.
>>
>> hope this helps.
>>
>>
>> mamund
>> +1.859.757.1449
>> skype: mca.amundsen
>> http://amundsen.com/blog/
>> http://twitter.com/mamund
>> https://github.com/mamund
>> http://www.linkedin.com/in/mamund
>>
>>
>> On Sat, Nov 9, 2013 at 3:25 PM, Philippe Marsteau <[email protected]>wrote:
>>
>>> Appreciate the feedback and experience sharing.
>>>
>>> So reusing my use case if buying a book, what rels would define from the
>>> root book collection resource? (assuming the application is designed to let
>>> customers buy books).
>>>
>>> How do I let the consumer discover a book listed in the collection can
>>> now be "bought"?
>>>
>>> I believe there are cases where the server dictates the steps before a
>>> book order can be placed: server decides shipment info is ended or payment
>>> info is needed. I mean the book listed in store does not have a model
>>> relationship "orders" linking to it, does it?
>>>
>>> You cannot create an order until user goes through a server defined list
>>> of steps. Furthermore, the steps could be different per user (eg one who
>>> already stored his payment/shipping on file for future orders).
>>>
>>> While I completely understand it is the consumer who activates the
>>> hypermedia controls, and thus the workflow progress depends on the user, I
>>> need a way to let consumer discover through hypermedia controls "what" can
>>> be done at each step of the application business workflow (here: what info
>>> must be entered to complete the book order process?), based on user
>>> permissions or internal application state...
>>>
>>> Your further guidance is appreciated!
>>>
>>> Le 9 nov. 2013 à 14:25, mike amundsen <[email protected]> a écrit :
>>>
>>>  I will say that i've gone both routes (using rels to indicate
>>> relationships and using rels to indicate actions) and am not settled on
>>> either.
>>>
>>> the "rel" community def. wants to see this attribute used to indicate
>>> relationships. reviews of  recently registered values at the IANA show this.
>>>
>>> however, i can see the appeal and value of having action indicators on
>>> hypermedia controls; esp. in cases where machines are doing the work of
>>> selecting controls to activate. in this case it seems efficient to reduce
>>> the "decision distance" of 1) find the control that has an id of the
>>> desired target then, 2) look at the control to see what protocol action is
>>> available to 1) find the control that has the id of the desired action of
>>> the target. But this is, in the long run, a false efficiency. It _assumes_
>>> the client code already "knows" things (action and target are coupled) and
>>> constrains the possible options for the client ("you can only do a single
>>> action for this control, want to do some other action? sorry, no control
>>> for that here, move along").
>>>
>>> in the big picture, i've found keeping target identifiers (collection,
>>> storage, document, person) decoupled from action (share, modify, copy,
>>> move, approve, cancel) is a big win. while it adds some
>>> indirection/complexity to the representation (both at design-time and
>>> run-time) this pattern also adds more options and increases the
>>> independence of the client application. including allowing clients to (in
>>> some cases) create new successful workflows that the server didn't map out
>>> even though it is completely allowed by the state machine.
>>>
>>> FWIW, if you want to continue to constrain clients to only following
>>> strict server pre-defined paths, you can still do that while sticking to
>>> the "rel is for relationships" pattern.
>>>
>>> Cheers.
>>>
>>>
>>>
>>> mamund
>>> +1.859.757.1449
>>> skype: mca.amundsen
>>> http://amundsen.com/blog/
>>> http://twitter.com/mamund
>>> https://github.com/mamund
>>> http://www.linkedin.com/in/mamund
>>>
>>>
>>> On Sat, Nov 9, 2013 at 12:59 PM, Philippe Marsteau <[email protected]>wrote:
>>>
>>>> I see 2 distinct purposes of link relations: either to qualified a
>>>> transition from one state to another of the resource, or to describe how
>>>> two resources relate one to another.
>>>>
>>>> This discussion I think focused on the latter. I am specifically
>>>> curious of best practices for the former case, when a RESTful API aims at
>>>> letting consumer work through a specific workflow (eg. buying a book
>>>> online).
>>>>
>>>> I thought the best practice was to let user land ton an entry point
>>>> resource (eg collection of books) and then let user evolve in the workflow:
>>>> first by affording user to initiate the workflow (eg. "rel=buy" which
>>>> likely translates with GETing a "buy-a-book-form" resource, letting user
>>>> discover which inputs are need to start the workflow). Then subsequently,
>>>> each step in the workflow will afford user to confirm an order, select
>>>> payment information, shipping details... Ultimately the server will confirm
>>>> creation of an order resource (and maybe  provide a shipment resource
>>>> allowing user to track shipping status or to cancel order, etc.)
>>>>
>>>> In such typical workflow scenario, is it a bad practice to expose rels
>>>> as "actions" (thus verbs)? I think of having server sending relevant
>>>> actions on each step (as part of resource representations), letting user
>>>> discover HTTP methods and target resource to interact with as a result of
>>>> activating the hypermedia control (action).
>>>>
>>>> In the example of AtomPub, we have a similar hypermedia control "edit"
>>>> (verb) to afford atom consumer a given feed entry can be edited. Which
>>>> translate with a PUT to the target href (the target feed entry).
>>>>
>>>> In other words, what is the best practice to express hypermedia actions
>>>> in a RESTful way, to allow consumer to control the workflow while the
>>>> server controls the affordances of the user (based on internal application
>>>> state)?
>>>>
>>>> Phil
>>>>
>>>> Le 8 nov. 2013 à 02:58, Mike Kelly <[email protected]> a écrit :
>>>>
>>>>
>>>>
>>>> On Fri, Nov 8, 2013 at 1:31 AM, Jan Algermissen
>>>> <[email protected]> wrote:
>>>> > Hi Mike,
>>>> >
>>>> > On 08.11.2013, at 02:08, mike amundsen <[email protected]> wrote:
>>>> >
>>>> >>
>>>> >> not sure i understand the Q, but i'll offer this:
>>>> >>
>>>> >> rel="http://example.com/rels/publisher" describes the relationship
>>>> between the source and the target.
>>>> >>
>>>> >
>>>> > I like to try to emphasize what the target is *to the source* with
>>>> the goal that the application-level effect of the HTTP methods falls into
>>>> place.
>>>> >
>>>> > This IMO helps a great deal with avoiding to layer specialized
>>>> application protocols on top of HTTP (which already is the application
>>>> protocol).
>>>> >
>>>> > IOW, it helps prevent redefinitions of the meaning of HTTP methods.
>>>> POST means POST, it cannot mean 'publish the source resource'. DELETE means
>>>> DELETE, it cannot mean 'unpublish the the source resource'.
>>>> >
>>>>
>>>> Well, those methods have a general meaning within the uniform
>>>> interface of HTTP whose purpose is to add to the self-descriptiveness
>>>> of messages and, in doing so, to afford intermediation across the
>>>> system (e.g. web caching). The HTTP method definitions attribute
>>>> meaning designed for this purpose (e.g. establishing safety,
>>>> idempotency, cacheability, etc).
>>>>
>>>> Provided the link relations are not in conflict with the HTTP
>>>> definitions, and are merely qualifying the details of methods within
>>>> the context of a given transition, then it is wrong to think about
>>>> that in terms of "redefinition". It's qualification.
>>>>
>>>> In practice, it's much easier for consuming parties if your
>>>> documentation is specific by providing an explicit description of the
>>>> meaning and structure of the various requests possible over a given
>>>> link. Leaving your documentation so abstract that the reader is left
>>>> with the task of inferring every part of each possible request does
>>>> not seem like a very pragmatic approach for custom link relations (but
>>>> may be more appropriate for standardised link relations).
>>>>
>>>> > If you find yourself in a situation that you absolutely must tell the
>>>> client developer this, rephrase the hypermedia semantic (here: the link rel
>>>> spec).
>>>> >
>>>> > There is nothing to say againts hints regarding the intended
>>>> 'canonical' use case but I can always only be a hint. AtomPub is an
>>>> example, where the spec tells us so much about the interactions between
>>>> client and server that it looks like a protocol when it is actually only
>>>> hints about a canonical application flow. Focussing on resource semantics
>>>> would have been much nicer, IMHO.
>>>> >
>>>> > One simply cannot constrain HTTP servers that way and still have REST.
>>>> >
>>>>
>>>> The importance of HTTP methods from a REST point of view is that they
>>>> create **some** visibility of the client server interactions, so that
>>>> the messages can be understood to _a certain extent_ by
>>>> intermediaries. Provided that visibility is not impacted (i.e. a link
>>>> rel's qualification of a method doesn't _conflict_ with HTTP's) then
>>>> how does this have any bearing on the "RESTfulness" of the
>>>> application?
>>>>
>>>> Cheers,
>>>> M
>>>>  
>>>>
>>>>
>>>
>>
>