Terminology
β Error null
β Exceptional case
β Has an error in the errors array
β Semantic null
β Business case
β No error in the errors array
Slide 16
Slide 16 text
@Composable
fun VideoItem(video: Video) {
Text(text = video.title!!)
}
Slide 17
Slide 17 text
@Composable
fun VideoItem(response: Response) {
if (response.errors.isNotEmpty()) {
Error()
} else {
Text(text = response.data.video.title!!)
}
}
Slide 18
Slide 18 text
2 months later
Slide 19
Slide 19 text
Post mortem
β New feature: video upload
β During the upload, a video doesnβt have a title yet
β This was a backward compatible schema
change!
Slide 20
Slide 20 text
@Composable
fun VideoItem(response: Response) {
if (response.errors.isNotEmpty()) {
Error()
} else {
if (response.data.video.title == null) {
Text(text = "This video doesn't have a title yet")
} else {
Text(text = response.data.video.title)
}
}
}
Slide 21
Slide 21 text
Different shades of error handling
Slide 22
Slide 22 text
There is moreβ¦
Slide 23
Slide 23 text
No content
Slide 24
Slide 24 text
@Composable
fun VideoItem(response: Response) {
if (response.errors.any { it.path == "video.title" }) {
Error() // Can't display a video without a title
} else {
if (response.data.video.title != null) {
Text(text = "This video does not have a title yet")
} else {
Text(text = response.data.video.title!!)
}
if (response.errors.any { it.path == "video.viewCount" }) {
// Skip viewCount
} else {
Text(text = "${response.data.video.viewCount!!} + views")
}
}
}
Partial data
Slide 25
Slide 25 text
10 ο¬elds β¨ 1024 possibilities
Slide 26
Slide 26 text
Guessing game
β Semantic null?
β Error null?
β π€·
Slide 27
Slide 27 text
GraphQL is missing types
Your favorite
type-safe language
GraphQL
string β String!
string | null β String
string | error β String
string | null | error β String
Slide 28
Slide 28 text
Part II: solutions
Slide 29
Slide 29 text
Documentation
type Video {
"""
The title of the Video
null if the video has just been uploaded
"""
title: String
"""
Number of times this video has been watched
Never null unless there is an error
"""
viewCount: Int
}
Slide 30
Slide 30 text
Evolving the language
Slide 31
Slide 31 text
Nullability working group
2021
Client Controlled
Nullability
May 2023
sub working group
Sep 2023
GraphQL conf
True nullability
Asterisk
Interrobang
Oct 2023
semantic-non-null
@strictNullability
@catch
graphql/nullability-wg
Slide 32
Slide 32 text
Nullability working group
2021
Client Controlled
Nullability
May 2023
sub working group
Sep 2023
GraphQL conf
True nullability
Asterisk
Interrobang
Oct 2023
semantic-non-null
@strictNullability
@catch
graphql/nullability-wg
Slide 33
Slide 33 text
Asterisk
string β String!
string | null β donβt use
string | error β String*
string | null | error β String
graphql/graphql-spec/pull/1048
Never a semantic
null
Problem 2: what default?
β Fail the whole query
β Easy
β Fragile
β Handle ο¬eld errors
β Hard
β Robust
Slide 44
Slide 44 text
Opting in error handling
β Start easy
β Add error handling progressively
fragment VideoDetails on Video {
video {
title
# opt-in error handling
viewCount @catch
}
}
facebook/relay/issues/4416
Slide 45
Slide 45 text
Opting in error handling
fragment VideoDetails on Video {
video {
title
# opt-in error handling
viewCount @catch
}
}
sealed interface Result {
class Success(val value: T): Result
class Failure(val error: error): Result
}
Video(
val title: String
val viewCount: Result
)
apollographql/apollo-kotlin/pull/5405
Slide 46
Slide 46 text
Client Controlled Nullability
graphql/graphql-wg/blob/main/rfcs/ClientControlledNullability.md
fragment videoDetails on Video {
video {
# We need title to display a video
title!
# It's okay to fail viewCount
viewCount?
}
}