8000 Attributes of relationships #415 by hhware · Pull Request #431 · json-api/json-api · GitHub
[go: up one dir, main page]

Skip to content

Attributes of relationships #415 #431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

hhware
Copy link
Contributor
@hhware hhware commented Mar 8, 2015

Resolves: #415

@dgeb
Copy link
Member
dgeb commented Mar 8, 2015

@hhware Thanks for working up this PR in time for consideration.

I personally don't agree with this blurring of lines between resources and relationships. In my opinion, this adds a lot of complexity for little benefit. If relationships are allowed to have attributes, then the spec will need to provide a means to edit those attributes (PATCH I suppose). Furthermore, it will create dissonance for API designers who need to decide between creating resources vs. "complex relationships".

@dgeb dgeb added this to the 1.0 milestone Mar 8, 2015
@dgeb
Copy link
Member
dgeb commented Mar 8, 2015

Moving to 1.0 milestone.

@wycats @steveklabnik are either of you in favor?

@hhware
Copy link
Contributor Author
hhware commented Mar 8, 2015

@dgeb, thanks for reviewing it!

then the spec will need to provide a means to edit those attributes (PATCH I suppose)

It is addressed by this PR

I personally don't agree with this blurring of lines between resources and relationships. In my opinion, this adds a lot of complexity for little benefit... Furthermore, it will create dissonance for API designers who need to decide between creating resources vs. "complex relationships".

IMHO, this "blurring" can be viewed as an intrinsic feature of some real-life systems, which have objects which are "in between" resources and links, but much closer to links. As for the "dissonance", it could indeed be a dissonance to some, but longed-for flexibility to others. There is always a balance between rigidity and flexibility, and I think it would in the spirit of JSON API to be more on a rigid side of things, but not entirely rigid. In my view, allowing simple attributes of relationships is 90% of rigidity and 10% of flexibility.

Let me elaborate more with two examples.

First one extends the filesystem example from #415. Imagine a CMS-like system (this is the case which I personally care about), consisting of a tree of containers, which can contain either some objects or other containers. A container with all its content can be referred to from another container (to allow people share content without copying it). The difference from the filesystem example is that there is more than one types of such references (to allow different approach to sharing, either with read-only rights, with some admin rights, etc.) Surely, each of this types of sharing links can be represented as an object of its own, necessitating several types of such objects and complexity associated with that, but it would be very convenient for the API designer to hide this complexity and simplify life for himself and for the API consumers by abstracting this as a relationship with just one attribute (type of the link). I wish JSON API allowed to do that.

Second one is some modification of audit-like example from #415. Suppose some endpoints of an API represent some committees, and other endpoints of that API represent people, who are members of these committees. People move from one committee to another over time, which can be reflected by joined_at / left_at timestamp attributes of the relationships. It would be easy to represent the history of each committee over time this way, showing when each member joined and when she left. I think it is a perfect abstraction if the API is only concerned with such superficial representation of the situation. If the API needs to deal with the particulars of the processes of joining / leaving of members, the API designer could opt for resources for them, which would allow him to represent details of running for membership, voting for it, etc. Is it a dissonance? I would say it is a reasonable freedom of expression, and I wish JSON API allowed it.

Last but not least, meta of relationships can be very useful for reporting computed data about them, e.g., some statistics, which can only be returned by GET, but is never stored by POST / PUT / PATCH.

@tkellen
Copy link
Member
tkellen commented Mar 8, 2015

@hhware Would you be willing to mock up a set of example requests/payloads showing how you'd accomplish your desired interaction within the constraints of json-api now, and a companion set within the constraints you are proposing?

I think it would be very helpful to see them side by side.

@tkellen
Copy link
Member
tkellen commented Mar 8, 2015

This change is additive and can be considered post 1.0. I'm going to pull it from the milestone.

@tkellen tkellen removed this from the 1.0 milestone Mar 8, 2015
@hhware
Copy link
Contributor Author
hhware commented Mar 8, 2015

@tkellen Definitely, I will.

@hhware hhware force-pushed the i415-attributes-of-to-many-relationships branch from ac5423d to b0f0231 Compare March 29, 2015 14:34
hhware added a commit to hhware/json-api that referenced this pull request Mar 29, 2015
@tkellen
Copy link
Member
tkellen commented Apr 6, 2015

