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
  • Save mattknox/69bfd7fc1bcb668615e8b329b8e0cac7 to your computer and use it in GitHub Desktop.
Save mattknox/69bfd7fc1bcb668615e8b329b8e0cac7 to your computer and use it in GitHub Desktop.

Revisions

  1. @idibidiart idibidiart revised this gist Apr 3, 2017. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -8,15 +8,15 @@ We use GraphQL to dynamically derive a UI-specific projection of app state from

    With this approach, the developer's job becomes a much more pleasant and simpler task of building the application-level GraphQL schema, building UI components and declaratively specifying the required queries and mutations.

    Client-centric architectures (like those based on client-side 'app state' stores) tend to cache and most often compose "app state" on the client, and as such end up either replicating business logic in the client or managing cache invalidation at granular level. While those architectures enable things like 'optimistic UI' and 'offline first' apps they can exponentially complicate the work involved in maintaining and evolving the application.
    Client-centric architectures (like those based on client-side 'app state' stores) tend to compose "app state" on the client, and as such end up replicating business logic in the client. While those architectures enable things like 'optimistic UI' and 'offline first' apps they can exponentially complicate the work involved in maintaining and evolving the application.

    ![GraphQL](https://s29.postimg.org/b7ifw7vc7/image1.png)

    ## Optimistic and Offline-First UI

    This meta-framework is designed for realtime, transactional apps (think: ordering & delivery and 'hard realtime' apps like Uber) In this context, what does it mean to tell the user that their order was successful or the driver is 2 mins away then finding out from server that the order cannot be fulfilled or the driver is stuck in traffic? This is to say that offline-first UI and optimistic UI are at odds with 'realtime' apps and present extra overhead of replicating app state and business logic in the client.
    This principles presented here are for realtime, transactional apps (think: ordering & delivery and 'hard realtime' apps like Uber) In the context of realtime apps, what does it mean to tell the user that their order was successful or the driver is 2 minutess away then finding out from server that the order cannot be fulfilled or the driver is stuck in traffic? This is to say that offline-first UI and optimistic UI are at odds with 'realtime' apps and present extra overhead of replicating app state and business logic in the client.

    So then the question is wouldn't losing Optimistic UI hurt mobile performance? The fact is that GraphQL already does a lot to help mobile performance by allowing us to get exactly the data we need at any given instance as opposed to dowloading more data than we need and putting it in the client side cache (aka client-side app state container) and complicating the app by having to manage app state on client and server instead of simply deriving it from server in real time.
    So then the question is wouldn't losing Optimistic UI hurt mobile performance? The fact is that GraphQL already does a lot to help mobile performance by allowing us to get exactly the data we need at any given instance as opposed to downloading more data than we need and putting it in the client side cache then having to keep all that data in sync with the server, which could be very challenging, especially if we compose app state on the client, which means that we have a lot of client derived state that depends on the cached data.

    ## Some Challenges and Considerations

  2. @idibidiart idibidiart revised this gist Mar 24, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    ## Building Maintainable, Agile Architecture for Realtime, Transactional Apps
    ## Building a Maintainable, Agile Architecture for Realtime, Transactional Apps

    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 logic for composing "app state" on the client as that would necessarily embed business logic in the client. App state should be persisted to the database and the client projection of it should be composed in the mid tier, and refreshed as mutations occur on the server (and after network interruption) for a highly interactive, realtime UX.

  3. @idibidiart idibidiart revised this gist Mar 24, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -52,12 +52,12 @@ Repo coming soon...

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

    ![twitter conversation] (http://i.imgur.com/BD2Wu5m.png)
    ![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)
    ![twitter follow up](http://i.imgur.com/43lsGJo.png)


  4. @idibidiart idibidiart revised this gist Mar 24, 2017. 1 changed file with 28 additions and 4 deletions.
    32 changes: 28 additions & 4 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -1,20 +1,44 @@
    ## Building Maintainable, Agile Architecture for Realtime, Transactional Apps

    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 logic for managing "app state" on the client (other than client-only state for generic input validation or animation which is encapsulated by individual UI components or HOCs), as either would necessarily embed business logic in the client and introduce cache invalidation challenges. App state should be derived directly from the server, and in realtime for highly interactive UX.
    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 logic for composing "app state" on the client as that would necessarily embed business logic in the client. App state should be persisted to the database and the client projection of it should be composed in the mid tier, and refreshed as mutations occur on the server (and after network interruption) for a highly interactive, realtime UX.

    With GraphQL we are able to define an easy-to-change application-level data 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 data-oriented, uniform service APIs) to resolve client-specified "queries" and "mutations" against the schema.

    We use GraphQL queries to dynamically derive a UI-specific mapping of app state from server-side data stores to client that can be updated in real time (see FeathersJS below.)
    We use GraphQL to dynamically derive a UI-specific projection of app state from server-side data sources to client that can be updated in real time (with help of Feathers)

    With this approach, the developer's job becomes a much more pleasant and simpler task of building the application-level GraphQL schema, building UI components and declaratively specifying the required queries and mutations.

    Client-centric architectures (like those based on Redux, MobX, Reframe, Elm, et al) tend to derive and/or cache "app state" on the client, and as such end up either replicating business logic in the client or managing cache invalidation at granular level. While those architectures enable things like 'optimistic UI' and 'offline first' apps they can exponentially complicate the work involved in maintaining and evolving the application.
    Client-centric architectures (like those based on client-side 'app state' stores) tend to cache and most often compose "app state" on the client, and as such end up either replicating business logic in the client or managing cache invalidation at granular level. While those architectures enable things like 'optimistic UI' and 'offline first' apps they can exponentially complicate the work involved in maintaining and evolving the application.

    ![GraphQL](https://s29.postimg.org/b7ifw7vc7/image1.png)

    ## Optimistic and Offline-First UI

    This meta-framework is designed for realtime, transactional apps (think: ordering & delivery and 'hard realtime' apps Uber) In this context, what does it mean to tell the user that their order was successful or the driver is 2 mins away then finding out from server that the order cannot be fulfilled or the driver is stuck in traffic? So offline-first and optimistic updates are at odds with 'realtime' and present extra overhead in 'transactional' apps where things are changing all the time. It is said that cache invalidation (a cache, aka client-side app state container, is necessary for optimistic and offline-first UI) is one of the three hardest problems in computer science. So we definitely gain agility and simplicity by removing the requirement for offline-first and optimistic UI. So then the question is wouldn't thast hurt mobile performance? The fact is that GraphQL already does a lot to help mobile performance by allowing us to get exactly the data we need at any given instance as opposed to dowloading more data than we need and putting it in the client side cache (aka client-side app state container) and complicating the app by having to manage app state on client and server instead of simply deriving it from server in real time.
    This meta-framework is designed for realtime, transactional apps (think: ordering & delivery and 'hard realtime' apps like Uber) In this context, what does it mean to tell the user that their order was successful or the driver is 2 mins away then finding out from server that the order cannot be fulfilled or the driver is stuck in traffic? This is to say that offline-first UI and optimistic UI are at odds with 'realtime' apps and present extra overhead of replicating app state and business logic in the client.

    So then the question is wouldn't losing Optimistic UI hurt mobile performance? The fact is that GraphQL already does a lot to help mobile performance by allowing us to get exactly the data we need at any given instance as opposed to dowloading more data than we need and putting it in the client side cache (aka client-side app state container) and complicating the app by having to manage app state on client and server instead of simply deriving it from server in real time.

    ## Some Challenges and Considerations

    1. Avoid business logic in the client: “app state” should not be composed and/or cached on the client as that would put redundant business logic in the client which adds a lot of unneeded complexity to the app. The client needs to be just an I/O layer, fetching/re-fetching UI-component-bound query results and making mutations to data on the server. In this pure, functional client model, local component state (including local state of higher order components) is used for ephemeral, client-only state such as animation state. We avoid composing app state on the client because that necessitates the embedding of business logic in the client, which complicates app building and maintenance. Instead, we opt to simply refetch UI-component-bound query results based on certain events like (backend mutation events, navigation state change or after network interruption) and let UI components derive their own local state from server-side app state which is persisted to the database and composed and projected to the client via GraphQL. The business logic stays on the server and the UI developer's job becomes very simple.

    2. The need for pre-mutation hooks: we need to be able to authorize the user before executing a mutation (and conditionally avoiding the mutation) so we can implement authorization on the server and leave business logic completely outside the client.

    3. The need for post-mutation hooks to make calls to external APIs (e.g. send email) after a given mutation.

    4. The need for live mutation events that perform well at scale: when something changes on the server, we need to know about it, either via polling or signaling. The latter has the advantage of being immediate.

    5. 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 decouple their resolvers from the underlying data store.

    6. We should be able to validate data based on our business logic, inside GraphQL resolvers

    7. We should be able to implement secure authentication using OAuth and Email/Password.

    8. We should be able to implement authorization independent of our database or network interface.

    9. We should be able to implement validation generically at the UI component level for instant feedback as user types

    10. We should be able to compose business logic in GraphQL resolver using microservices with a uniform data-oriented interface.

    ###References

  5. @idibidiart idibidiart revised this gist Mar 11, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ We use GraphQL queries to dynamically derive a UI-specific mapping of app state

    With this approach, the developer's job becomes a much more pleasant and simpler task of building the application-level GraphQL schema, building UI components and declaratively specifying the required queries and mutations.

    Client-centric architectures (like those based on Redux MobX, Reframe, Elm, et al) tend to derive and/or cache "app state" on the client, and as such end up either replicating business logic in the client or managing cache invalidation at granular level. While those architectures enable things like 'optimistic UI' and 'offline first' apps they can exponentially complicate the work involved in maintaining and evolving the application.
    Client-centric architectures (like those based on Redux, MobX, Reframe, Elm, et al) tend to derive and/or cache "app state" on the client, and as such end up either replicating business logic in the client or managing cache invalidation at granular level. While those architectures enable things like 'optimistic UI' and 'offline first' apps they can exponentially complicate the work involved in maintaining and evolving the application.

    ![GraphQL](https://s29.postimg.org/b7ifw7vc7/image1.png)

  6. @idibidiart idibidiart revised this gist Mar 11, 2017. 1 changed file with 0 additions and 22 deletions.
    22 changes: 0 additions & 22 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -16,28 +16,6 @@ Client-centric architectures (like those based on Redux MobX, Reframe, Elm, et a

    This meta-framework is designed for realtime, transactional apps (think: ordering & delivery and 'hard realtime' apps Uber) In this context, what does it mean to tell the user that their order was successful or the driver is 2 mins away then finding out from server that the order cannot be fulfilled or the driver is stuck in traffic? So offline-first and optimistic updates are at odds with 'realtime' and present extra overhead in 'transactional' apps where things are changing all the time. It is said that cache invalidation (a cache, aka client-side app state container, is necessary for optimistic and offline-first UI) is one of the three hardest problems in computer science. So we definitely gain agility and simplicity by removing the requirement for offline-first and optimistic UI. So then the question is wouldn't thast hurt mobile performance? The fact is that GraphQL already does a lot to help mobile performance by allowing us to get exactly the data we need at any given instance as opposed to dowloading more data than we need and putting it in the client side cache (aka client-side app state container) and complicating the app by having to manage app state on client and server instead of simply deriving it from server in real time.

    ## Some Challenges and Considerations

    1. Avoid business logic in the client: “app state” should not be composed and/or cached on the client as that would put redundant business logic in the UI and/or lead to cache-invalidation challenges both of 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 such as animation state. We avoid caching and/or composing 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 based on certain events like (backend mutation events, navigation state change or after network interruption) and let UI components derive their own state from the server based on bound query results. The business logic stays on the server and the UI developer's job becomes very simple.

    2. The need for pre-mutation hooks: we need to be able to authorize the user before executing a mutation (and conditionally avoiding the mutation) so we can implement authorization on the server and leave business logic completely outside the client.

    3. The need for post-mutation hooks to make calls to external APIs (e.g. send email) after a given mutation.

    4. The need for live data subscriptions 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.

    5. 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 decouple their resolvers from the underlying data store.

    6. We should be able to validate data based on our business logic, inside GraphQL resolvers

    7. We should be able to implement secure authentication using OAuth and Email/Password.

    8. We should be able to implement authorization independent of our database or network interface.

    9. We should be able to implement validation generically at the UI component level for instant feedback as user types

    10. We should be able to compose business logic in GraphQL resolver using microservices with a uniform data-oriented interface.

    ###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/)
  7. @idibidiart idibidiart revised this gist Mar 8, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ We use GraphQL queries to dynamically derive a UI-specific mapping of app state

    With this approach, the developer's job becomes a much more pleasant and simpler task of building the application-level GraphQL schema, building UI components and declaratively specifying the required queries and mutations.

    Client-centric architectures (aka shallow architectures) tend to derive and/or cache "app state" on the client, and as such end up either replicating business logic in the client or managing cache invalidation at granular level. While those architectures enable things like 'optimistic UI' and 'offline first' apps they can exponentially complicate the work involved in maintaining and evolving the application.
    Client-centric architectures (like those based on Redux MobX, Reframe, Elm, et al) tend to derive and/or cache "app state" on the client, and as such end up either replicating business logic in the client or managing cache invalidation at granular level. While those architectures enable things like 'optimistic UI' and 'offline first' apps they can exponentially complicate the work involved in maintaining and evolving the application.

    ![GraphQL](https://s29.postimg.org/b7ifw7vc7/image1.png)

  8. @idibidiart idibidiart revised this gist Mar 8, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    ## Building a Maintainable, Agile Architecture for Realtime, Transactional Apps
    ## Building Maintainable, Agile Architecture for Realtime, Transactional Apps

    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 logic for managing "app state" on the client (other than client-only state for generic input validation or animation which is encapsulated by individual UI components or HOCs), as either would necessarily embed business logic in the client and introduce cache invalidation challenges. App state should be derived directly from the server, and in realtime for highly interactive UX.

  9. @idibidiart idibidiart revised this gist Mar 8, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -18,7 +18,7 @@ This meta-framework is designed for realtime, transactional apps (think: orderi

    ## Some Challenges and Considerations

    1. Avoid business logic in the client: “app state” should not be constructed on the client as that would put redundant business logic in the UI and lead to cache-invalidation challenges both of 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 such as 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 very simple.
    1. Avoid business logic in the client: “app state” should not be composed and/or cached on the client as that would put redundant business logic in the UI and/or lead to cache-invalidation challenges both of 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 such as animation state. We avoid caching and/or composing 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 based on certain events like (backend mutation events, navigation state change or after network interruption) and let UI components derive their own state from the server based on bound query results. The business logic stays on the server and the UI developer's job becomes very simple.

    2. The need for pre-mutation hooks: we need to be able to authorize the user before executing a mutation (and conditionally avoiding the mutation) so we can implement authorization on the server and leave business logic completely outside the client.

    @@ -36,7 +36,7 @@ This meta-framework is designed for realtime, transactional apps (think: orderi

    9. We should be able to implement validation generically at the UI component level for instant feedback as user types

    10. We should be able to compose business logic in GraphQL resolver using microservices with a uniform data-oriented interface.
    10. We should be able to compose business logic in GraphQL resolver using microservices with a uniform data-oriented interface.

    ###References

  10. @idibidiart idibidiart revised this gist Mar 8, 2017. 1 changed file with 1 addition and 3 deletions.
    4 changes: 1 addition & 3 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -8,10 +8,8 @@ We use GraphQL queries to dynamically derive a UI-specific mapping of app state

    With this approach, the developer's job becomes a much more pleasant and simpler task of building the application-level GraphQL schema, building UI components and declaratively specifying the required queries and mutations.

    Client-based architectures (aka shallow architectures) like Redux, MobX, et al. manage "app state" on the client, 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.
    Client-centric architectures (aka shallow architectures) tend to derive and/or cache "app state" on the client, and as such end up either replicating business logic in the client or managing cache invalidation at granular level. While those architectures enable things like 'optimistic UI' and 'offline first' apps they can exponentially complicate the work involved in maintaining and evolving the application.

    |
    |
    ![GraphQL](https://s29.postimg.org/b7ifw7vc7/image1.png)

    ## Optimistic and Offline-First UI
  11. @idibidiart idibidiart revised this gist Feb 19, 2017. 1 changed file with 40 additions and 0 deletions.
    40 changes: 40 additions & 0 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,43 @@
    ## Building a Maintainable, Agile Architecture for Realtime, Transactional Apps

    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 logic for managing "app state" on the client (other than client-only state for generic input validation or animation which is encapsulated by individual UI components or HOCs), as either would necessarily embed business logic in the client and introduce cache invalidation challenges. App state should be derived directly from the server, and in realtime for highly interactive UX.

    With GraphQL we are able to define an easy-to-change application-level data 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 data-oriented, uniform service APIs) to resolve client-specified "queries" and "mutations" against the schema.

    We use GraphQL queries to dynamically derive a UI-specific mapping of app state from server-side data stores to client that can be updated in real time (see FeathersJS below.)

    With this approach, the developer's job becomes a much more pleasant and simpler task of building the application-level GraphQL schema, building UI components and declaratively specifying the required queries and mutations.

    Client-based architectures (aka shallow architectures) like Redux, MobX, et al. manage "app state" on the client, 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](https://s29.postimg.org/b7ifw7vc7/image1.png)

    ## Optimistic and Offline-First UI

    This meta-framework is designed for realtime, transactional apps (think: ordering & delivery and 'hard realtime' apps Uber) In this context, what does it mean to tell the user that their order was successful or the driver is 2 mins away then finding out from server that the order cannot be fulfilled or the driver is stuck in traffic? So offline-first and optimistic updates are at odds with 'realtime' and present extra overhead in 'transactional' apps where things are changing all the time. It is said that cache invalidation (a cache, aka client-side app state container, is necessary for optimistic and offline-first UI) is one of the three hardest problems in computer science. So we definitely gain agility and simplicity by removing the requirement for offline-first and optimistic UI. So then the question is wouldn't thast hurt mobile performance? The fact is that GraphQL already does a lot to help mobile performance by allowing us to get exactly the data we need at any given instance as opposed to dowloading more data than we need and putting it in the client side cache (aka client-side app state container) and complicating the app by having to manage app state on client and server instead of simply deriving it from server in real time.

    ## Some Challenges and Considerations

    1. Avoid business logic in the client: “app state” should not be constructed on the client as that would put redundant business logic in the UI and lead to cache-invalidation challenges both of 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 such as 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 very simple.

    2. The need for pre-mutation hooks: we need to be able to authorize the user before executing a mutation (and conditionally avoiding the mutation) so we can implement authorization on the server and leave business logic completely outside the client.

    3. The need for post-mutation hooks to make calls to external APIs (e.g. send email) after a given mutation.

    4. The need for live data subscriptions 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.

    5. 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 decouple their resolvers from the underlying data store.

    6. We should be able to validate data based on our business logic, inside GraphQL resolvers

    7. We should be able to implement secure authentication using OAuth and Email/Password.

    8. We should be able to implement authorization independent of our database or network interface.

    9. We should be able to implement validation generically at the UI component level for instant feedback as user types

    10. We should be able to compose business logic in GraphQL resolver using microservices with a uniform data-oriented interface.

    ###References
  12. @idibidiart idibidiart revised this gist Feb 19, 2017. 1 changed file with 1 addition and 36 deletions.
    37 changes: 1 addition & 36 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -1,39 +1,4 @@
    # 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 logic for managing "app state" on the client (other than client-only state for generic input validation or animation which is encapsulated by individual UI components or HOCs), as either would necessarily embed business logic in the client and introduce cache invalidation challenges. App state should be derived directly from the server, and in realtime for highly interactive UX.

    With GraphQL we are able to define an easy-to-change application-level data 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 data-oriented, uniform service APIs) to resolve client-specified "queries" and "mutations" against the schema.

    We use GraphQL queries to dynamically derive a UI-specific mapping of app state from server-side data stores to client that can be updated in real time (see FeathersJS below.)

    With this approach, the developer's job becomes a much more pleasant and simpler task of building the application-level GraphQL schema, building UI components and declaratively specifying the required queries and mutations.

    Client-based architectures (aka shallow architectures) like Redux, MobX, et al. manage "app state" on the client, 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://graphql.org/img/diagrams/business_layer.png)

    ## 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 both of 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 such as 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 very simple.

    2. The need for pre-mutation hooks: we need to be able to authorize the user before executing a mutation (and conditionally avoiding the mutation) so we can implement authorization on the server and leave business logic completely outside the client.

    3. The need for post-mutation hooks to make calls to external APIs (e.g. send email) after a given mutation.

    4. The need for live data subscriptions 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.

    5. 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 decouple their resolvers from the underlying data store.

    6. We should be able to validate data based on our business logic, inside GraphQL resolvers

    7. We should be able to implement secure authentication using OAuth and Email/Password.

    8. We should be able to implement authorization independent of our database or network interface.

    9. We should be able to implement validation generically at the UI component level for instant feedback as user types

    10. We should be able to break the business logic into a distributed microservices architecture when/as needed.
    10. We should be able to compose business logic in GraphQL resolver using microservices with a uniform data-oriented interface.

    ###References

  13. @idibidiart idibidiart revised this gist Feb 12, 2017. 1 changed file with 19 additions and 13 deletions.
    32 changes: 19 additions & 13 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -1,39 +1,45 @@
    # 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 logic for managing "app state" on the client, as either would necessarily embed business logic in the client and introduce cache invalidation challenges. App state should be derived directly from the server.
    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 logic for managing "app state" on the client (other than client-only state for generic input validation or animation which is encapsulated by individual UI components or HOCs), as either would necessarily embed business logic in the client and introduce cache invalidation challenges. App state should be derived directly from the server, and in realtime for highly interactive UX.

    With GraphQL we asre able to define 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 data-oriented, uniform service APIs) to resolve client-defined "queries" and "mutations" against the schema.
    With GraphQL we are able to define an easy-to-change application-level data 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 data-oriented, uniform service APIs) to resolve client-specified "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.
    We use GraphQL queries to dynamically derive a UI-specific mapping of app state from server-side data stores to client that can be updated in real time (see FeathersJS below.)

    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.
    With this approach, the developer's job becomes a much more pleasant and simpler task of building the application-level GraphQL schema, building UI components and declaratively specifying the required queries and mutations.

    Client-based architectures (aka shallow architectures) like Redux, MobX, et al manage "app state" on the client, 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.
    Client-based architectures (aka shallow architectures) like Redux, MobX, et al. manage "app state" on the client, 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://graphql.org/img/diagrams/business_layer.png)

    ## 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 both of 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 very simple.
    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 both of 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 such as 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 very 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.
    2. The need for pre-mutation hooks: we need to be able to authorize the user before executing a mutation (and conditionally avoiding the mutation) so we can implement authorization on the server and leave business logic completely outside the client.

    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.
    3. The need for post-mutation hooks to make calls to external APIs (e.g. send email) after a given mutation.

    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 decouple their resolvers from the underlying data store.
    4. The need for live data subscriptions 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.

    5. We should be able to implement secure authentication using OAuth and Email/Password.
    5. 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 decouple their resolvers from the underlying data store.

    6. We should be able to implement permissions independent of our database or network interface.
    6. We should be able to validate data based on our business logic, inside GraphQL resolvers

    7. We should be able to break the business logic into microservices when/as needed.
    7. We should be able to implement secure authentication using OAuth and Email/Password.

    8. We should be able to implement authorization independent of our database or network interface.

    9. We should be able to implement validation generically at the UI component level for instant feedback as user types

    10. We should be able to break the business logic into a distributed microservices architecture 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...
    Repo coming soon...

    ###Update

  14. @idibidiart idibidiart revised this gist Jan 27, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@ Client-based architectures (aka shallow architectures) like Redux, MobX, et al m

    ## 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 both of 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.
    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 both of 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 very 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.

  15. @idibidiart idibidiart revised this gist Jan 27, 2017. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -1,14 +1,14 @@
    # 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 logic for deriving/constructing app state on the client, as either would necessarily embed business logic in the client and introduce cache invalidation challenges. App state should be derived directly from the server.
    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 logic for managing "app state" on the client, as either would necessarily embed business logic in the client and introduce cache invalidation challenges. App state should be derived directly 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 GraphQL we asre able to define 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 data-oriented, uniform service 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.
    Client-based architectures (aka shallow architectures) like Redux, MobX, et al manage "app state" on the client, 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://graphql.org/img/diagrams/business_layer.png)
  16. @idibidiart idibidiart revised this gist Jan 23, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    # 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 introduce cache invalidation challenges. App state should be derived directly from the server.
    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 logic for deriving/constructing app state on the client, as either would necessarily embed business logic in the client and introduce cache invalidation challenges. App state should be derived directly 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.

  17. @idibidiart idibidiart revised this gist Jan 23, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    # 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.
    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 introduce cache invalidation challenges. App state should be derived directly 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.

  18. @idibidiart idibidiart revised this gist Jan 23, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -21,7 +21,7 @@ Client-based architectures (aka shallow architectures) like Redux, MobX, et al d

    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.
    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 decouple their resolvers from the underlying data store.

    5. We should be able to implement secure authentication using OAuth and Email/Password.

  19. @idibidiart idibidiart revised this gist Jan 23, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@ Client-based architectures (aka shallow architectures) like Redux, MobX, et al d

    ## 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.
    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 both of 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.

  20. @idibidiart idibidiart revised this gist Jan 23, 2017. 1 changed file with 2 additions and 15 deletions.
    17 changes: 2 additions & 15 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -10,6 +10,7 @@ Given the UI's data dependencies are specified declaratively, the front end deve

    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://graphql.org/img/diagrams/business_layer.png)

    ## Current Challenges and Considerations
    @@ -34,21 +35,7 @@ Client-based architectures (aka shallow architectures) like Redux, MobX, et al d

    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] (https://github.com/facebook/relay/issues/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:
    ###Update

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

  21. @idibidiart idibidiart revised this gist Jan 23, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -10,7 +10,7 @@ Given the UI's data dependencies are specified declaratively, the front end deve

    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)
    ![graphql](http://graphql.org/img/diagrams/business_layer.png)

    ## Current Challenges and Considerations

  22. @idibidiart idibidiart revised this gist Jan 23, 2017. 1 changed file with 8 additions and 8 deletions.
    16 changes: 8 additions & 8 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -10,23 +10,23 @@ Given the UI's data dependencies are specified declaratively, the front end deve

    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)
    ![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.
    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.
    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.
    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.
    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.
    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.
    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.
    7. We should be able to break the business logic into microservices when/as needed.

    ###References

  23. @idibidiart idibidiart revised this gist Jan 23, 2017. 2 changed files with 65 additions and 48 deletions.
    65 changes: 65 additions & 0 deletions GraphQL-Architecture.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    # 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] (https://github.com/facebook/relay/issues/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)


    48 changes: 0 additions & 48 deletions GraphQL-Relay-Redux.md
    Original file line number Diff line number Diff line change
    @@ -1,48 +0,0 @@
    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 encode 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 to data sources via resolvers that leverage our db's own query language or in-memory objects to resolve client-defined "queries" and "mutations" against the schema.

    With each component in the UI component tree declaring its own data dependencies, GraphQL (with Relay or Apollo client in the browser) creates a projection of our data on the server that maps directly to the UI component tree. GraphQL + Relay|Apollo 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 our app state in the client. Using Relay or Apollo the queries from our GraphQL client to the GraphQL server are composed in an efficient manner based on the aggregate data dependencies that are declared by each component in the UI component tree, thus eliminating redundant queries over the network. Relay (and Apollo client) also allow for mutation events from the UI to propagate to the server, while keeping the projected app state in the UI in sync with the data on the server. Relay|Apollo can also update the UI when an external mutation (from another process/user) takes place on the server, via GraphQL subscriptions.

    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 their queries and mutations.

    With GraphQL + Relay|Apollo everyone, be them web, mobile or 3rd party developers, works with the same application-level, UI agnostic, server-side schema and declare their data dependencies at the UI component level, then have GraphQL in combination with Relay or Apollo et al take care of generating an efficient query, shaping the query result for consumption by the UI and keeping the projected app state in sync with the data on the server.
    GraphQL + Relay|Apollo eliminate a host of cost centers, conveniences and tools such as RESTful APIs, ORMs/ODMs (it should as it removes the need for manual denormalization/renormalization, unless you don't wish to use SQL/NoSQL query syntax directly) and imperatively sync'd client caches. Client-side-only solutions like Redux, MobX, et al (i.e. without GraphQL + Apollo|Relay) don't go deep enough, and as such end up putting app state and user intent derivation in the client, which means that business logic gets entangled in the client by design.

    A deep architecture like GraphQL + Relay|Apollo allow us to make radical changes to our UI without a lot of rework on client and server, which is something that cannot be done with a shallow, client-side-only architecture.

    ###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] (https://github.com/facebook/relay/issues/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)


  24. @idibidiart idibidiart revised this gist Jan 23, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Relay-Redux.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    A maintainable application architecture requires that the UI only contain the rendering logic and execute queries and mutations against the underlying data layer on the server. A maintainable UI must not contain any logic for deriving user intent or any logic for deriving app state, as either would necessarily encode business logic in the client.
    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 encode 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 to data sources via resolvers that leverage our db's own query language or in-memory objects to resolve client-defined "queries" and "mutations" against the schema.

  25. @idibidiart idibidiart revised this gist Jan 23, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Relay-Redux.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    A maintainable UI architecture requires that our UI only contains the logic to render current app state and relay queries and mutations to the underlying data layer on the server (i.e. a maintainable UI must not contain any logic for deriving user intent or deriving app state, as either would necessarily encode business logic in the client.)
    A maintainable application architecture requires that the UI only contain the rendering logic and execute queries and mutations against the underlying data layer on the server. A maintainable UI must not contain any logic for deriving user intent or any logic for deriving app state, as either would necessarily encode business logic in the client.

    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 to data sources via resolvers that leverage our db's own query language or in-memory objects to resolve client-defined "queries" and "mutations" against the schema.

  26. @idibidiart idibidiart revised this gist Jan 14, 2017. 1 changed file with 7 additions and 18 deletions.
    25 changes: 7 additions & 18 deletions GraphQL-Relay-Redux.md
    Original file line number Diff line number Diff line change
    @@ -1,26 +1,15 @@
    A maintainable UI architecture requires that our UI only contains the logic to render current app state and relay queries and mutations to the underlying data layer on the server (i.e. a maintainable UI must not contain any logic for deriving user intent or deriving app state, as either would necessarily encode business logic in the client.)

    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 to data sources via resolvers that leverage our db's own query language or in-memory objects to resolve client-defined "queries" and "mutations" against the schema.
    A maintainable UI architecture requires that our UI only contains the logic to render current app state and relay queries and mutations to the underlying data layer on the server (i.e. a maintainable UI must not contain any logic for deriving user intent or deriving app state, as either would necessarily encode business logic in the client.)

    With each component in the UI component tree declaring its own data dependencies, GraphQL (with Relay or Apollo client in the browser) creates a projection of
    the server-side data model that maps directly to the UI component tree, thus allowing us to have an application-level, UI-agnostic model of our data on the server,
    while at once giving us and UI-specific projection of our app's state. Using Relay or Apollo the queries from our GraphQL client to the GraphQL server are composed
    in an efficient manner based on the aggregate data dependencies that are declared by each component in the UI component
    tree, thus eliminating redundant queries over the network.
    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 to data sources via resolvers that leverage our db's own query language or in-memory objects to resolve client-defined "queries" and "mutations" against the schema.

    Relay (and Apollo client) also allow for mutation events from the UI to propagate to the server, while keeping the projected app state in the UI in sync with the data on the server. Relay|Apollo can also update the UI when an external mutation (from
    another process/user) takes place on the server, via GraphQL subscriptions.
    With each component in the UI component tree declaring its own data dependencies, GraphQL (with Relay or Apollo client in the browser) creates a projection of our data on the server that maps directly to the UI component tree. GraphQL + Relay|Apollo 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 our app state in the client. Using Relay or Apollo the queries from our GraphQL client to the GraphQL server are composed in an efficient manner based on the aggregate data dependencies that are declared by each component in the UI component tree, thus eliminating redundant queries over the network. Relay (and Apollo client) also allow for mutation events from the UI to propagate to the server, while keeping the projected app state in the UI in sync with the data on the server. Relay|Apollo can also update the UI when an external mutation (from another process/user) takes place on the server, via GraphQL subscriptions.

    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 their queries and mutations.
    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 their queries and mutations.

    With GraphQL/Relay everyone, be them web, mobile or 3rd party developers, works with the same application-level, UI agnostic, server-side schema and declare their data dependencies at the UI component level, then have GraphQL in combination
    with Relay or Apollo et al take care of generating an efficient query, shaping the query result for consumption by the UI and keeping the projected app state in sync with the data on the server.

    In one fell swoop, GraphQL/Relay (or Apollo Stack) eliminate a host of cost centers, conveniences and tools such as RESTful APIs, ORMs/ODMs (it should as it removes the need for manual denormalization/renormalization, unless you don't wish to ue SQL/NoSQL query syntax directly) and imperatively sync'd client caches. Client-side-only solutions like Redux (without GraphQL/Apollo) don't go deep enough, and as such end up putting app state and user intent derivation in the client, which means that business logic gets entangled in the client by design.

    A deep architecture like GraphQL/Relay (and Apollo) allow us to make radical changes to our UI without a lot of rework on client and server, which is something that cannot be done with a shallow, client-side-only architecture.
    With GraphQL + Relay|Apollo everyone, be them web, mobile or 3rd party developers, works with the same application-level, UI agnostic, server-side schema and declare their data dependencies at the UI component level, then have GraphQL in combination with Relay or Apollo et al take care of generating an efficient query, shaping the query result for consumption by the UI and keeping the projected app state in sync with the data on the server.
    GraphQL + Relay|Apollo eliminate a host of cost centers, conveniences and tools such as RESTful APIs, ORMs/ODMs (it should as it removes the need for manual denormalization/renormalization, unless you don't wish to use SQL/NoSQL query syntax directly) and imperatively sync'd client caches. Client-side-only solutions like Redux, MobX, et al (i.e. without GraphQL + Apollo|Relay) don't go deep enough, and as such end up putting app state and user intent derivation in the client, which means that business logic gets entangled in the client by design.

    A deep architecture like GraphQL + Relay|Apollo allow us to make radical changes to our UI without a lot of rework on client and server, which is something that cannot be done with a shallow, client-side-only architecture.

    ###References

  27. @idibidiart idibidiart revised this gist Jan 13, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion GraphQL-Relay-Redux.md
    Original file line number Diff line number Diff line change
    @@ -27,7 +27,7 @@ A deep architecture like GraphQL/Relay (and Apollo) allow us to make radical cha
    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...
    2.

    ###Updated 1:

    (after a Twitter chat with @en_JS (Joseph Savona), one of the GraphQL/Relay developers at Facebook)
  28. @idibidiart idibidiart revised this gist Jan 13, 2017. 1 changed file with 14 additions and 54 deletions.
    68 changes: 14 additions & 54 deletions GraphQL-Relay-Redux.md
    Original file line number Diff line number Diff line change
    @@ -1,35 +1,26 @@

    GraphQL allows us to define a UI-agnostic data model on the server using a virtual graph schema that captures the types and relationships in the data. To wire the model to data sources, we define resolvers in the schema that leverage our db's own query language (or API calls for in-memory objects) to resolve client-defined "queries" against our data model.
    A maintainable UI architecture requires that our UI only contains the logic to render current app state and relay queries and mutations to the underlying data layer on the server (i.e. a maintainable UI must not contain any logic for deriving user intent or deriving app state, as either would necessarily encode business logic in the client.)

    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 to data sources via resolvers that leverage our db's own query language or in-memory objects to resolve client-defined "queries" and "mutations" against the schema.

    With each component in the UI component tree declaring its own data dependencies, GraphQL (with Relay or Apollo client in the browser) creates a projection of
    the server-side data model that maps directly to the UI component tree, thus allowing us to have a UI-agnostic data model on the server,
    while at once giving us and UI-specific projection of our app's data/state. The queries from GraphQL server to the database are composed
    the server-side data model that maps directly to the UI component tree, thus allowing us to have an application-level, UI-agnostic model of our data on the server,
    while at once giving us and UI-specific projection of our app's state. Using Relay or Apollo the queries from our GraphQL client to the GraphQL server are composed
    in an efficient manner based on the aggregate data dependencies that are declared by each component in the UI component
    tree, thus eliminating redundant queries to the database.

    Relay (and Apollo client) also allow for mutation events from the UI to propagate to the server, while rendering
    the UI optimistically. It can also update the UI when an external mutation (from
    another process/user) takes place on the server.
    tree, thus eliminating redundant queries over the network.

    Given how UI data dependencies are specified declaratively, the front end developer's job becomes a much more pleasant task
    consisting of simply building components and declaratively specifying their data dependencies and mutations. GraphQL and Relay
    take care of the rest.
    Relay (and Apollo client) also allow for mutation events from the UI to propagate to the server, while keeping the projected app state in the UI in sync with the data on the server. Relay|Apollo can also update the UI when an external mutation (from
    another process/user) takes place on the server, via GraphQL subscriptions.

    Since we can only have parent-child composition in the DOM and that is true for React's DOM renderer, too. Thus, the UI as a data structure is a tree of components implementing various behavior that ultimately mutate the DOM. So whatever you can do in with React you'll be able to do with Relay.
    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 their queries and mutations.

    The Facebook Relay team is planning on providing time travel facility (time based app state inspection) for React/Relay apps (Apollo already uses Redux DevTools) making client-only architectures that rely on Redux only (or other client-side state management patterns) very brittle in
    comparison as they ultimately depend on a client-specified app state data structure that does not derive declaratively from the state of the server side model, which means lots of rework on both the client side and server side when we need to make deep changes to our app. With GraphQL/Relay everyone,
    be them web, mobile or 3rd party developers, works with the same server side graph schema and declare their data dependencies at the UI component level, then have GraphQL in combination
    with Relay take care of generating an efficient query, shaping the query result for consumption by the UI and keeping application state in sync across client and server.
    With GraphQL/Relay everyone, be them web, mobile or 3rd party developers, works with the same application-level, UI agnostic, server-side schema and declare their data dependencies at the UI component level, then have GraphQL in combination
    with Relay or Apollo et al take care of generating an efficient query, shaping the query result for consumption by the UI and keeping the projected app state in sync with the data on the server.

    In one fell swoop, GraphQL/Relay (or Apollo Stack) eliminate a host of cost centers, conveniences and tools such as RESTful APIs,
    imperatively sync'd client/server caches, and client-side-only solutions like Redux (without GraphQL/Apollo) that don't go deep enough.
    In one fell swoop, GraphQL/Relay (or Apollo Stack) eliminate a host of cost centers, conveniences and tools such as RESTful APIs, ORMs/ODMs (it should as it removes the need for manual denormalization/renormalization, unless you don't wish to ue SQL/NoSQL query syntax directly) and imperatively sync'd client caches. Client-side-only solutions like Redux (without GraphQL/Apollo) don't go deep enough, and as such end up putting app state and user intent derivation in the client, which means that business logic gets entangled in the client by design.

    A deep architecture like GraphQL/Relay (and Apollo) allow us to make radical changes to our UI without a lot of rework on client and server, which is something that cannot be done with a shallow, client-side-only architecture.

    ###Limitations

    When it comes to the subject of client-only state and Relay, I think the two features listed in the Roadmap (see Update #1 below) are must-have eventually. But I see a risk at a conceptual level in what many people take for granted: that client's job is to specify to the server how to satisfy user intent -- This leads to all sorts of complications. App state that sync'd via Relay between the UI component tree and our graph model on the server should be all that is needed in *most* cases (other than client-only state like component animation state and other client state that we don't care to sync to server) Client should relay mutations to that state that are due to user interaction and the server should figure out user intent and how to satisfy it. Having the client figure out user intent and how to satisfy it means that you're isolating that part of the application's behavior in the client, which leads to a thick, complicated client.

    ###References

    @@ -61,39 +52,8 @@ Here is a section of the very long conversation that Dan started:

    ###Update 3:

    My follow up conversation with Dan below
    My follow up conversation with Dan Abrahmov below

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

    ###Update 4:

    Answer from @en_JS (Relay lead at Facebook?) to the first complex use case I ran into, which gives me a lot of confidence
    in Relay.

    ![twittter followup] (http://i.imgur.com/aWC9ur0.png)

    [@en_JS' truncated link] (https://facebook.github.io/relay/docs/api-reference-relay-container.html#setvariables)

    ####Update 5:

    I had a brief chat on Gitter with Jean-Jacques Dubray, author of [Why I No Longer Use MVC Frameworks] (http://www.infoq.com/articles/no-more-mvc-frameworks)

    ![gitter chat] (http://i.imgur.com/SAmptOC.png)

    ####Update 6:

    I was wondering how to safely and properly expose typical DB operations to the client via GraphQL since not every UI is going to want canned query resolution specified in the query resolves. Some UI use cases call for composing queries with specific operators. Here is the answer:

    ![HN tip] (http://i.imgur.com/fGfZ8lI.png)

    ####Update 7:

    Christopher from Facebook RT'd this about Datalayer, which can be used as cache to optimise query resolution:

    ![Twitter] (http://i.imgur.com/rTF8wLl.png)

    ####Update 8:

    Client Only State (aka "client fields") and other advances and simplifications in Relay 2 (click to play video):

    [![Youtube video] (https://img.youtube.com/vi/OEfUBN9dAI8/0.jpg)] (https://www.youtube.com/watch?v=OEfUBN9dAI8)
  29. @idibidiart idibidiart revised this gist Jan 5, 2017. 1 changed file with 3 additions and 4 deletions.
    7 changes: 3 additions & 4 deletions GraphQL-Relay-Redux.md
    Original file line number Diff line number Diff line change
    @@ -22,11 +22,10 @@ comparison as they ultimately depend on a client-specified app state data struct
    be them web, mobile or 3rd party developers, works with the same server side graph schema and declare their data dependencies at the UI component level, then have GraphQL in combination
    with Relay take care of generating an efficient query, shaping the query result for consumption by the UI and keeping application state in sync across client and server.

    In one fell swoop, GraphQL/Relay eliminate a host of cost centers, conveniences and tools such as RESTful APIs, ORM/OGM,
    client/server caches, and client-side solutions like Flux/Redux that don't go deep enough.
    In one fell swoop, GraphQL/Relay (or Apollo Stack) eliminate a host of cost centers, conveniences and tools such as RESTful APIs,
    imperatively sync'd client/server caches, and client-side-only solutions like Redux (without GraphQL/Apollo) that don't go deep enough.

    A deep architecture like GraphQL/Relay can allow us to make radical changes to our UI without a ton of rework on client and server, which is something that cannot be done with by a client-side-only framework
    like Redux.
    A deep architecture like GraphQL/Relay (and Apollo) allow us to make radical changes to our UI without a lot of rework on client and server, which is something that cannot be done with a shallow, client-side-only architecture.

    ###Limitations

  30. @idibidiart idibidiart revised this gist Jan 5, 2017. 1 changed file with 4 additions and 5 deletions.
    9 changes: 4 additions & 5 deletions GraphQL-Relay-Redux.md
    Original file line number Diff line number Diff line change
    @@ -1,13 +1,13 @@

    GraphQL allows us to define a UI-agnostic data model on the server using a schema that captures the types and relationships in the data. To wire the model to data sources, we define resolvers in the schema that leverage our db's own query language (or API calls for in-memory objects) to resolve client-defined "queries" against our UI-agnostic data model.
    GraphQL allows us to define a UI-agnostic data model on the server using a virtual graph schema that captures the types and relationships in the data. To wire the model to data sources, we define resolvers in the schema that leverage our db's own query language (or API calls for in-memory objects) to resolve client-defined "queries" against our data model.

    With each component in the UI component tree declaring its own data dependencies, GraphQL/Relay creates a projection of
    With each component in the UI component tree declaring its own data dependencies, GraphQL (with Relay or Apollo client in the browser) creates a projection of
    the server-side data model that maps directly to the UI component tree, thus allowing us to have a UI-agnostic data model on the server,
    while at once giving us and UI-specific projection of our app's data/state. The queries from GraphQL server to the database are composed
    in an efficient manner based on the aggregate data dependencies that are declared by each component in the UI component
    tree, thus eliminating redundant queries to the database.

    Relay also allows for mutation events from the UI to propagate to the server, while rendering
    Relay (and Apollo client) also allow for mutation events from the UI to propagate to the server, while rendering
    the UI optimistically. It can also update the UI when an external mutation (from
    another process/user) takes place on the server.

    @@ -17,8 +17,7 @@ take care of the rest.

    Since we can only have parent-child composition in the DOM and that is true for React's DOM renderer, too. Thus, the UI as a data structure is a tree of components implementing various behavior that ultimately mutate the DOM. So whatever you can do in with React you'll be able to do with Relay.

    The Facebook Relay team is planning on providing time travel facility (time based app state inspection) for React/Relay
    apps (potentially using the dev tools part of Redux) making solutions like Redux not only redundant but also very brittle in
    The Facebook Relay team is planning on providing time travel facility (time based app state inspection) for React/Relay apps (Apollo already uses Redux DevTools) making client-only architectures that rely on Redux only (or other client-side state management patterns) very brittle in
    comparison as they ultimately depend on a client-specified app state data structure that does not derive declaratively from the state of the server side model, which means lots of rework on both the client side and server side when we need to make deep changes to our app. With GraphQL/Relay everyone,
    be them web, mobile or 3rd party developers, works with the same server side graph schema and declare their data dependencies at the UI component level, then have GraphQL in combination
    with Relay take care of generating an efficient query, shaping the query result for consumption by the UI and keeping application state in sync across client and server.