Sometimes More is More
My role at Google is known as a DPE or Developer Programs Engineer. As the name suggests, I’m considered an engineer, but I’m not the same as a SWE, a “SoftWare Engineer”. What’s the difference? Well, it starts with our products.
A SWE (we say it like a word, so like “sweet” but without the ’t’) is responsible for building the software that powers Google’s external and internal products. Google Search, Android, Chrome, etc… are, for the most part, built by SWEs. As they build these products that are used by billions of users a day, they have to be robust, secure, and performant.
A DPE, such as myself, is responsible for writing and maintaining our sample code. Some samples are obviously samples, such as UAMP, but others, such as Santa Tracker and “IOSched” are also samples and maintained by DPEs (and DA, Developer Advocates).
So what’s the difference? You both develop software! Isn’t code just code?
Well, not really. And this is something I’ve only just been coming around to appreciate.
The goal of a SWE is to write code to satisfy a set of requirements, and while it should be understandable, the audience is likely to be not only highly technical, but also rather familiar with the topic at hand.
The goal of sample code, by contrast, is often to teach a new concept, or demonstrate an API. The audience may also be highly technical, but not always, but it is much more likely they are not as familiar with the topic, which is why they’re looking at the sample.
Here’s an example of concise code to find all songs matching a “focused search”, which is something the Google Assistant does when asked to “play your favorite song title”.
override fun search(query: String, extras: Bundle): List<MediaMetadataCompat> {
val matchKeys = focusedSearchMap[extras[MediaStore.EXTRA_MEDIA_FOCUS]] ?: return emptyList()
return filter { song ->
matchKeys.fold(true) { acc, pair ->
acc && (extras[pair.first] == song.getString(pair.second))
}
}
}
Nice and short! Oh, but the really interesting part is what that focusedSearchMap
contains, but that’s all the way at the top of the file.
private val focusedSearchMap = mapOf(
MediaStore.Audio.Genres.ENTRY_CONTENT_TYPE to listOf(
Pair(EXTRA_MEDIA_GENRE, MediaMetadataCompat.METADATA_KEY_GENRE)
),
MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE to listOf(
Pair(MediaStore.EXTRA_MEDIA_ARTIST, MediaMetadataCompat.METADATA_KEY_ARTIST)
),
MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE to listOf(
Pair(MediaStore.EXTRA_MEDIA_ARTIST, MediaMetadataCompat.METADATA_KEY_ARTIST),
Pair(MediaStore.EXTRA_MEDIA_ALBUM, MediaMetadataCompat.METADATA_KEY_ALBUM)
),
MediaStore.Audio.Media.ENTRY_CONTENT_TYPE to listOf(
Pair(MediaStore.EXTRA_MEDIA_TITLE, MediaMetadataCompat.METADATA_KEY_TITLE),
Pair(MediaStore.EXTRA_MEDIA_ALBUM, MediaMetadataCompat.METADATA_KEY_ALBUM),
Pair(MediaStore.EXTRA_MEDIA_ARTIST, MediaMetadataCompat.METADATA_KEY_ARTIST)
))
Still, not so bad, and we can see that a search by genre checks the genre, search by album checks the artist and album, etc…
But that’s not the code I used for UAMP. There, I wrote this:
override fun search(query: String, extras: Bundle): List<MediaMetadataCompat> {
// First attempt to search with the "focus" that's provided in the extras.
val focusSearchResult = when (extras[MediaStore.EXTRA_MEDIA_FOCUS]) {
MediaStore.Audio.Genres.ENTRY_CONTENT_TYPE -> {
// For a Genre focused search, only genre is set.
val genre = extras[EXTRA_MEDIA_GENRE]
Log.d(TAG, "Focused genre search: '$genre'")
filter { song ->
song.genre == genre
}
}
MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE -> {
// For an Artist focused search, only the artist is set.
val artist = extras[MediaStore.EXTRA_MEDIA_ARTIST]
Log.d(TAG, "Focused artist search: '$artist'")
filter { song ->
song.artist == artist
}
}
MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE -> {
// For an Album focused search, album and artist are set.
val artist = extras[MediaStore.EXTRA_MEDIA_ARTIST]
val album = extras[MediaStore.EXTRA_MEDIA_ALBUM]
Log.d(TAG, "Focused album search: album='$album' artist='$artist")
filter { song ->
song.artist == artist && song.album == album
}
}
MediaStore.Audio.Media.ENTRY_CONTENT_TYPE -> {
// For a Song (aka Media) focused search, title, album, and artist are set.
val title = extras[MediaStore.EXTRA_MEDIA_TITLE]
val album = extras[MediaStore.EXTRA_MEDIA_ALBUM]
val artist = extras[MediaStore.EXTRA_MEDIA_ARTIST]
Log.d(TAG, "Focused media search: title='$title' album='$album' artist='$artist")
filter { song ->
song.artist == artist && song.album == album
&& song.title == title
}
}
else -> {
// There isn't a focus, so no results yet.
emptyList()
}
}
return focusSearchResult
}
Wow! That’s a lot more code, but… it’s also a lot easier to see what’s going on, isn’t it? Even aside from the comments, each case pulls out the parameters its interested in, and then performs a comparison inline.
When I asked a SWE to review my code they suggested bundling up some of the logic, but I decided to leave it after I showed this method to a person who a) doesn’t know anything about media on Android, and b) doesn’t know Kotlin, but they could follow it easily.
This isn’t always the case, of course, and it isn’t the only difference between production and sample code. It was something that finally ‘clicked’ for me though, and I’m hoping that helps me write better samples in the future.