[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [rest-practices] Modelling membership



So, by not having it toplevel, what we're thinking is equivalent to:

 POST /users/1234/memberships

 <membership>
   <group id="4321"/>
 </membership>

Generally speaking, I'd rather see hrefs instead of IDs:

  <group href="${url_to_group}"/>

I don't like this partial in-lined description of a <membership> resource, though, as then I have to keep up with user_id separately, it's not a part of the representation when fetched this way. It's easier to code if I know I can resolve a URL to fetch a complete object, instead of having to considering it within some context. Particularly if we're ignoring URL structure and being HATEOASishy.

Depending on how "pure" you wanted to be, I might also do

<memberships>
  <membership href="${url1}"/>
  <membership href="${url2}"/>
</memberships>

And treat it as a collection of references. This is what I mean by a "top-level" object. One that is directly accessible with a discrete URL. Here, though, we look at N+1 fetches, or some extra way to inline the results or fetch-all in a single operation. (Both seem reasonable).

Versus a "value" object, which is purely embedded within another object, and not directly referenceable.

If you embed as a value, then I think you make sure it's not accessible, since it's more just an internal structure to the owning object.

In this case, perhaps embedded value is the way to go, in which case, purely the following, where the only href/URL points to the referenced group:

<memberships>
  <membership>
    <group href="${group_url}"/>
  </membership>
</membership>

Here, you don't have to repeat user_id, since context is implicit and mandatory, as we're embedded within the <user> object. But then we're back to the race condition of multiple updates to a single url to add/ remove groups. But that is orthogonol, and affects all fields on all resources. We just happen to think it might be triggered on this one with high probability.

Perhaps time to think about optimistic locking, and a <version> serial number or timestamp on all resources, to allow the server to perform reasonable optimistic locking.

We'll also make the membership list available read-only via the group:

 GET /groups/4321

 <group id="4321">
   <name>foo</name>
   ...
   <memberships>
     <link rel="membership" href="/users/1234/memberships/1111"/>
     ...
   </memberships>
 </group>

Though, does a group have memberships? Or does it have members? A "membership" seems to be a management/structural object from User perspective, but not necessarily from the group perspective, especially if it's just referencing it in a read-only fashion.

I'd suggest:

<group>
  <name>foo</name>
  <members>
    <user href="${user_url1}"/>
    <user href="${user_url2}"/>
    ..
  </members>
</group>

In this case, we're reducing the number of fetches to obtain a list of all members of a group. Having to bounce through a membership reference means 2N+1, where at least this way it's only N+1. Same inline/fetch-all notes from above may then apply to optimise some more.

What an amazingly deep topic. :)

	-Bob








[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]