HomeAbout

Architectural Layer

Principle

Domain Service method should not be tightly coupled with another domain's service or repository.

  • Should be injected

When structuring a return shape of a resolver, avoid coupling multiple methods or bundling return in a single field:

  • Should instead be called as a dedicated field in the resolver layer.

Architectural Layer

API schema and database schemas are decoupled within GraphQL architecture.

  • e.g. resolver can be used to create a missing country field on an address schema even when it is missing in the database.

This is why a type can transform across the layers in the architecture.

  • e.g. type on client layer is different than on the server layer.
  • This is why you can also call multiple resources from a single graph (e.g. DB can be SQL, NoSQL, someArbitraryDbTech).

At times, even data layer types and server layer types may be different for the same field

  • e.g. SQL has a dedicated uuid type while server would interpret it just as a string type
  • This would require a type to be "transformed" to be layer-compatible

Data to Service Layer

When the data is pulled as a response to a request, it first gets pulled from the database to the repository layer

  • The repository layer should mirror the DB Schema because we're simply pulling the data-layer into the server layer at this step

Repository layer method is then called by the service layer method

  • Service layer should scope strictly to the service method as a unit
    • Meaning, the service method should return data shape that is compliant to the service layer.

Service layer should NOT do everything needed to fulfill the graphql schema expectations

  • This is a role of the resolver

Within the Service Layer

Shape the return shape in the resolver, not in other parts of the service layer

When you need to define a graph connection of a field, you must do this in the resolver layer

  • You DO NOT define this in the server layer
  • You HAVE to define it in the resolver layer

If you don't place the relationships in the resolver layer, you are violating domain boundary and entangling the relationship in domain definition, not based on return

  • you will also have a tough time typing the return shape on a service and multiple service calls will get tangled in a single service method.
    • "service layer trying to do much"
  • By resolving the field relationships at the resolver, the field relationships are split to each fields and a single service method is called for a single relationship (keeping a single version/integrity of a service method unless another method is defined)
    • Especially when using a codegen on gql, generated types would need to be heavily manipulated when it is used to cater multiple
// resolver return shape { primitiveField1: UUID, primitiveField2: number, // return type of service1.getMethod relationshipField1: service1.getMethod(), // return type of service2.getMethod relationshipField2: service2.getMethod() }
AboutContact