Protocol-Oriented Library Design: Part 1

Episode #37 • Nov 12, 2018 • Subscriber-Only

Perhaps the most popular approach to code reuse and extensibility in Swift is to liberally adopt protocol-oriented programming, and many Swift libraries are designed with protocol-heavy APIs. In today’s episode we refactor a sample library to use protocols and examine the pros and cons of this approach.

Protocol-Oriented Library Design: Part 1
Introduction
00:05
An overview of the problem
01:42
Generalizing screen shot tests
07:08
Generalizing the snapshot format
10:45
Till next time…
22:22

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 four episodes taking a deep study of protocols and exploring how their features can be represented using concrete datatypes and functions, and we’ve seen how in doing so we can address some of the shortcomings and complexities of protocols while unlocking a world of composition that was previously hidden. We’ve even suggested that the way we design our APIs could be dramatically improved by eschewing protocols in favor of these concrete datatypes and functions. That’s quite the claim, seeing as we’ve spent four episodes on the subject without ever demonstrating this! So much for “what’s the point,” huh!?

Well this week we finally put our theory to the test! We’re going to refactor a small library to be more flexible and extensible by abstracting away part of its design. We’ll start in the protocol-oriented way because that’s how we’re told to design these kinds of things in Swift. It’ll give us an opportunity to analyze the problems that protocols have that we think concrete datatypes and functions can solve.

We want to stress that we do not consider the actual library we are design to be the most interesting aspect of this topic, although it is quite cool. The real topic we are dissecting here is that of how we approach library design in Swift, and what lessons from our series on protocol witnesses can we apply so that we avoid the pitfalls of protocols.

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. There’s one protocol requirement we missed: the fact that we hard-code the path extension of the snapshot reference to “png”. Move this requirement into our protocols. Which protocol does it belong to?

  2. Add a default implementation of path extension so that those conforming their own types to be Snapshottable do not need to declare "png" every time.

  3. Showing the difference between two images is a matter of using a Core Image difference filter. Unfortunately, Apple provides no such API to show the difference between two strings. Implement a line diff algorithm to describe the difference between two strings in Swift.

    A popular, human-readable algorithm is called the “patience diff”. Here are some resources:

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.

Modern Swift API Design

Apple • Wednesday Jan 2, 2019

As of WWDC 2019, Apple no longer recommends that we “start with a protocol” when designing our APIs. A more balanced approach is discussed instead, including trying out concrete data types. Fast forward to 12:58 for the discussion.

Every programming language has a set of conventions that people come to expect. Learn about the patterns that are common to Swift API design, with examples from new APIs like SwiftUI, Combine, and RealityKit. Whether you’re developing an app as part of a team, or you’re publishing a library for others to use, find out how to use new features of Swift to ensure clarity and correct use of your APIs.

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.

Protocol Witnesses: App Builders 2019

Brandon Williams • Friday May 3, 2019

Brandon gave a talk about “protocol witnesses” at the 2019 App Builders conference. The basics of scraping protocols is covered as well as some interesting examples of where this technique really shines when applied to snapshot testing and animations.

Protocol-oriented programming is strongly recommended in the Swift community, and Apple has given a lot of guidance on how to use it in your everyday code. However, there has not been a lot of attention on when it is not appropriate, and what to do in that case. We will explore this idea, and show that there is a completely straightforward and mechanical way to translate any protocol into a concrete datatype. Once you do this you can still write your code much like you would with protocols, but all of the complexity inherit in protocols go away. Even more amazing, a new type of composition appears that is difficult to see when dealing with only protocols. We will also demo a real life, open source library that was originally written in the protocol-oriented way, but after running into many problems with the protocols, it was rewritten entirely in this witness-oriented way. The outcome was really surprising, and really powerful.