Skip to content

Instantly share code, notes, and snippets.

@mattknox
Forked from idibidiart/GraphQL-Architecture.md
Created April 21, 2017 21:32
Show Gist options
  • Select an option

  • Save mattknox/69bfd7fc1bcb668615e8b329b8e0cac7 to your computer and use it in GitHub Desktop.

Select an option

Save mattknox/69bfd7fc1bcb668615e8b329b8e0cac7 to your computer and use it in GitHub Desktop.
Building an Agile, Maintainable Architecture with GraphQL

Building an Agile, Maintainable Architecture with GraphQL

A maintainable application architecture requires that the UI only contain the rendering logic and execute queries and mutations against the underlying data model on the server. A maintainable architecture must not contain any client-side logic for deriving/constructing app state, as either would necessarily embed business logic in the client, and app state should be derived from the server.

GraphQL allows us to do that by defining an application-level, UI-agnostic schema on the server that captures the types and relationships in our data, and wiring it to data sources via resolvers that leverage our db's own query language or existing APIs to resolve client-defined "queries" and "mutations" against the schema.

With each component in the UI component tree declaring its own data dependencies, GraphQL creates a projection of our data on the server that maps directly to the UI component tree. GraphQL allow us to have an application-level, UI-agnostic model of our data on the server, while at the same time giving us and UI-specific projection of the current app state on the client.

Given the UI's data dependencies are specified declaratively, the front end developer's job becomes a much more pleasant task of building the application-level, UI-agnostic GraphQL schema, building UI components and declaratively specifying the required queries and mutations.

Client-based architectures (aka shallow architectures) like Redux, MobX, et al derive/construct app state on the server, and as such end up embedding business logic in the client. While those architectures enable things like 'optimistic UI' and 'offline first' apps they necessarily lead to the creation of fat clients and the dispersion and replication of business logic across UI and backend, which doubles (if not exponentially complicates) the work involved in maintaining and evolving the application.

![graphql] (http://imgur.com/a/ccpiF)

Current Challenges and Considerations

  1.   Avoid business logic in the client: “app state” should not be derived/constructed on the client, as that leaks business logic into the UI and leads to cache-invalidation type challenges which add a lot of unneeded complexity to the app. The UI needs to be just an I/O layer, fetching/re-fetching UI-component-bound query results and making mutations to data on the server, leveraging an application-level, UI-agnostic schema on the server. In this state-free, functional UI model, local component state (including local state of higher order components) is used for ephemeral client-only state like animation state. We avoid deriving/constructing app state on the client because that ultimately leads to cache invalidation challenges, not to mention embedding business logic in the UI, both of which greatly complicate things. Instead, we opt to simply refetch UI-component-bound query results either via component-bound subscriptions or polling (with ability to force updates on immediate basis) and let UI components derive their own state from the server based on bound query results. We also refetch query results immediately (for all components that are mounted) when we mutate something on the server. The business logic stays on the server and the UI developer's job becomes ver simple. 
    
  2.   The need for pre-mutation hooks: we need to be able to validate data before executing a mutation (and conditionally avoiding the mutation) so we can implement validation or sanitation on the server and leave business logic completely outside the client. We also need post-mutation hooks to make calls to APIs that must be called after a given mutation. 
    
  3.   The need for live data subscription that perform well at scale: when something changes on the server, we need to know about it, either via polling or subscriptions. The latter has the advantage of being immediate.
    
  4.   Currently, GraphQL developers need to know many different querying syntaxes for the various resolvers in the schema (MySQL, MongoDB, different APIs, etc), or write their own API adapters for each data store to make their connectors consistent. This can be a lot of work and a number of thoughtful design choices must be made for this to work well.
    
  5.   We should be able to implement secure authentication using OAuth and Email/Password.
    
  6.   We should be able to implement permissions independent of our database or network interface.
    
  7.   We should be able to break the business logic into microservices when/as needed.
    

###References

  1. [Building a GraphQL Server with Node.js and SQL] (https://www.reindex.io/blog/building-a-graphql-server-with-node-js-and-sql/)

More coming soon...

###Updated 1:

(after a Twitter chat with @en_JS (Joseph Savona), one of the GraphQL/Relay developers at Facebook)

Any app state that is not sync'd to the db is not something that Relay encompasses right now, but there is an ongoing [discussion] (facebook/relay#114) for handling scenarios like client-side form validation and state updates from sources other than the db (e.g. websocket)

These important scenarios will be addressed according to the Relay Roadmap (https://github.com/facebook/relay/wiki/Roadmap):

  1. API for resolving fields locally: #431.

  2. Support querying & compiling client-only fields by extending the server schema, and a means for writing data for these fields into the cache: #114.

###Update 2:

@gaearon (Dan Abramov), author of Redux, was gracious enough to tweet this, and I give him a lot of credit for doing so.

Here is a section of the very long conversation that Dan started:

![twitter conversation] (http://i.imgur.com/BD2Wu5m.png)

###Update 3:

My follow up conversation with Dan Abrahmov below

![twitter follow up] (http://i.imgur.com/43lsGJo.png)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment