loading...
Cover image for Questioning GraphQL's Fragments

Questioning GraphQL's Fragments

chiefgui profile image Guilherme Oderdenge ・5 min read

I dare to say that 70% of my career I spent living together with REST, but barely can remember of it and its good practices. I remember we had standards; I remember we had routes; I remember there was a distinction between REST and RESTful. The most iconic thing I remember is that we had requests returning huge amounts of fields and the major part of those were oftentimes needless. Then GraphQL came around.

GraphQL's logo in purple

I bluntly fell in love at the first stare it gave me. What a time to be alive, huh?

Thing is, as someone who worked in a daily basis with REST, doing the migration was not seamless. New concepts, several different new keywords, good practices peeking around the corner. It was not only a new MVC framework—it was a whole different and modern mentality.

Back then, before getting my hands dirty, I spent hours reading and skimming articles. Queries, mutations, fragments, resolvers, etc. When I felt I was too confused, just gave up with the formal education and picked Relay's "Quick" Start guide to see the thing in practice.

So I started learning GraphQL in the front-end. Mostly, what we had there—and still have—were Queries and Mutations. These two—specially Queries—were easy to tame. However, one thing I skipped completely was Fragments. The truth is that was naive from me doing so because, nowadays, it's clear it is a core mechanism the technology has to offer.

There is one fundamental piece on my naiveness: I started working with GraphQL in a daily basis and meanwhile skipping and ignoring Fragments the entire time. Back to my first reading on GraphQL, I skipped Fragments because "oh, alright, I'll check it out later", but this "later" ended up meaning years.

The photograph of a cute Squirrel staring at the camera, being held by a human hand

Year is 2019. Now with some experience in GraphQL, I decided to create a "serious" pet project, and those who, like me, fantasise serious pet projects, they go wild when it comes to programming seriousness. I'm serious.

Picture this: a developer in front of his computer running yarn add non-stop, setting up all the foundation for his next big venture. I mean, pursuing the codebase that would make Facebook envy. C'mon, who never?

Anyways, time to get even more serious about GraphQL and expand my knowledge further.

Sat down in my computer and spent hours on some serious (lol), deep reading. This time no skim. Suddenly, I got to it: Fragments. I remember it was an Apollo page (maybe this one).

Cool, you can easily reuse pieces of your Queries out and about
My younger self thought

Before reading that page and diving deep into it, what I imagined about Fragments is that its function would go beyond merely serving as variables to hold fields one want to use in different Queries. Hence I imagined it was a way to reuse the values of those fields that were returned from the data of a real query. In other words, I fantasised that Fragments was a kind of cache.

But then, after the reading I mentioned earlier, the quote of myself above became my new axiom. It's literally just a DRY; developer sugar. And please, don't get me wrong—that's not bad at all.

Turns out that when I realised that, frustration and relief occurred to me at the same time. Frustration because my imagination was completely wrong; relief because I could achieve GraphQL without Fragments.

Bringing the climax to the table, in this serious project of mine, I experimented Fragments a little bit. At first, I felt the productivity at my fingertips and thought how I survived all this time without it, however it didn't take long to show up some bleedings.

To give you some easy-to-digest examples, these are a few things that happened to me:

  1. Different Fragments for the same fields;
  2. The need to open the file the Fragment was to confer its fields (slowing me down);
  3. The need to search within my codebase to check if a Fragment for a given batch of fields already existed.

That started to piss me off. My loss on productivity was concrete, I could more than see it; I could feel it.

The cherry on the cake was that Fragments made me feel I was doing wrong GraphQL. Not technically, but theoretically.

A picture with an abstracted shape

It's easy to agree that the greatest achievement of GraphQL, at least compared to REST, is that it allows you to explicitly request exactly what you want when performing a request. You don't GET /users and just accept whatever the response gives you. You are free to nitpick only the fields that make sense to that specific situation.

So let's take this example from the official GraphQL documentation:

{
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }
}

fragment comparisonFields on Character {
  name
  appearsIn
  friends {
    name
  }
}

This seems to be the perfect use case for Fragments. And, in fact, it is. But reality isn't always that kind with us. Because, for some reason, the PO wants the leftComparison and only the leftComparison to show something like the "flag" of the hero.

In your day-to-day, with lots of tasks piled in your backlog, one natural and quick fix for that would be doing this:

fragment comparisonFields on Character {
  name
  appearsIn
  flag # here
  friends {
    name
  }
}

And boom! You can now access data.leftComparison.flag and do whatever you want with it.

However, this "quick fix", which I doubt that would be something rare for one to do, comes at a cost: we are also retrieving flag to the rightComparison, and that particular hero doesn't need it. Of course, flag might be cheap to query and may not bother the bandwidth of your customers and users, but it definitely breaks the most fundamental principle of GraphQL that is just ask for what you need.

This also happened to me. I was using some Fragments to share common fields and in these queries I implemented them were oftentimes requesting unneeded stuff.

The ironic conclusion I took about this situation is that GraphQL has a functionality prone to diverge from itself. Fragments seems to me an innocent, induced solution to avoid repetition brought by the Facebook team, capable of sneakily implode an anti-pattern in our requests, codebase and whatnot; I feel that those unsuspecting, unaware programmers could easily get caught on doing REST through GraphQL without any acknowledgement or consciousness.

To overcome my problems then, I left Fragments behind and started CTRL+Cing and CTRL+Ving instead. Pure redundancy and repeating myself. Cheap solution. Explicit versus implicit. One less abstraction and needless complexity to worry about.

But I want to state a few things before wrapping up. Starting with the fact that I'm not saying don't use Fragments or Fragments is crap, please Facebook remove it from GraphQL.

I'm saying that I have the impression it can be harmful depending on how you use it, where harmful might mean flag could be an expensive field to query for; or harmful might mean it could damage your developer experience, slowing you down.

Secondly, I haven't used Fragments for long, nor in massive scale projects. That said, perhaps I could have misunderstood it or may be lacking the ideal experience to make it profit. Or maybe I'm simply using it wrong. Worth to mention I really tried. And I really wanted to use it the right way.

Thirdly, Fragments do you any good? Alright, go for it! It's there to be used.


Now, don't be shy—share your thoughts. Have you had a bad experience with Fragments as well? Or a good one? The microphone is all yours.

Peace.

Discussion

markdown guide