Update description of Fragments to emphasize evolving data needs
Why these changes?
Fragments are not for reuse.
The current language in section 2.8 on Fragments, namely the sentence...
Fragments allow for the reuse of common repeated selections of fields, reducing duplicated text in the document.
...encourages using fragments to deduplicate common selections, even if those selections represent independent data needs.
For example, let's consider these two functions
// This function formats a post for display in a feed
func formatPostForFeed(post: PostDisplayFragment) -> String {
let authorName = post.author.name
let contentText = post.content.text
return "\(authorName) posted: \(contentText)"
}
// This function formats a post for notification purposes
func formatPostForNotification(post: PostDisplayFragment) -> String {
let authorName = post.author.name
let contentText = post.content.text
return "New post from \(authorName): \(contentText)"
}
Given these two functions currently both use authorName and contentText, the current language in the spec encourages one to write a fragment
fragment PostDisplayFragment on Post {
author
content
}
If formatPostForFeed now needs timestamp, we will add naturally add timestamp to PostDisplayFragment
// This function formats a post for display in a feed
func formatPostForFeed(post: PostDisplayFragment) -> String {
let authorName = post.author.name
let contentText = post.content.text
let timestamp = post.createdAt.formatted // Added
return "\(authorName) posted: \(contentText)\nPosted \(timestamp)"
}
fragment PostDisplayFragment on Post {
author
content
timestamp # Added
}
If we have the following queries
query NotificationQuery {
...PostDisplayFragment # Over-fetching timestamp
}
query FeedQuery {
...PostDisplayFragment
}
notice how NotificationQuery is now over-fetching timestamp!
The key observation is that formatPostForFeed and formatPostForNotification are two independent functions, so by having them both rely on a single fragment to express their data needs, we are creating a dependency where one should not exist (because that dependency does not exist in the product logic itself).
What are the proposed changes?
Updated:
- The description for why one might use fragments
- The first GraphQL example in section 2.8
The goal is to emphasize that fragments support evolving data needs (as opposed to recommending people identify common selections that are currently in an executable document).
Open to any and all feedback on the motivation for the change and how it's communicated via changes in the spec language!
Deploy Preview for graphql-spec-draft ready!
| Name | Link |
|---|---|
| Latest commit | df32811fe9141d99f047079df7272e5d5ce438e9 |
| Latest deploy log | https://app.netlify.com/projects/graphql-spec-draft/deploys/68e935b26f2fc70008bffb5d |
| Deploy Preview | https://deploy-preview-1193--graphql-spec-draft.netlify.app |
| Preview on mobile | Toggle QR Code...Use your smartphone camera to open QR code link. |
To edit notification comments on pull requests, go to your Netlify project configuration.
Definitely agree on the motivation for this change; thanks for the submission Janette!
I think that is is great change overall. The challenge is a bit to make it understandable in the context of the spec.
Using fragments to declare data needs (like in relay) always requires something on top of the spec to make it work. So we would have to make this clear somehow.
Just updated based off some of the feedback from the working group meeting!
- Removed the word modular and opted for something more prescriptive based on people's suggestions ("should declare its data needs in a dedicated fragment"). Let me know if "should" is too strong here (I think it makes sense based off this guidance, but open to discussion!)
- Instead of referencing a function
friendProfile, use prose as suggested by @benjie
The video is just out. Can we merge this and iterate on the wording if needed. I'd love the message to be consistent.
Each data-consuming component (function, class, UI element, and so on) ...
I like this! The spec should be as framework and implementation agnostic as possible
Perhaps we could lay out the entire scenario showing multi-level composition?
Yes! This is great. I'm hearing from our users (RedwoodJS/CedarJS) that fragments are seen as a very advanced concept. A full example like this really helps. Maybe the text could be even clearer with the fact that it's entirely natural for a component having to include both the "code definition" (i.e. function signature) and the "data definition" (i.e. fragment) of any children it wants to render.
(And when this change lands, I'll definitely have to update the Cedar docs on fragments)
I don't know how Lee feels about using _ in fragment names,
Would like to keep examples camel case in the spec