@hhware Are you still willing to provide examples for this? If so, is there any chance you could do so this week? We are planning on doing a group review in the very near term and I would love to have them as a reference so we can consider this carefully.

hhware added a commit to hhware/json-api that referenced this pull request Apr 7, 2015
@hhware hhware force-pushed the i415-attributes-of-to-many-relationships branch from b0f0231 to 7aca000 Compare April 7, 2015 05:55
hhware added a commit to hhware/json-api that referenced this pull request Apr 7, 2015
@hhware
8000 Copy link
Contributor Author
hhware commented Apr 7, 2015

Are you still willing to provide examples for this?

@tkellen, yes, I have been working on this PR and examples for the last few weeks, time permitting. I guess it's finally time to let it go :)

@dgeb, @tkellen, I very much appreciate your time and interest in reviewing my earlier posts on this topic. I reworked and significantly simplified this proposal to account for the discussion.

@lsylvester, I would appreciate your opinion on whether this satisfies your expectations wrt attributes of relationships.

Structure of this PR

This PR is split into several commits for convenience of reviewers:

  1. the substance of the proposal,
  2. terminology updates and formatting changes,
  3. optional improvements (sparse fieldsets, sorting, meta).

The 4th commit is the example, it can be viewed in readable form here.

Key points

I think the PR now articulates the goals and limitations of the proposed changes much better than before. In particular, I would like to emphasize the following points:

  1. The line between resources and relationships is much less blurred in this version compared to the previous one.
  2. It was targeted at to-many relationships before, now it includes to-one relationships because it is more consistent. It does not seem to conflict with anything: e.g., if an API backed by RDBMS wants to provide to-one relationship with attributes, it can store them in a join table with appropriate UNIQUE indices.
  3. The main difference between resources and "complex relationships" is that while resources can have their own types and can be referred to by type/id, relationships do not have their own type/id and cannot be referred to by them. I believe this is the reason why there should be no "dissonance": relationships can never compete with resources because they are only auxiliary entities, exactly the same as in the current spec.
  4. Another difference between resources and relationships is that the latter cannot have links.
  5. Answering the comment of @dgeb: there is simply no need to provide methods for updating attributes of relationships: if such attribute has to be changed, the corresponding relationship can be deleted and created from scratch, just like it is done in the current spec.
  6. The only similarity between resources and relationships is that both allow arbitrary attribute members (and meta, in the optional part).
  7. The spec is updated so that the word "attribute" is never used alone, it is always either "resource attribute" or "relationship attribute" (primarily in the terminology part).
  8. Not sure whether there is any practical use in allowing complex attributes of relationships, but I think it is more consistent to keep limitations on attributes of resources and attributes of relationships identical.
  9. Suggestions are made on incorporating relationship attributes into sparse fieldsets and sort requests. Suggestion on sorting could have its merits even without relationship attributes. I will open a new issue on it if it does not go through as part of this PR.
  10. For the purposes of pushing this PR forward, I tried to update as little as necessary. In particular, examples became less convincing after my changes, they should probably be replaced altogether.
  11. In this PR, most of GET examples do not illustrate attributes of relationships, but the "complete example document with multiple included relationships" does. To the contrary, a good portion of POST/PATCH examples do illustrate them. The primary reason for this discrepancy is that there is no "complete example document" for POST/PATCH.
  12. I expect that one common use case of this would be ordered relationships (touched in Ordering of primary data #473). In RDBMS setting, a to-many relationship can be stored with an additional column, e.g., order_number INT. Relationships in the spec have semantics of sets, so one way of addressing this question could be support of totally ordered sets, but then a mechanism to distinguish sets from totally ordered sets would be required. This will likely bring a lot of confusion since in most cases relationships are not ordered. Support for relationship attributes removes the issue: order can be explicitly communicated and sorting by it can be supported.

Milestoning

I am well aware that the official position is to postpone additive changes until post 1.0. While some additive changes are mere optimizations with available workarounds (e.g., #477), I think it would be appropriate to consider this one for 1.0 because it modifies one of the core concepts of the spec. If relationship attributes were proposed post 1.0 and then accepted, then obviosuly implementors of libraries would have to deal with them as with additive change. As @steveklabnik put: "I can appreciate frustration with changes, we are making them now, so that we can not make them in the future" -- I think it absolutely applies to the particular change proposed here.

Another reason to consider this now is that this change is additive for the JSON API spec and its generic implementations, but it will not be additive for specific JSON-API-compliant APIs which could make use of this feature. They will rarely be able to afford a luxury of switching from relationships-as-entities to relationships-with-attributes because it is a backward-incompatible change for an API. Implementors of such APIs make choices on API design and then stick to them. Even if this feature becomes availabe in JSON API 1.X, APIs implemented before that would not be able just to "add" it, the way the spec and libraries can. Obviously, some people are waiting for 1.0 to start using JSON API or to consider it "for real" because of stability expectations -- it is not unreasonable to expect that after 2 years of preparations for 1.0, the core concepts of the spec will remain stable for a while.

Commit "substance" is what I believe has to be considered for 1.0. Commit "terminology" would be useful in 1.0 too, but the main reason I provide it here is to avoid rejection of the proposal because of misunderstandings of terminology (the commits are non-overlapping though, so some terminology changes have leaked into other commits as well). Commit "optional" is not blocking for 1.0, but provided here to complete the picture.

Examples

Two alternatives to relationship attributes have been suggested in discussions in #415 and here:

  1. make relationships heterogeneous, with value of type incorporating the attribute(s),
  2. disguise relationships as resources.

After having a closer look, I realized that I do not even understand how the first option can be implemented. But even if it could be, I think it is not a workable solution for the following reasons:

  1. it pollutes type system with multitude of technical entities, creating complexity out of nowhere,
  2. it is impractical for relationships with multiple attributes -- number of types will grow in geometrical progression,
  3. it is impractical for relationships attributes which can be represented as ENUMs with large number of members for the same reason,
  4. it is inapplicable to relationship attributes which cannot be represented as ENUMs, e.g., which have numeric values.

So I skip the first option and compare the second one to the proposed solution here. If these examples are unclear or need improvement, please let me know, so I could update them.

For completeness sake, other alternatives also exists: define an extension or simply handle these attributes within meta. However, these alternatives produce less portable APIs, which defeats the purpose of following JSON API spec.

@hhware hhware changed the title Attributes of to-many relationships #415 Attributes of relationships #415 Apr 7, 2015
@hhware hhware mentioned this pull request Apr 7, 2015
@lsylvester
Copy link

@hhware For my purposes, I wanted to embed information about the linked resource without having to include the linked resource, so the information wasn't particular to the association.

The reason for this was to be able to invalidated locally cached resources.

I think for my use case, the best approach would be to allow for meta in the linkage objects, which is included in this PR, but I do not require the relation attributes which are the main feature of this PR.

Updated on 4/7/15: added the following:
> Linkage objects **MUST** reserve `"links"` member for future use.
@hhware hhware force-pushed the i415-attributes-of-to-many-relationships branch from 7aca000 to 51bb65a Compare April 8, 2015 04:41
@hhware
Copy link
Contributor Author
hhware commented Apr 8, 2015

Made a minor update, left a note in the message of the corresponding commit (to preserve PR structure).

@steveklabnik
Copy link
Contributor

In my opinion, this adds a lot of complexity for little benefit.

Ultimately, this is my thought as well. I've read through these tickets (sorry for the delay, work is getting tough) but I don't understand why relationships need attributes. As soon as they do, they become resources in their own right, and don't need special casing.

@dgeb
Copy link
Member
dgeb commented Apr 14, 2015

We sincerely appreciate your effort here, @hhware. However, after consideration and discussion, @tkellen, @steveklabnik, and myself share the belief that relationships with attributes should become resources in their own right. This has been a tough call as we struggle to balance complexity and utility.

An edge case we should consider is the allowance of meta on linkage objects, as you and @lsylvester have mentioned.

Thanks again for all your work, @hhware.

@dgeb dgeb closed this Apr 14, 2015
@hhware hhware mentioned this pull request Apr 18, 2015
hhware added a commit to hhware/json-api that referenced this pull request May 4, 2015
@ethanresnick
Copy link
Member

/reffing #794, as the extension system should make something like this possible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Attributes of relationships
6 participants
0