17

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:

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.

Dan Narsavage
  • 325
  • 3
  • 13

1 Answers1

7

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.

Joundill
  • 6,828
  • 12
  • 36
  • 50
Alucardz
  • 528
  • 4
  • 11
  • 1
    My question was aimed specifically at your scenario #1, in which clients talk directly to the GraphQL endpoint. It asks whether it is acceptable in such a scenario to expose a series of flat classes and to use GraphQL to allow clients to pick & choose which classes (and properties thereof) they care to retrieve. I think what your answer is suggesting is that, yes, that's okay. Am I reading things correctly? – Dan Narsavage Mar 18 '19 at 21:32
  • 1
    Yes you read things correctly! It's perfectly ok and falls in line with good domain modeling (having DTOs or the equivalent) – Alucardz Mar 18 '19 at 21:55