Designing Dependencies: The Problem

Episode #110 • Jul 27, 2020 • Subscriber-Only

Let’s take a moment to properly define what a dependency is and understand why they add so much complexity to our code. We will begin building a moderately complex application with three dependencies, and see how it complicates development, and what we can do about it.

The Problem
Introduction
00:05
What is a dependency?
01:40
An app with dependencies
06:02
An API dependency
08:50
Controlling an API
19:08
Protocol-oriented problems
28:13

Unlock This Episode

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

Introduction

Today we are going to begin a series of episodes on “designing dependencies.” We’ve talked about dependencies quite a bit on Point-Free in the past, starting over 2 years ago when we introduced the idea of dependency injection and how it can be made quite easy by packaging all of your dependencies up into one mega struct. And then earlier this year we showed how to bake that notion of dependency injection directly into the Composable Architecture so that each feature of your application precisely describes exactly what dependencies it needs to do its job, and then as you decompose your app into smaller and smaller components you simply describe how to slice up the entire world of dependencies into just the subset a particular component needs.

There are some really powerful ideas in those episodes, but what we haven’t done yet is discuss exactly how to design dependencies when you are writing code in this style. We’ve shown a few hints of how to do this, for example we strongly recommend forgoing classes, protocols and manager objects, and instead use simple data types. It can be a little uncomfortable to disband with those tools since they’ve been in our tool belt for so long, but there is a lot of power in doing so. So, we want to spend a little bit more time with this style of dependencies and show how to wrap some pretty complex functionality in simple data types instead of using protocols, and we’ll show that this unlocks some truly amazing functionality.

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. Our application currently has no error handling around API requests. Update the view model and view to show an alert when a weather request fails. Use the failed weather mock to verify that things look as they should.

  2. When we added a delay to the happy path weather mock we found the user experience to be lacking. Update the view model and view to render a loading indicator when the weather request is in flight. Use the delayed happy path weather mock to verify that things look as they should.

References

Dependency Injection Made Easy

Brandon Williams & Stephen Celis • Monday May 21, 2018

Our first episode on dependencies, where we show that they can be wrangled quite quickly and effectively by introducing a global, mutable instance of a struct.

Today we’re going to control the world! Well, dependencies to the outside world, at least. We’ll define the “dependency injection” problem and show a lightweight solution that can be implemented in your code base with little work and no third party library.

Dependency Injection Made Comfortable

Brandon Williams & Stephen Celis • Monday Jun 4, 2018

Let’s have some fun with the “environment” form of dependency injection we previously explored. We’re going to extract out a few more dependencies, strengthen our mocks, and use our Overture library to make manipulating the environment friendlier.

Composable Architecture: Dependency Management

Brandon Williams & Stephen Celis • Monday Feb 17, 2020

We made dependencies a first class concern of the Composable Architecture by baking the notion of dependencies directly into the definition of its atomic unit: the reducer.

How to Control the World

Stephen Celis • Monday Sep 24, 2018

Stephen gave a talk on our Environment-based approach to dependency injection at NSSpain 2018. He starts with the basics and slowly builds up to controlling more and more complex dependencies.

Side Effects

Brandon Williams & Stephen Celis • Monday Feb 5, 2018

In our first episode on side effects we first show that side effects that depend on the outside world can be controlled by passing the dependency as input.

Side effects: can’t live with ’em; can’t write a program without ’em. Let’s explore a few kinds of side effects we encounter every day, why they make code difficult to reason about and test, and how we can control them without losing composition.

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.

Protocol Oriented Programming is Not a Silver Bullet

Chris Eidhof • Thursday Nov 24, 2016

An old article detailing many of the pitfalls of Swift protocols, and how often you can simplify your code by just using concrete datatypes and values. Chris walks the reader through an example of some networking API library code, and shows how abstracting the library with protocols does not give us any tangible benefits, but does increase the complexity of the code.