Lessons learned while going from 0 to 1 with Mobile and GraphQL
Kamilah Taylor, @kamilahGraphQL Summit 2020
2 | Confidential – Do Not Distribute
🇯🇲👩🏾🏫🤖📚👩🏾💻A little about me
3 | Confidential – Do Not Distribute
🇯🇲👩🏾🏫🤖📚👩🏾💻A little about me
4 | Confidential – Do Not Distribute
So you want to build an app and also use and learn GraphQL and evolve the schema at the same time
When we started working on this app, there were three main questions that we had and that
we have continuously asked ourselves
6 | Confidential – Do Not Distribute
🤨🧐🤔
So I’m using Apollo iOS in my app, what goes where?1
The schema is evolving! How do we keep up?2
So you’re telling me the engineering team has to think about multiple clients now?3
Over time, we’ve worked out some answers for these, and
some things, we’re still working on
Modular App Architecture + Apollo iOS
9 | Confidential – Do Not Distribute
The problem with the monolithAnd why we architected our app modularly
● Swift codebases get large and unmanageable● Compile times increase● Libraries get tightly coupled to our code● Lots of merge conflicts
10 | Confidential – Do Not Distribute
Our guiding architecture principles
● Modular app architecture● Enforce boundaries between modules● Practice encapsulation, especially for external dependencies● Use the coordinator pattern for navigation
11 | Confidential – Do Not Distribute
Where we startedA couple of feature frameworks
12 | Confidential – Do Not Distribute
Where we startedA couple of feature frameworks
Problem we found:We have multiple feature
frameworks and needed all of them to access the data layer
without creating a dependency on apollo for every feature
framework
14 | Confidential – Do Not Distribute
Enter: The DataService layerHow the feature frameworks talk to apollo
15 | Confidential – Do Not Distribute
What this wins for usModularization
● We’re able to break our codebase up into modules● We also separate our infrastructure layer from our feature
layer● We set ourselves up to be able to pull some of our infra layer
modules out completely as shareable libraries
16 | Confidential – Do Not Distribute
The DataServiceOur apollo workhorse
17 | Confidential – Do Not Distribute
What this wins for usEncapsulation
● Our feature frameworks never need to know that Apollo is running under the hood
● We centralize how everyone interfaces with the data layer● We hide some of our details of what the network manager is
doing from the feature frameworks
Solution we found: We used our modular app
architecture to encapsulate and create boundaries around Apollo and our data layer
Active app development + an evolving schema
20 | Confidential – Do Not Distribute
Build the app, define the schema, build the app, repeatAdd in some early experiments with mock data, realizations of how the schema should be defined and also some new use cases
Problem we found: Over time our understanding of what we
needed the schema structure to be changed, and with active
feature development, sometimes the schema had to
be updated
22 | Confidential – Do Not Distribute
Decoupling our code from the shape of the queries through the MVVM+Coordinator patternKeep data calls to just the view models and coordinators
23 | Confidential – Do Not Distribute
What this wins for usMore encapsulation
● Within our feature frameworks, usually only our view models interact with our data layer and have knowledge of the GraphQL models
● Sometimes our coordinators end up with this job, usually when they’re handling a flow that’s spread across multiple views
24 | Confidential – Do Not Distribute
Extensions to our GraphQL modelsIsolating the exact shape of the query where possible
● GraphQL generated models end up with deeply nested types that reveal the exact shape of the query
● We end up tightly coupling the shape of the query to everyone that needs to interact with the models
25 | Confidential – Do Not Distribute
Extensions to our GraphQL modelsIsolating the exact shape of the query where possible
26 | Confidential – Do Not Distribute
Extensions to our GraphQL modelsIsolating the exact shape of the query where possible
Solution we found: We handle schema evolution by limiting access to the data layer using
patterns like MVVM, and decoupling the code from the shape of the schema by using
Swift extensions
It’s a multiple client world - we just live in it
Problem we found: The team was used to designing APIs for a
web client that lived with the backend, but now we had to figure out how to design for
multiple clients
30 | Confidential – Do Not Distribute
Design the schemas to encapsulate business logicDon’t have your logic multiplied across clients
31 | Confidential – Do Not Distribute
Design the schemas to encapsulate business logicDon’t have your logic multiplied across clients
32 | Confidential – Do Not Distribute
Design the schemas to encapsulate business logicDon’t have your logic multiplied across clients
33 | Confidential – Do Not Distribute
A few more things that have worked for usThis list will only keep growing!
● For client side strings, always interpolate them with business values returned from the schema
● GraphQL Interfaces and enums are powerful tools for lists of items where new item types could be added over time
● Coordinate deprecations by partnering cross functionally● Design schemas to product backwards compatible where possible
Solution we found: We’ve embraced the multiple client world by designing GraphQL APIs to encapsulate business
logic, being product backwards compatible, and partnering across engineering teams
35 | Confidential – Do Not Distribute
☺✌🏾😌
Apollo iOS lives in a data service layer and feature frameworks interact with the data service through their view models1
Decouple as much of the app as possible from the shape of the schema to handle schema evolution gracefully2
Embrace the multiple client life and design the schema to encapsulate business logic and be product backwards compatible
3
36 | Confidential – Do Not Distribute
Victory