Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does GraphQL obviate Data Transfer Objects?

Tags:

dto

graphql

To my understanding, Data Transfer Objects (DTOs) are typically smallish, flattish, behavior-less, serializable objects whose main advantage is ease of transport across networks.

GraphQL has the following facets:

  • encourages serving rich object graphs, which (in my head anyway) contradicts the "flattish" portion of DTOs,
  • lets clients choose exactly the data they want, which addresses the "smallish" portion,
  • returns JSON-esque objects, which addresses the "behavior-less" and "serializable" portions

Do GraphQL and the DTO pattern mutually exclude one another?

Here's what led to this question: We envision a microservices architecture with a gateway. I'm designing one API to fit into that architecture that will serve (among other things) geometries. In many (likely most) cases the geometries will not be useful to client applications, but they'll be critical in others so they must be served. However they're serialized, geometries can be big so giving clients the option to decline them can save lots of bandwidth. RESTful APIs that I've seen handling geometries do that by providing a "returnGeometry" parameter in the query string. I never felt entirely comfortable with that approach, and I initially envisioned serving a reasonably deep set of related/nested return objects many of which clients will elect to decline. All of that led me to consider a GraphQL interface. As the design has progressed, I've started considering flattening the output (either entirely or partially), which led me to consider the DTO pattern. So now I'm wondering if it would be best to flatten everything into DTOs and skip GraphQL (in favor of REST, I suppose?). I've considered a middle ground with DTOs served using GraphQL to let clients pick and choose the attributes they want on them, but I'm wondering if that's mixing patterns & technologies inappropriately.

like image 599
Fing Lixon Avatar asked Mar 27 '18 16:03

Fing Lixon


People also ask

How does GraphQL store data?

GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. GraphQL isn't tied to any specific database or storage engine and is instead backed by your existing code and data.

What is DTO in GraphQL?

In the last post, I mentioned the fact that DTOs (Data Transfer Objects) and GraphQL schemas serve a similar purpose; they create a strict abstraction layer that the client (web, mobile, or desktop apps) can rely on. This leaves backend services to merely figure out how to implement the data.

What is GraphQL used for?

GraphQL is designed to make APIs fast, flexible, and developer-friendly. It can even be deployed within an integrated development environment (IDE) known as GraphiQL. As an alternative to REST, GraphQL lets developers construct requests that pull data from multiple data sources in a single API call.

What is the point of a data transfer object?

A DTO is helpful whenever you need to group values in ad hoc structures for passing data around. From a pure design perspective, DTOs are a solution really close to perfection. DTOs help to further decouple presentation from the service layer and the domain model.


1 Answers

I think it's worthwhile differentiating between 2 typical use cases for GraphQL, and a hidden 3rd use case which combines the first two.

In all 3 however, the very nature of a GraphType is to selectively decide which fields you want to expose from your domain entity. Sounds familiar? It should, that's what a DTO is. GraphQL or not, you do not want to expose the 'password' field on your Users table for example, hence you need to hide it from your clients one way or another.

This is enabled by the fact that GraphQL doesn't make any assumptions about your persistence layer and gives you the tools to treat your input types / queries as you see fit.

1. GraphQL endpoint exposed directly to clients (e.g. web, mobile):

In this use case you'd use any GraphQL client to talk to your graphql endpoint directly. The DTOs here are the actual GraphType objects, and are structured depending on the Fields you added to your exposed GraphTypes.

Internally, you would use field resolvers to transform your DTO to your domain entity and then use your repository to persist it.

DTO transformation occurs inside the GraphType's Field resolver.

GraphQL --> DTO --> Domain Entity --> Data Store

2. REST endpoint exposed to clients, which internally consumes a GraphQL endpoint:

In this use case, your web and mobile clients are working with traditional DTOs via REST. The controllers however are connecting to an internally-exposed GraphQL endpoint - as opposed to use case #1 - whose GraphTypes are an exact mapping of your domain entities, password field included!

DTO transformation occurs in the controller before calling the endpoint.

DTO --> Domain Entity --> GraphQL --> Data Store

3. Combining 1 and 2

This is is a use case for when you're shifting your architecture from one to the other and you don't want to break things for client consumers, so you leave both options open and eventually decommission one of them.

Hope this helps!

like image 153
Alucardz Avatar answered Sep 29 '22 12:09

Alucardz