Software Dev

Results from builders 🧱

Looking back, it’s interesting to appreciate the various Swift advancements that allowed SwiftUI to be created: namely opaque return types, property wrappers, and result builders.

It reminds me of all the things invented for the Apollo moon mission.

In particular, I’ve been appreciating result builders lately. They’re a useful, general-purpose feature on their own terms. I just created a cache-key builder at work which greatly simplified some pretty ugly and bug-prone logic for createing a cache key string.

I’ve seen a couple even more interesting result builds recently too.

👉 RequestDL, which simplifies the creation of network requests

👉 TextBuilder, which streamlines the creation of complex Text values

These are just two examples I’ve seen on iOS Dev Weekly once or twice, although I’m sure there are plenty more result builders out there to play with.

Software Dev

Clarity is (even) more important than brevity

I have published a post or two about the powers of brevity. But we programmers sometimes take it too far.

Can someone tell me what these integers represent?

case upc(Int, Int, Int, Int)

No? Me either.

This is how associated values are pretty much always done in Swift. But thanks to this post by Marco Eidinger via iOS Dev Weekly, I discovered something new and clarifying: it turns out that you can actually label your enum’s associated values too. People just don’t do it for some reason. 🤷🏻‍♂️

Can you tell me what the integers represent now?

case upc(numberSystem: Int, manufacturer: Int, product: Int, check: Int)

Isn’t that a little easier to understand?

I run into the assumption sometimes where people mistake brevity for efficiency. Brevity shouldn’t mean sacrificing valuable context for slightly fewer words. Thanks to the Marco Eidinger post for pointing this out explicitly. 👍

Clarity is more important than brevity.

Marco Eidinger
Software Dev

“Sketching” out an app prototype

I’ve learned a lot making apps for big companies, mostly about process: how a good continuous integration process works, how code reviews can be productive (or not productive), how to break a big app into smaller components so lots of people work on related things at the same time.

Still, it’s helpful to do something fresh and new 100% on your own from time to time. Doing something new all your own, you get to try any architecture you want, go all in on the latest asynchronous programming techniques, fully embrace the amazing new(ish) declarative/reactive view layer, and even try out a new CI framework to two.

But the most fun part of all is developing the idea of your app. What does your app do? How exactly does it work from a user perspective? And what do the screens look like in detail?

👉This time around, I’m prototyping my new app idea on my phone so that I can get a feel for how it works in my hands before writing all that code. ^

I tried out a few prototyping tools. After looking at some basic options and some pretty involved options (arguably too involved), I landed on a pretty “sketchy” Mac app that handles full-on detailed UI design and kind of does mobile prototypes through its “mirroring” iOS app. Perfect. 👌

👉 Sketch | mirroring app

I will say that Figma looks pretty promising as well. What nudged me over to Sketch was Apple’s Sketch-compatible design resources. There are some third-party iOS design resources for Figma, but I’d rather go with Apple’s official offering. Sorry, Figma. 🤷🏻‍♂️

So my new design process is this, now that I’ve finally learned Sketch:

Rough sketch on paper ➡ realistic visual design in Sketch ➡ prototype on a phone ➡ code

My instinct is to talk about the app itself while it’s in progress, but sorry… that’s top secret for now. 🕵️‍♀️

Software Dev

The what, why, and how of the RIBs mobile architecture

Continuing my mobile architecture kick, let’s look next at RIBs. In this case, RIBs is not a delicious, slow-cooked entrée but rather a software architecture that Uber developed a few years ago.

Why RIBs?

RIBs lets Uber’s 200+ mobile developers knock out features quickly without stomping all over each other.

The original design worked well for the first three developers. (via Uber)

Back in 2016, the Uber team had just expanded from three mobile developers several hundred developers. And the app’s design did not scale well to that large of a team. From both a UX/design perspective and a technical perspective, it became difficult to add features. Citing “quite a few examples of, you know, pretty bad UI”, the design team bravely demanded a rewrite.

The design team came in and said, you know, ‘We probity have to redesign the whole application.’… Everybody was super concerned.

Classic engineering understatement

The Uber engineering team resisted the rewrite (which can be nightmare for a large app) for a year, but eventually came around to its necessity. So they defined a few goals for the new design (99.99% reliability, scaling to ~1000 developers, …) and experimented with that they knew – MVC, MVVM, MVP, and VIPER.

But nothing worked. 🤦🏻‍♂️

The problem is that all these architectures are based around the view, and if you base everything around the view, everybody has to integrate at one point, and that becomes a mess at the scale that we have.

The state tree solution

So they came up with a fresh idea, which was to model the whole app as a state tree. Much to their surprise, it worked really well. 🤷🏻‍♂️

We haven’t found an application that you couldn’t model with this very nicely.

A special architecture subteam spent six months reworking some “super ugly looking” core use cases and then turned the rest of the team loose on the new architecture.

Now we have RIBs and the modern Uber app.

Whoa! That looks too easy! (via Uber)

But how does it work?

A RIB is a combination of Router/Interactor/Builder (plus Presenter/View, but I guess “RIBPV” doesn’t sound very good). Each RIB represents a state of the app, which can have sub-states as children.

For example, the root of the tree has two children: logged-out and logged-in. Every RIB under logged-in can safely assume that the user is logged in, and it has an authenticated user token 🔑 to prove it.

RIBs can present themselves hierarchically on top of each other on the screen. Some RIBs just do background support don’t show themselves at all.

No auth token for you, left side. (via Uber)

For more…

Pretty cool, eh?

Okay, I’ll stop here since this is a conceptual overview (aka a teaser) and not a tutorial. ✋ For more details, see the original Uber presentation below or try it yourself.

Up next in the architectural series, we’ll attack The Composable Architecture, which is responsible for at least one cool game and, like RIBS, has a concrete implementation rather than just a bunch of vague ideas. 🙏

Software Dev

Scaling up: how AirBnB ships a quality, gigantic app

AirBnB’s iPhone app has a gigantic code base (1.5 million lines of first-party code), a giant mobile team (75 iOS engineers), and a long history (first commit: 2010).

Over time, their app got so big and complex that the project began to take minutes to open (not build) in Xcode. Developers had to use the USB port on the right side of their MacBooks to avoid thermal throttling. 🤦🏻‍♂️

Given all this sheer complexity, the team there made some clever adjustments to develop, test, and ship their app pretty efficiently. Check it out.

👉 Designing for Productivity in a Large-Scale iOS Application

Among the highlights are independent modules called Dev Apps.

A Dev App allows a product developer to iterate on their feature’s UI and much of its business logic while building a fraction of the overall Airbnb application.

Dev App for an existing Airbnb module

For dependencies across modules, module types allow for “visibility rules” to minimize and document dependencies.

Also, AirBnB uses the Buck build system to keep Xcode projects out of source control (bye bye, Xcode project merge conflicts).

via iOS Dev Weekly.