Modern software engineering continues to move at an ever-accelerating pace as both the industry and consumers demand more out of their technology. With mobile playing a large part in this trend, it's especially important for mobile application developers to stay up-to-date on best practices and the latest technologies that can streamline their development pipeline and allow them to ship more code quickly and correctly.
Today's mobile application developers stand to gain quite a bit of power, agility, and robustness if presented with the opportunity to work with a GraphQL-based backend API.
It's Well-typed Data All The Way Down
When building mobile applications that consume external data from the web, there is often times an impedance mismatch between the statically-typed world of your application code and the unstructured JSON responses received from traditional REST APIs.
With REST APIs, developers are tasked with either making potentially incorrect assumptions about endpoint response shapes... or go through the process of validating and asserting the correctness of each payload based on their expectations.
While maintaining hand-written validation logic is certainly an option, the burden then falls on the developer to ensure parity between the API's response shapes and app's validation logic; any changes in the upstream API forces the app team to re-evaluate and update their code.
Emerging standards such as the OpenAPI Specification provide a framework to add typings and formalized documentation to REST APIs. While this can allow for some improved ergonomics around consuming REST endpoints and tools for generating typed code from an API spec, it generally exists as a separate augmentation layer that has to be opted-in to by API development team.
With GraphQL, these concerns can be completely sidestepped simply because GraphQL APIs are, out of the box, statically and strongly typed.
GraphQL endpoints are defined by their schema-- the declarative SDL document that fully documents defines all queries, types, and mutations available on the API. Through rich tooling in the GraphQL ecosystem, app developers can source a GraphQL API's schema via introspection and output generated code for their language and platform of choice that contains all of the types provided by the API. This means developers can get compile-time feedback of API usage correctness and expectations when building mobile apps that consume GraphQL APIs.
For example, an iOS developer could use the tooling available in the Apollo iOS SDK to take a GraphQL query:
And have it generate the corresponding Swift query class:
This gives mobile developers the assurance that the data they're receiving from the server is a well-typed, known shape. If a developer's app code attempts to access fields from the response payload that aren't there, then a compile-time error will occur and their IDE can provide helpful information about how to resolve it.
Bespoke API Queries for the Discerning Developer
Especially when developing mobile apps that often times are using less-than-ideal internet connections, it's important to be mindful of API request latencies and response payload sizes. Other constraints such as limited compute power and battery life only further drive the need to carefully control network communications.
With traditional REST endpoints, the mobile app client has to design its API request strategy around the limited available response shapes from the server. This requires design compromises such as over-fetching data (making requests for large amounts of data of which the client only needs a subset) or under-fetching data (making multiple requests from disparate endpoints to fully obtain the data needed on the client).
One way to potentially mitigate this issue is to closely couple the design of the API backend and the mobile client that is consuming it-- effectively having the mobile development team detail all of their planned data access patterns for the platform engineers building the API. However, this strategy has some distinct problems:
- API Endpoint Sprawl. A single API platform could be used by a native desktop client, a mobile app, and a smart-watch or other small device. Each client is likely to have very different needs and constraints, and having customized endpoints for each one would quickly become extremely clunky to maintain. It's also highly likely there would be a lot of endpoint overlap, as each one is providing a specifically-customized view of the data.
- Client and Server end up too tightly coupled. If a mobile client is relying on the server for their exact response shape, anytime the client's needs change the server will have to be updated as well. This hard-coupling creates bottlenecks and stalls in the delivery pipeline that can severely impede a teams ability to quickly ship products.
GraphQL endpoints effectively solve this problem by allowing clients to explicitly request only, and exactly, the data they need. Over-fetching is no longer an issue, since the client only has to select the fields and objects they care about, and under-fetching is eliminated since detailed and nested information about objects can be requested in-place. In addition, multiple queries can be combined in a single GraphQL API request, potentially allowing a mobile app client to receive all the data needed to populate a view in a single network request.
To elaborate, it’s a common pattern with REST APIs to have one resource that returns a list of terse models with a subset of all available fields, and a separate resource that will return a more detailed projection of the model with all the available fields:
As a mobile app developer, this may initially cover our needs for presenting information to the user in a client application. We could easily show a list of all of their devices by name and type. But what if we'd like to also show the ON/OFF state of any lights in the list? We'd have to make another API request for each Light device in our list in order to get access to the fields we'd need. This is referred to as the N+1 problem, as our client is now having to make additional API requests for each additional item.
With an API powered by GraphQL, we could specify the exact fields we wanted back at request-time, and get everything we need in a single API call:
Since the app developer writes the queries with an explicit list of fields they want returned from the API, there’s no need to make additional requests to fill in the missing detailed information.
GraphQL is far more than just the latest trendy buzzword making tech news headlines-- it represents a fundamental shift in how data can be modeled and consumed over the web. By leaning into these changes and eagerly adopting the technology where it makes sense, mobile development teams stand to supercharge their apps and give their users a truly cutting-edge experience.