We’ve now got a moderately complex application that makes non-trivial use of 3 dependencies: a weather API client, a network path monitor, and a location manager. The weather API dependency was quite simple in that it merely fires off network requests that can either return some data or fail. The path monitor client was a bit more complex in that it bundled up the idea of starting a long-living effect that emits network paths over time as the device connection changes, as well as the ability to cancel that effect. And Core Location was the most complicated by far. It allows you to ask the user for access to their location, and then request their location information, which is a pretty complex state machine that needs to be carefully considered.
So we’ve accomplished some cool things, but I think it’s about time to ask “what’s the point?” We like to do this at the end of each series of episodes on Point-Free because it gives us the opportunity to truly justify all the work we have accomplished so far, and prove that the things we are discussing have real life benefits, and that you could make use of these techniques today.
And this is an important question to ask here because we are advocating for something that isn’t super common in the Swift community. The community already has an answer for managing and controlling dependencies, and that’s protocols. You slap a protocol in front of your dependency, make a live conformance and a mock conformance of the protocol, and then you are good to go. We showed that this protocol-oriented style comes with a bit of boilerplate, but if that’s the only difference from our approach is it really worth deviating from it?
Well, we definitely say that yes, designing your dependencies in this style has tons of benefits, beyond removing some boilerplate. And to prove this we are going to write a full test suite for our feature, which would have been much more difficult to do had we controlled things in a more typical, protocol-oriented fashion.