Async Functional Refactoring

Episode #40 • Dec 17, 2018 • Subscriber-Only

The snapshot testing library we have been designing over the past few weeks has a serious problem: it can’t snapshot asynchronous values, like web views and anything that uses delegates or callbacks. Today we embark on a no-regret refactor to fix this problem with the help of a well-studied and well-understood functional type that we have discussed numerous times before.

Async Functional Refactoring
Introduction
00:05
Snapshotting web views
01:47
A web view strategy
07:45
Async snapshotting
14:08
An async web view strategy
23:18
Async pullback
27:52
What’s the point?
32:34

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

Introduction

We’ve spent the past few weeks working on a real-world library in order to explore the ins-and-outs of protocol-oriented programming (part 1, part 2, part 3). We saw that we can improve the designs of our APIs by scrapping our protocols and using concrete data types, a process we explored in depth in our series on protocol witnesses.

While the library we’ve built is already incredibly powerful and flexible, it has a serious limitation: it can’t snapshot values that are asynchronous. This is a pretty big limitation since many values can’t be snapshot until a callback is invoked or a delegate method is called, and in fact it completely prevents us from writing snapshot tests for web views!

This was a real problem we encountered in using this library because we take snapshots of web views to write tests for this very site, which is written in Swift and completely open source. Web views have this exact problem, where they require waiting for a delegate method to be called and a callback to be invoked to produce a snapshot image.

The solution turned out to be incredibly simple and we did it in a matter of minutes. The best part was that our refactor was completely guided by some of the functional programming ideas we’ve covered on this very site. In fact, a type we’ve discussed a number of times on this series came to the rescue.

So today we want to show why this async snapshot thing really is a problem with the current library design, and show how a to solve this in a really nice, simple way.

This episode is for subscribers only.

Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

See plans and pricing

Already a subscriber? Log in

Exercises

  1. Redefine pullback on Snapshotting in terms of asyncPullback.

  2. While we were introduced to pullback by doing a deep dive on contravariance, asyncPullback seems to have a different shape.

    Extract the snapshot logic of asyncPullback to a more general function on Parallel. What is the shape of this function? Is it familiar? What other types from past episodes have a similar operation?

References

Protocol-Oriented Programming in Swift

Apple • Tuesday Jun 16, 2015

Apple’s eponymous WWDC talk on protocol-oriented programming:

At the heart of Swift’s design are two incredibly powerful ideas: protocol-oriented programming and first class value semantics. Each of these concepts benefit predictability, performance, and productivity, but together they can change the way we think about programming. Find out how you can apply these ideas to improve the code you write.

uber/ios-snapshot-test-case

Uber, previously Facebook

Facebook released a snapshot testing framework known as FBSnapshotTestCase back in 2013, and many in the iOS community adopted it. The library gives you an API to assert snapshots of UIView’s that will take a screenshot of your UI and compare it against a reference image in your repo. If a single pixel is off it will fail the test. Since then Facebook has stopped maintaining it and transfered ownership to Uber.

Snapshot Testing in Swift

Stephen Celis • Friday Sep 1, 2017

Stephen gave an overview of snapshot testing, its benefits, and how one may snapshot Swift data types, walking through a minimal implementation.