<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xml" href="/feed.xslt.xml"?><feed xmlns="http://www.w3.org/2005/Atom"><generator uri="http://jekyllrb.com" version="3.3.1">Jekyll</generator><link href="https://sfsoftwareist.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sfsoftwareist.com/" rel="alternate" type="text/html" /><updated>2019-07-22T20:04:31+00:00</updated><id>https://sfsoftwareist.com/</id><title>sf softwareist</title><subtitle>iOS app development advice
</subtitle><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><entry><title>An introduction to YAIA</title><link href="https://sfsoftwareist.com/2019/07/20/Yay-yeah/" rel="alternate" type="text/html" title="An introduction to YAIA" /><published>2019-07-20T00:00:00+00:00</published><updated>2019-07-20T00:00:00+00:00</updated><id>https://sfsoftwareist.com/2019/07/20/Yay-yeah</id><content type="html" xml:base="https://sfsoftwareist.com/2019/07/20/Yay-yeah/">&lt;p&gt;&lt;img src=&quot;/images/fulls/ddp-hpLQb1pqPtE-unsplash.jpg&quot; class=&quot;fit image&quot; /&gt;
&lt;em&gt;Photo by DDP on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With so many iOS architectures out there these days, I was sure that one would
speak to me. I’ve tried Viper, MVVM, ReSwift and others. They each had their
merits but ultimately their shortcomings prevented me from using them. So what
did I do?? I Invent one more architecture! And what is the worst name I could come
up with for it? Glad you asked! I call it “Yet Another iOS Archtecture” or YAIA
(pronounced ‘Yay-yeah!’).&lt;/p&gt;

&lt;h3 id=&quot;goals-of-yaia&quot;&gt;Goals of YAIA&lt;/h3&gt;
&lt;p&gt;An architecture should have goals, otherwise its just
a collection of arbitrary rules which is no fun. Below I’ll describe some of the
values that motivated YAIA.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Writing unit tests should be painless&lt;/strong&gt;. This is the main goal of YAIA and
everything else falls out of that. I’d like to write test without mocks, fakes
or injecting anything. I’d like to avoid testing async code and I certainly
don’t want to do any IO such as reading files or hitting a database in my
tests. I’d like my test to run as quickly as possible.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;The architecture should be flexible and light weight&lt;/strong&gt;. It doesn’t require
implementers to create classes X, Y and Z &lt;em&gt;and&lt;/em&gt; protocols for each of those
classes (I’m looking at you, Viper!). I also don’t want tests to implement
stubs or mocks to facilitate testing.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Changes should be easy to make.&lt;/strong&gt; This is related to points one and two. I
don’t want to discourage users from making improvements because it will
require changes in many places or might break something.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Simple.&lt;/strong&gt; No unnecessary abstractions or classes. Abstractions such as
protocols or base classes can make your code flexible but they also make it
harder to follow. Every class or protocol has to earn its
place. If it doesn’t, it’s out.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To achieve these goals, I cherry-picked features from a few different
architectures I had used in the past. From ReSwift,
an implementation of the redux pattern, I borrowed its emphasis on value types
and keeping data and logic in one place. In YAIA, the models that represent the business
and app logic are all value types (as opposed to reference types). The inputs
and outputs to this values-only system are also values. This makes results easy to
verify by simply making them &lt;code class=&quot;highlighter-rouge&quot;&gt;Equatable&lt;/code&gt;. A nice side effect of a values only
system is that it’s impossible for it to contain any async code paths (a struct
or other value type can’t be captured by reference in an escaping closure).
This keeps tests simple and running fast.&lt;/p&gt;

&lt;p&gt;While there are many things to dislike about Viper, one of its tenants is that
services should be hidden behind interfaces. This is one place where an
abstraction can be nice. Types from services shouldn’t creep into the
business logic. What this means for iOS is that Core Data’s NSManagedObjects,
wont be referenced in the values-only core. Instead, we copy data out of Core
Data and into plain old Swift structs. These value type are then passed into our
system. This allows us to test our system without instantiating Core Data
objects. It also means that I can switch persistence technology without too
much pain since the Core Data dependencies are contained; our business logic
layer will be unaffected when we change the type of database we’re using.&lt;/p&gt;

&lt;h3 id=&quot;a-brief-overview&quot;&gt;A brief overview&lt;/h3&gt;
&lt;p&gt;I’ve described this architecture &lt;a href=&quot;/2017/10/04/pt-1-effective-testing/&quot;&gt;in&lt;/a&gt;
&lt;a href=&quot;/2018/05/08/pt-2-testable-swift/&quot;&gt;previous&lt;/a&gt;
&lt;a href=&quot;/2018/05/31/pt-3-swift-testability-by-example/&quot;&gt;posts&lt;/a&gt; but I’ll go over the
highlights here. For a given screen you’d like to build, a login screen
perhaps, the class that ties the different elements together is called a
&lt;code class=&quot;highlighter-rouge&quot;&gt;Scene&lt;/code&gt; (naming things is hard). In &lt;a href=&quot;https://github.com/Tylerc230/LoginExample&quot;&gt;this simple
example&lt;/a&gt; of a login screen I’ve
called it &lt;code class=&quot;highlighter-rouge&quot;&gt;LoginScene&lt;/code&gt;. It behaves similarly to the &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; in MVVM. In
YAIA, it has a weak reference to the view controller via a protocol. This is
one of the few places that I use a protocol in YAIA. The view controller has a
strong reference to the Scene so that the Scene’s lifecycle is tied to the view
controller’s.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Scene&lt;/code&gt; object contains a &lt;code class=&quot;highlighter-rouge&quot;&gt;State&lt;/code&gt; object which is some sort of value type;
generally a struct or enum. I will discuss the &lt;code class=&quot;highlighter-rouge&quot;&gt;State&lt;/code&gt; object further but
for now understand that the bulk of the logic resides here. The
&lt;code class=&quot;highlighter-rouge&quot;&gt;Scene&lt;/code&gt; object may also have network or database services as
dependencies. The &lt;code class=&quot;highlighter-rouge&quot;&gt;Scene&lt;/code&gt;’s job is to move data between the &lt;code class=&quot;highlighter-rouge&quot;&gt;State&lt;/code&gt; object and
these dependencies (the UI is also a dependency).&lt;/p&gt;

&lt;p&gt;It is the &lt;code class=&quot;highlighter-rouge&quot;&gt;Scene&lt;/code&gt;’s responsibility to take input from the UI, a button press
for instance, and pass it to the &lt;code class=&quot;highlighter-rouge&quot;&gt;State&lt;/code&gt; object for processing. At this point,
the &lt;code class=&quot;highlighter-rouge&quot;&gt;State&lt;/code&gt; object might update its internal state and possibly return a
value type indicating the IO to be performed. The &lt;code class=&quot;highlighter-rouge&quot;&gt;Scene&lt;/code&gt; would then tell the
appropriate interface to perform the request (eg network request).
The result of this request is then fed back into the &lt;code class=&quot;highlighter-rouge&quot;&gt;State&lt;/code&gt; for processing.
If the &lt;code class=&quot;highlighter-rouge&quot;&gt;State&lt;/code&gt; object determines a view transition is required, it will return
an enum representing that transition which is then passed to a &lt;a href=&quot;http://khanlou.com/2015/10/coordinators-redux/&quot;&gt;flow
coordinator&lt;/a&gt; which handles the
transition.&lt;/p&gt;

&lt;p&gt;To update the UI, the &lt;code class=&quot;highlighter-rouge&quot;&gt;State&lt;/code&gt; will return a &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; instance which is
passed to the ui by the &lt;code class=&quot;highlighter-rouge&quot;&gt;Scene&lt;/code&gt;. In YAIA, a &lt;code class=&quot;highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; is a simple data
transfer object (a value type of course) that contains all the info the view
needs to update itself with.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/fulls/YAIA.jpg&quot; class=&quot;fit image&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;but-how-does-all-this-help-me&quot;&gt;But how does all this help &lt;em&gt;me&lt;/em&gt;?&lt;/h3&gt;
&lt;p&gt;How does YAIA achieve the goals listed above? Since the main
goal is to make software testable, I had to figure out what type of code
is easily tested. I discovered that if you separate the logic and state 
from the IO, the state/logic portion becomes much more testable. The
easiest thing in the world to test is a function that takes values in and
returns a value. I wouldn’t hesitate to write a test for &lt;code class=&quot;highlighter-rouge&quot;&gt;func add(a: Int, b:
Int)-&amp;gt;Int&lt;/code&gt;. It takes values as inputs and returns a value. It doesn’t
have any internal state, doesn’t read from a database and doesn’t have any
dependencies that make the tests complicated. A test based on this method would
be easy to read and debug.&lt;/p&gt;

&lt;p&gt;The opposite end of the spectrum is a class which handles all of its IO
internally and has its logic and IO coupled together. This class
may be dependent on other complex classes which must be recreated in a test
environment or mocked. When testing this code, the setup ends up being
many times longer than the actual test and verification portion of the test.
This means the tests are brittle and hard to read. Additionally, since they
take so much effort to configure, developers will be less inclined to write
tests in the first place. By making the &lt;code class=&quot;highlighter-rouge&quot;&gt;State&lt;/code&gt; object a value which doesn’t do
any IO, we side step most of the difficulties above.&lt;/p&gt;

&lt;p&gt;To achieve flexibility, I recommend using your best judgment regarding when to
use the pieces above.  If you’re building a screen with some text and a single button,
put all the logic in the view controller and move on. This is just one
approach to separating logic from IO but there are other ways to achieve the
same goal. When it comes to architecture, one size does not fit all.&lt;/p&gt;

&lt;p&gt;In the end, the specific names of the components and the exact
responsibilities of a given class don’t matter. What matters it being able to
write software that is easily verified by unit test. This is achieved by isolating
logic in value types and away from the async code and IO. By doing that, you
are one step closer to making tests work for you.&lt;/p&gt;</content><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><summary>Photo by DDP on Unsplash</summary></entry><entry><title>Neovim and Swift, a Match Made in Heaven</title><link href="https://sfsoftwareist.com/2018/12/05/swift-LSP-and-vim/" rel="alternate" type="text/html" title="Neovim and Swift, a Match Made in Heaven" /><published>2018-12-05T00:00:00+00:00</published><updated>2018-12-05T00:00:00+00:00</updated><id>https://sfsoftwareist.com/2018/12/05/swift-LSP-and-vim</id><content type="html" xml:base="https://sfsoftwareist.com/2018/12/05/swift-LSP-and-vim/">&lt;p&gt;&lt;img src=&quot;/images/fulls/justin-greene-137326-unsplash.jpg&quot; class=&quot;fit image&quot; /&gt;
&lt;em&gt;Photo by Justin Greene on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every once in a while two technologies will converge, yielding a sum that is greater than their parts. If you are lucky enough, you will witness just such an event once or maybe twice in your life. Swift LSP combined with Neovim is one of these cataclysmic events. Hyperbole aside, I’m really excited about the prospect of effectively writing Swift outside of XCode. Once the project was announced, I couldn’t wait to dive in and integrate it with my favorite editor.&lt;/p&gt;

&lt;h4 id=&quot;what-is-swift-lsp&quot;&gt;What is Swift LSP?&lt;/h4&gt;
&lt;p&gt;Recently the Swift team announced that they would be releasing an LSP server (Language Server Protocol) for Swift. An LSP server, developed for a particular language, allows any editor which implements an LSP client to attain many IDE like features for editing that language, for free. These features include code completion, formatting, refactoring, go to definition, find references, contextual documentation look up and much more.&lt;/p&gt;

&lt;p&gt;Before LSP, each IDE or editor had to implement all the above features for each language they supported. As a result, most editors would have a patchwork of functionality implemented for the few languages they supported. Polyglot developers would have to learn a new IDE for each language they used or do without advanced editing features.&lt;/p&gt;

&lt;p&gt;While the Swift team has made amazing progress on the LSP server, it is still an immature project. Currently the only supported LSP features are code completion, go to definition, documentation lookup and find all references. Even though this is only a small subset of what LSP has to offer, it is already a big boost to developer productivity.&lt;/p&gt;

&lt;h3 id=&quot;how-it-works&quot;&gt;How it works&lt;/h3&gt;
&lt;p&gt;Before I get into how to integrate the server with Neovim, I need to talk a bit about how an LSP server works. An LSP server needs to know how all the source files in a project relate to each other. Therefore, the server must know something about how the project is built. It needs to know which files are included in the project, where to find dependencies and which flags are passed to the compiler. The Swift LSP uses the Swift Package Manager to understand how the project is built. As such, if you want to use Swift LSP, your project needs be a Swift package. I wont go into detail on creating a package but you will need a Package.swift at the root of your project.&lt;/p&gt;

&lt;p&gt;You will also need to install the Swift tool chain describe on the Swift LSP &lt;a href=&quot;https://github.com/apple/sourcekit-lsp&quot;&gt;website&lt;/a&gt;. You will then need to define &lt;code class=&quot;highlighter-rouge&quot;&gt;SOURCEKIT_TOOLCHAIN_PATH&lt;/code&gt; in your &lt;code class=&quot;highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;. It will look something like &lt;code class=&quot;highlighter-rouge&quot;&gt;export SOURCEKIT_TOOLCHAIN_PATH=&amp;lt;path to toolchain&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Additionally, we will need an LSP Client. In our case, we will use &lt;a href=&quot;https://github.com/autozimu/LanguageClient-neovim&quot;&gt;LanguageClient-neovim&lt;/a&gt; (LCN form here on out), a Neovim plugin. Not only will this give you IDE like features for Swift but also for any other language implementing an LSP server.&lt;/p&gt;

&lt;p&gt;I’ve created a demo repository that handles installing all the required Neovim plugins, downloads and build the LSP server and implements a small Swift package to experiment with. It can be found &lt;a href=&quot;https://github.com/Tylerc230/SwiftNeoVimLSP&quot;&gt;here&lt;/a&gt;. It uses the Dein plugin manager for Neovim to install plugins. It also uses Deoplete for code completion. LCN will fallback to use omniFunc to do completion so Deoplete isn’t strictly required. The project uses its own vimrc and puts all plugins in the &lt;code class=&quot;highlighter-rouge&quot;&gt;cache&lt;/code&gt; folder so your Neovim installation should not be affected.&lt;/p&gt;

&lt;h3 id=&quot;how-to-use-the-demo-repo&quot;&gt;How to use the demo repo&lt;/h3&gt;
&lt;p&gt;To use the repository, there are 3 steps:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Clone &lt;a href=&quot;https://github.com/Tylerc230/SwiftNeoVimLSP&quot;&gt;my repo&lt;/a&gt;, cd into it and &lt;code class=&quot;highlighter-rouge&quot;&gt;./init.sh&lt;/code&gt;.
This will fetch the &lt;code class=&quot;highlighter-rouge&quot;&gt;sourcekit-lsp&lt;/code&gt; submodule, build it and build the demo Swift package found at &lt;code class=&quot;highlighter-rouge&quot;&gt;MySwiftPackage&lt;/code&gt;. It will also update neovim with the Dein, Deoplete and LCN plugins.&lt;/li&gt;
  &lt;li&gt;Download and install the Swift toolchain recommended on the &lt;a href=&quot;https://github.com/apple/sourcekit-lsp&quot;&gt;sourcekit-lsp website&lt;/a&gt;(&lt;a href=&quot;https://swift.org/builds/development/xcode/swift-DEVELOPMENT-SNAPSHOT-2018-12-04-a/swift-DEVELOPMENT-SNAPSHOT-2018-12-04-a-osx.pkg&quot;&gt;12-4-2018&lt;/a&gt; at the time of this writing). Make sure &lt;code class=&quot;highlighter-rouge&quot;&gt;SOURCEKIT_TOOLCHAIN_PATH&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;tryit.sh&lt;/code&gt; points to the newly installed xctoochain file.&lt;/li&gt;
  &lt;li&gt;Run &lt;code class=&quot;highlighter-rouge&quot;&gt;tryit.sh&lt;/code&gt; which will set some environment variables and launch Neovim into the &lt;code class=&quot;highlighter-rouge&quot;&gt;main.swift&lt;/code&gt; file. At this point you are ready to start experimenting!&lt;/li&gt;
  &lt;li&gt;In Neovim, run :UpdateRemotePlugins&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;things-to-try&quot;&gt;Things to try&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;If you move the cursor over a symbol eg. &lt;code class=&quot;highlighter-rouge&quot;&gt;MyStruct&lt;/code&gt; and type &lt;code class=&quot;highlighter-rouge&quot;&gt;gd&lt;/code&gt; in normal mode. You will be taken to the &lt;code class=&quot;highlighter-rouge&quot;&gt;MyStruct&lt;/code&gt; definition in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Greeter.swift&lt;/code&gt; file. &lt;code class=&quot;highlighter-rouge&quot;&gt;gd&lt;/code&gt; is mapped to &lt;code class=&quot;highlighter-rouge&quot;&gt;:call LanguageClient#textDocument_definition()&amp;lt;CR&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Open a line under line 4 and type &lt;code class=&quot;highlighter-rouge&quot;&gt;my_array.&lt;/code&gt;. You should see a list of all methods and properties defined by &lt;code class=&quot;highlighter-rouge&quot;&gt;Array&lt;/code&gt;. You should be able to Tab through all the options.&lt;/li&gt;
  &lt;li&gt;Move the cursor over &lt;code class=&quot;highlighter-rouge&quot;&gt;first&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;my_array.first!&lt;/code&gt; and type &lt;code class=&quot;highlighter-rouge&quot;&gt;:call LanguageClient#textDocument_hover()&amp;lt;CR&amp;gt;&lt;/code&gt;. This should open up a preview window with the documentation for &lt;code class=&quot;highlighter-rouge&quot;&gt;Array.first&lt;/code&gt; property.&lt;/li&gt;
  &lt;li&gt;Type &lt;code class=&quot;highlighter-rouge&quot;&gt;:call LanguageClient_contextMenu()&amp;lt;CR&amp;gt;&lt;/code&gt;. This will bring up a context menu allowing you to select from the actions above. Most options are not implemented yet but gives you an idea of what will be possible in the future.&lt;/li&gt;
  &lt;li&gt;The Swift LSP server docs say that find all references is supported but I wasn’t able to make it work. If you figure it out, drop me a line.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you can see, the functionality is currently somewhat limited but the Swift team is moving fast. Even as I wrote this new commits were being pushed. Neovim is a pleasure to use and with the advent of the Swift LSP server I could see my self moving to it for all my Swift development needs.&lt;/p&gt;

&lt;h3 id=&quot;caveats&quot;&gt;Caveats&lt;/h3&gt;
&lt;p&gt;There are a few catches that I ran into. First of all, you need to tell LCN how to find the root of the Swift project. In the vimrc file I told LCN to look for a file called &lt;code class=&quot;highlighter-rouge&quot;&gt;Package.swift&lt;/code&gt; which indicates the root of a Swift project. By default LCN looks for a &lt;code class=&quot;highlighter-rouge&quot;&gt;.git&lt;/code&gt; folder which, in our case, is one level up from our SPM root.
Swift LSP also doesn’t index in the background, it will only index a project’s symbols at build time. This means that the LSP server wont be aware of any new symbols added to a project until it is recompiled.
The Swift LSP project is moving fast so make sure you always have the latest versions of everything.&lt;/p&gt;</content><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><summary>Photo by Justin Greene on Unsplash</summary></entry><entry><title>Imitation Game, Implementing Dribbble Concepts</title><link href="https://sfsoftwareist.com/2018/10/09/nvpay/" rel="alternate" type="text/html" title="Imitation Game, Implementing Dribbble Concepts" /><published>2018-10-09T00:00:00+00:00</published><updated>2018-10-09T00:00:00+00:00</updated><id>https://sfsoftwareist.com/2018/10/09/nvpay</id><content type="html" xml:base="https://sfsoftwareist.com/2018/10/09/nvpay/">&lt;p&gt;&lt;img src=&quot;/images/fulls/yellow_leaves.jpg&quot; class=&quot;fit image&quot; /&gt;
&lt;em&gt;Photo by Anton Darius | @theSollers on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lately I’ve been learning UI design basics and spending time on &lt;a href=&quot;https://dribbble.com&quot;&gt;Dribbble&lt;/a&gt;, a site where designer types show off their latest creations. My first thought when I see an amazing animation is always ‘Whoa, that looks so cool!’ and my second thought is always ‘Whoa, I have no idea how to implement that!’. Studying these animations has inspired me to close the gap between what designers are creating in After Effects and what I’m able to do with UIKit.&lt;/p&gt;

&lt;p&gt;In order to hone my skills and challenge myself, I decided to take a design from Dribbble and implement it in Swift. I chose something that wasn’t too complicated and had a variety of animations. The one I chose was the &lt;a href=&quot;https://dribbble.com/shots/3829985-VNPAY-App-Interactions&quot;&gt;VNPAY&lt;/a&gt; concept design by &lt;a href=&quot;https://dribbble.com/Ramotion&quot;&gt;Ramotion&lt;/a&gt;. Ramotion does amazing work and they’re SF locals!&lt;/p&gt;
&lt;div class=&quot;quoted-image&quot;&gt;
  &lt;img src=&quot;/images/interaction.gif&quot; class=&quot;image&quot; /&gt;
  &lt;em&gt;
  This is their final product. It was probably mocked up in After Effects and rendered to a gif.
  &lt;/em&gt;
&lt;/div&gt;

&lt;p&gt;This app concept is a simple 2 screen interaction. It contains a login view which transitions to a dashboard screen. It utilizes a Google Material Design aesthetic, in which interactive controls appear to float above the rest of the UI. I particularly like the animated blue stripe on the login screen so this is what I implemented first.&lt;/p&gt;

&lt;p&gt;I admit that I picked this interaction partially because I wanted to learn how to use &lt;a href=&quot;https://airbnb.design/lottie/&quot;&gt;Lottie&lt;/a&gt; and I thought the stripe animation would be a good first experience. I was seriously impressed. Briefly, Lottie enables exporting vector based animations from After Effects into iOS or Android. This means you have all the power of AE animations in your iOS projects.
Learning After Effects and setting up animation exporting consumed almost half the time I spent on this project but it was worth it. My blue stripe doesn’t do justice to Lottie’s power. Head on over to their site to see some of Lottie’s amazing abilities (but not yet!).&lt;/p&gt;
&lt;div class=&quot;quoted-image&quot; style=&quot;float:left;margin: 0 1.5em 1em 0;width:40%&quot;&gt;
 &lt;video autoplay=&quot;autoplay&quot; loop=&quot;loop&quot; controls=&quot;controls&quot; width=&quot;100%&quot; name=&quot;My VNPay&quot; src=&quot;/images/fulls/VNPay_rendered.mp4&quot;&gt;&lt;/video&gt;   
  &lt;!--&lt;img src=&quot;/images/vnpay.gif&quot; class=&quot;image&quot; &gt;--&gt;
  &lt;em&gt;
    I sped up the boring bits (like my slow typing), but the animations are running at normal speed.
  &lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;To the left you can see my &lt;a href=&quot;https://github.com/Tylerc230/VNPay&quot;&gt;implementation&lt;/a&gt;. For the rounded controls and buttons, initially I had integrated &lt;a href=&quot;https://github.com/material-components/material-components-ios&quot;&gt;material-components-ios&lt;/a&gt;. This is Google’s implementation of Material Design for UIKit and is a rather large library. I could imagine using it if I was going all in on Material Design. For this project, however, it seemed a little heavy handed as I only needed a few shadows and rounded corners. In the end, I ended up dropping it and rolling my own components.&lt;/p&gt;

&lt;p&gt;Next, to implement the actual animations, I tried &lt;a href=&quot;https://github.com/AugustRush/Stellar&quot;&gt;Stellar&lt;/a&gt;. I had high hopes for this library — It was well documented, had a nice interface and seemed quite powerful. Unfortunately, I struggled to integrate it with my project, the maintainer had stopped supporting it a few Swifts ago. Additionally, it was difficult to make simple animations work properly and, most importantly, it didn’t take advantage of the more modern UIViewPropertyAnimator API which I was interested in learning.&lt;/p&gt;

&lt;p&gt;Eventually I ended up dropping Stellar and creating my own animation library. Né &lt;a href=&quot;https://github.com/Tylerc230/Disco&quot;&gt;Disco&lt;/a&gt;. Disco is a thin wrapper around UIViewPropertyAnimator. It simply adds a fluent interface to property animator. It’s pretty bare bones at the moment but I intend to flesh it out when I have some time.&lt;/p&gt;

&lt;p&gt;Since we’re on the topic of libraries I created for this project, I’d also like to introduce &lt;a href=&quot;https://github.com/Tylerc230/Choreo&quot;&gt;Choreo&lt;/a&gt;. Choreo doesn’t do any animation on its own. It simply choreographs the animations between several views. Users of the library can specify the amount of time the entire animation should take, the start and duration time of each view’s animation. Choreo will start each view’s animation at the proper time. Like Disco, I intend to spend more time polishing this up in the future.&lt;/p&gt;

&lt;p&gt;Some challenges I encountered during this project were getting the animation timing functions to match the gif. I broke their gif down into individual frames to calculate the length of a each animation but had to guess at their timing curves. I also never figured out exactly what typeface they are using.&lt;/p&gt;

&lt;p&gt;This ended up being a really fun project. I learned a lot about CoreAnimation and UIViewPropertyAnimator and got two new libraries out of it! In the future I intend to do another one of these little experiments, but for now I’m switching gears and am attempting build my daughter some sort of electronic toy. Wish me luck!&lt;/p&gt;</content><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><summary>Photo by Anton Darius | @theSollers on Unsplash</summary></entry><entry><title>WWDC Refactored</title><link href="https://sfsoftwareist.com/2018/06/20/wwdc-refactoring/" rel="alternate" type="text/html" title="WWDC Refactored" /><published>2018-06-20T00:00:00+00:00</published><updated>2018-06-20T00:00:00+00:00</updated><id>https://sfsoftwareist.com/2018/06/20/wwdc-refactoring</id><content type="html" xml:base="https://sfsoftwareist.com/2018/06/20/wwdc-refactoring/">&lt;p&gt;&lt;img src=&quot;/images/fulls/IMG_0087.jpg&quot; class=&quot;fit image&quot; /&gt;
Recently, I’ve been discussing ways to architect iOS applications to make them easier to test. Yesterday, I stumbled upon &lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2017/414/&quot;&gt;this&lt;/a&gt; talk from WWDC ‘17. In this video, the presenter espouses a lot of the same ideas I’ve been advocating here. It’s a great video and I highly recommend it.&lt;/p&gt;

&lt;p&gt;There, the presenter refactors a method that might be seen in any application. The original method would be hard or impossible to unit tests due to its dependency on the &lt;code class=&quot;highlighter-rouge&quot;&gt;UIApplication&lt;/code&gt; singleton. They refactor it using several techniques, including mocking a dependency, in order to make the logic testable. The result is a much more testable unit of code.
Here is the original method:&lt;/p&gt;
&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;@IBAction&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;openTapped&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;segmentedControl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selectedSegmentIndex&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;view&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;edit&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fatalError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Impossible case&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;myappscheme://open?id=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;identifier&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;mode=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;canOpenURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;UIApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[:],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;completionHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;handleURLError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And here is the refactored version:&lt;/p&gt;
&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URLOpening&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;canOpenURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;completionHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)?)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIApplication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URLOpening&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Nothing needed here!&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DocumentOpener&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlOpener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URLOpening&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;urlOpener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URLOpening&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;urlOpener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlOpener&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OpenMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;modeString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawValue&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;myappscheme://open?id=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;identifier&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;mode=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modeString&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlOpener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;canOpenURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;urlOpener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[:],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;completionHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nf&quot;&gt;handleURLError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And this is how you would test it:&lt;/p&gt;
&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MockURLOpener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URLOpening&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;canOpen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;openedURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;canOpenURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;canOpen&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;completionHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)?)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;openedURL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; 
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testDocumentOpenerWhenItCanOpen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;urlOpener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MockURLOpener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;urlOpener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;canOpen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;documentOpener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DocumentOpener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;urlOpener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urlOpener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;documentOpener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;TheID&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;edit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;XCTAssertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;urlOpener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;openedURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;myappscheme://open?id=TheID&amp;amp;mode=edit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This is a huge improvement over the original method. It allows us to test all the logic contained in &lt;code class=&quot;highlighter-rouge&quot;&gt;DocumentOpener&lt;/code&gt;. It decouples the application singleton from the logic under test. My only objection is that the test is a little convoluted. As someone unfamiliar with the code, I need to examine the mock object to see how it works and I need to open up the &lt;code class=&quot;highlighter-rouge&quot;&gt;DocumentOpener&lt;/code&gt; to understand how it interacts with the &lt;code class=&quot;highlighter-rouge&quot;&gt;MockURLOpener&lt;/code&gt;. Additionally, the &lt;code class=&quot;highlighter-rouge&quot;&gt;URLOpening&lt;/code&gt; protocol makes the production code harder to reason about. Was the protocol added to facilitate testing or did the writer truly intend for consumers of &lt;code class=&quot;highlighter-rouge&quot;&gt;DocumentOpener&lt;/code&gt; to implement multiple &lt;code class=&quot;highlighter-rouge&quot;&gt;URLOpening&lt;/code&gt; classes? What if we refactored this using some tips I’ve outlined in previous articles?&lt;/p&gt;
&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DocumentOpener&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;openURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invalidURLError&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;isURLValid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isURLValid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isURLValid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isURLValid&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OpenMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DocumentOpener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;modeString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawValue&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;myappscheme://open?id=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;identifier&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;mode=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modeString&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isURLValid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;openURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;invalidURLError&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Arguably this is a little nicer; we’ve removed a few lines of code and a type declaration. The real value comes when attempting to test this unit.&lt;/p&gt;
&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testDocumentOpenerWhenItCanOpen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;documentOpener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DocumentOpener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isURLValid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentOpener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;identifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;TheID&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;edit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;XCTAssertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;openURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;myappscheme://open?id=TheID&amp;amp;mode=edit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As you can see, we are injecting a single method instead of a conforming object. Additionally, we are returning a value representing the action we’d like to perform. The advantage is that our test is reduced from 18 lines to 8, there is almost no arrange code, and the return value is easily verified.&lt;/p&gt;

&lt;p&gt;This isn’t always the best approach. If &lt;code class=&quot;highlighter-rouge&quot;&gt;DocumentOpener&lt;/code&gt; had a lot of interaction with the system via &lt;code class=&quot;highlighter-rouge&quot;&gt;URLOpening&lt;/code&gt;, we’d end up injecting a lot of methods into &lt;code class=&quot;highlighter-rouge&quot;&gt;DocumentOpener&lt;/code&gt;. At this point it might make sense to inject a &lt;code class=&quot;highlighter-rouge&quot;&gt;URLOpening&lt;/code&gt; object instead.&lt;/p&gt;

&lt;p&gt;In conclusion, by avoiding mocks and focusing on value types, it is possible to write tests that are shorter and easier to understand down the road.&lt;/p&gt;</content><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><summary>Recently, I’ve been discussing ways to architect iOS applications to make them easier to test. Yesterday, I stumbled upon this talk from WWDC ‘17. In this video, the presenter espouses a lot of the same ideas I’ve been advocating here. It’s a great video and I highly recommend it.</summary></entry><entry><title>Pt. 3 Swift Testability By Example</title><link href="https://sfsoftwareist.com/2018/05/31/pt-3-swift-testability-by-example/" rel="alternate" type="text/html" title="Pt. 3 Swift Testability By Example" /><published>2018-05-31T00:00:00+00:00</published><updated>2018-05-31T00:00:00+00:00</updated><id>https://sfsoftwareist.com/2018/05/31/pt-3-swift-testability-by-example</id><content type="html" xml:base="https://sfsoftwareist.com/2018/05/31/pt-3-swift-testability-by-example/">&lt;p&gt;&lt;img src=&quot;/images/fulls/DSC01650.jpg&quot; class=&quot;fit image&quot; /&gt;
In &lt;a href=&quot;/2018/05/08/pt-2-testable-swift/&quot;&gt;my last article&lt;/a&gt;, I discuss the easiest path to testable Swift. In that article I list qualities that make tests valuable. Additionally, I show that business and application logic should be decoupled from volatile or asynchronous dependencies. Now I’d like to focus on the “State” object that houses all of this logic and illustrate some design decisions that will make it easier to test.&lt;br /&gt;
An experienced tester knows that certain features are trivial to test while others must be mangled and distorted before they yield to testing. Tests that are easy to write are ones that require little or no arrangement code, don’t require new classes to enable testing (ie. mocks or stubs) and produce easily verifiable output. The easiest thing in the world to test is a pure function:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addInts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;XCTestAssertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;We dream of tests that look like this. A pure function is one who’s return value is solely determined by its input parameters. Its internals don’t reference any global mutable data which can affect the return value. For a given input, it will always return the same output. Its output is another value, not a write to a database or network request. The output is a value that can be easily verified using the &lt;code class=&quot;highlighter-rouge&quot;&gt;==&lt;/code&gt; operator.&lt;br /&gt;
The next easiest thing to test is a mutable object that has internal state but doesn’t reference any volatile dependencies. To test these objects we must first construct the object, then mutate it until it is in the state we’d like to verify and finally check that certain conditions are true. An example of this would be:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;calculator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Calculator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;startingValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;calculator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;press&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;three&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;calculator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;press&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;calculator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;press&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;four&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;calculator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;press&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;finalValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currentValue&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;XCTestAssertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;finalValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Again, this class (or struct) doesn’t make any network calls and doesn’t reference any global data; calling these methods, in this order, with these parameters will always result in the same final value. It’s not quite as simple as the previous example but it is still obvious what this test does and why.&lt;br /&gt;
We only want to write tests that resemble these two forms. Unfortunately, most unit tests I’ve seen in Swift follow a different pattern.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MockAPIClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;APIClient&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;APIRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;onComplete&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//Add all other methods required by APIClient,&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//possibly stubbing return values to make&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//MockAPIClient behave like the real APIClient&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MockLoginDelegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LoginViewModelDelegate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;showErrorBannerCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;showErrorBanner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;withMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;showErrorBannerCalled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//Stub all other LoginViewModelDelegate methods&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mockDelegate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MockLoginDelegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;apiClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MockAPIClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;apiClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//some error&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LoginViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;apiClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;apiClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mockDelegate&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;userTappedLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;steve_jobs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;i&amp;lt;3apple&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;XCTestAssertTrue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mockDelegate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;showErrorBannerCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I avoid this style because it violates a number of rules outlined in my &lt;a href=&quot;http://www.sfsoftwareist.com/2018/05/08/testable-swift/&quot;&gt;previous article&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;First, it is long and it would be a lot longer if I had implemented every method in &lt;code class=&quot;highlighter-rouge&quot;&gt;LoginViewDelegate&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;APIClient&lt;/code&gt;. Long tests force the reader to figure out what code is required by the test versus what is there just to keep the compiler happy. They are also brittle; every line must be maintained and can break if an interface changes. Besides, who wants to type that much.&lt;/li&gt;
  &lt;li&gt;In order for &lt;code class=&quot;highlighter-rouge&quot;&gt;LoginViewModel&lt;/code&gt; to function properly, &lt;code class=&quot;highlighter-rouge&quot;&gt;MockAPIClient&lt;/code&gt; must return the proper values from all its public methods. For instance, if &lt;code class=&quot;highlighter-rouge&quot;&gt;hasNetworkConnection: Bool&lt;/code&gt; is declared in &lt;code class=&quot;highlighter-rouge&quot;&gt;APIClient&lt;/code&gt;, we need to grok the implementation details of &lt;code class=&quot;highlighter-rouge&quot;&gt;LoginViewModel&lt;/code&gt; in order to know that this method must return &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt; for the tests to behave properly. Any time a test is coupled to implementation details like this, it’s sure to cause trouble.&lt;/li&gt;
  &lt;li&gt;In order to inject the &lt;code class=&quot;highlighter-rouge&quot;&gt;MockAPIClient&lt;/code&gt;, we are forced to add the &lt;code class=&quot;highlighter-rouge&quot;&gt;APIClient&lt;/code&gt; protocol which wouldn’t otherwise be there. This protocol needs to be updated whenever &lt;code class=&quot;highlighter-rouge&quot;&gt;RealAPIClient&lt;/code&gt;‘s public interface changes. This forces all of the tests to be updated as well. Protocols add a level of abstraction that can make code harder to reason about; it’s unclear to the reader that &lt;code class=&quot;highlighter-rouge&quot;&gt;APIClient&lt;/code&gt; will always be a &lt;code class=&quot;highlighter-rouge&quot;&gt;RealAPIClient&lt;/code&gt; at runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Converting the above to a more simplified form gives us the following:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;loginState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LoginState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/*some error*/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LoginState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loginState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;handleLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;XCTestAssertEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;showErrorBanner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Failed to log in&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Four lines of code, no mocks or stubs and no protocols added. Value types are passed in and value types are returned. The production code might look like the following:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LoginViewModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LoginViewState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;apiClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;APIClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loginTapped&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;commands&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loginTapped&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LoginViewState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sendLoginRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;apiClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;commands&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;handleLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;showErrorBanner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ui&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;showErrorBanner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;showLandingScreen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transitionToLandingPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;    
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;disclaimer: I have no idea if any of this compiles&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’ve left out some details for brevity but you can see how the logic of &lt;em&gt;what&lt;/em&gt; to do is embedded in the state object while &lt;em&gt;how&lt;/em&gt; to do it is found elsewhere. Of course, this is a toy example but you can imagine the state object will become more complex as requirements are added (eg. validation logic, error cases). This will be contained and kept separate from the IO represented by the &lt;code class=&quot;highlighter-rouge&quot;&gt;Command&lt;/code&gt; objects. You can find more examples of these patterns &lt;a href=&quot;https://github.com/Tylerc230/CleanArchitectureSample&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article I’ve outlined some specific examples of code that is easily testable. I’ve also given some pointers on how to restructure code to be tested painlessly. Thanks for reading!&lt;/p&gt;

&lt;p&gt;Edit: Here I’ve been carrying on about separating logic and IO, using value types and avoiding mutation like it was some great discovery but turns out apple outlined a lot of these &lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2017/414/&quot;&gt;ideas&lt;/a&gt; at WWDC 2017. 🤦‍♀️ If you haven’t caught that talk yet, give it a watch. It’s full of good information.&lt;/p&gt;</content><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><summary>In my last article, I discuss the easiest path to testable Swift. In that article I list qualities that make tests valuable. Additionally, I show that business and application logic should be decoupled from volatile or asynchronous dependencies. Now I’d like to focus on the “State” object that houses all of this logic and illustrate some design decisions that will make it easier to test.
An experienced tester knows that certain features are trivial to test while others must be mangled and distorted before they yield to testing. Tests that are easy to write are ones that require little or no arrangement code, don’t require new classes to enable testing (ie. mocks or stubs) and produce easily verifiable output. The easiest thing in the world to test is a pure function:</summary></entry><entry><title>Pt. 2 Testable Swift</title><link href="https://sfsoftwareist.com/2018/05/08/pt-2-testable-swift/" rel="alternate" type="text/html" title="Pt. 2 Testable Swift" /><published>2018-05-08T00:00:00+00:00</published><updated>2018-05-08T00:00:00+00:00</updated><id>https://sfsoftwareist.com/2018/05/08/pt-2-testable-swift</id><content type="html" xml:base="https://sfsoftwareist.com/2018/05/08/pt-2-testable-swift/">&lt;p&gt;&lt;img src=&quot;/images/fulls/DSC00762.jpg&quot; class=&quot;fit image&quot; /&gt;
In my &lt;a href=&quot;/2017/10/04/pt-1-effective-testing/&quot;&gt;last article&lt;/a&gt; I touched on a few ideas to make Swift testable. Here I’d like to demonstrate these ideas by implementing a &lt;a href=&quot;https://github.com/Tylerc230/CleanArchitectureSample&quot;&gt;hypothetical feature.&lt;/a&gt; The feature is written using TDD and exhibits these virtuous patterns. Before I go on, I’d like to describe the attributes which make a test good.&lt;/p&gt;

&lt;h4 id=&quot;what-to-strive-for&quot;&gt;What to Strive For&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Tests should be easy to read.&lt;/strong&gt; All setup code is located in close proximity to the test condition. It is clear what the setup code does and why it is required. The test is concise and only includes code relevant to the test. Readers can easily grok which product requirement the test demonstrates. Testing enables others to understand the code as much as it enables the writer to create it.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tests should be easy to write.&lt;/strong&gt; Only a few lines of code are required to arrange the test. The test executes synchronously and no mocks or stubs are required to implement them. If there is friction in writing tests, developers will skimp on them.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tests should not make production code more complex.&lt;/strong&gt; Adding abstractions or making private APIs public to facilitate testing muddies the intention of the code. Tests enable developers to write simpler production code.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tests should not be brittle.&lt;/strong&gt; As long as the API under test doesn’t change, wild changes to the implementation can be made and test failures will only be seen when a feature is broken. The confidence to make dramatic changes is the true power of unit testing.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tests should execute quickly.&lt;/strong&gt; While practicing TDD, the tests are run dozens of times a day. If you must wait for the simulator to spin up each time, momentum will be lost.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sounds nice doesn’t it? Most people who dip their toes into the TDD end of the pool have the opposite experience. Testers create several mocked classes and write tens of lines of setup code for each test. The suite runs painfully slowly making TDD impossible. Changes to the system break or invalidate dozens of tests, making refactoring harder instead of easier.&lt;/p&gt;

&lt;h4 id=&quot;an-example&quot;&gt;An Example&lt;/h4&gt;

&lt;p&gt;My approach to this article is to assign myself a hypothetical feature and implement it using TDD. I followed a few heuristics which make it much simpler to write testable code.&lt;/p&gt;

&lt;p&gt;So what is this secret testing sauce I keep alluding to? The idea is to keep the logic and state isolated from the IO or any other volatile dependencies. By ‘logic and state’ I mean business rules and domain models, I also mean the state required by a view controller, or the queuing and prioritization logic required by a network controller. In this instance ‘IO’ means disk and network access, UI interactions, anything to do with GCD as well as DispatchQueues and even timers. As long as all IO have been removed from the code under test, writing the tests will be simple.&lt;/p&gt;

&lt;p&gt;The feature I’ve decided to build is a BLE pairing screen. The user is shown all broadcasting BLE devices in their vicinity. They are able to tap a broadcasting device and give it a nickname which adds it to the local Core Data store. In this scenario I have three IO devices; the CBCentralManager, the CoreData repo and the view controller displaying the list of BLE devices. I also added cell animations when a users adds, deletes or renames a device. The complex logic behind this feature is where TDD really shines.&lt;/p&gt;

&lt;p&gt;I want to stress that this is not another “MV* architecture will fix your problems” article. The example here is just one implementation illustrating these principles. There are many ways to isolate logic from volatile dependencies. These guidelines apply to all software project, not just view based ones.&lt;/p&gt;

&lt;h4 id=&quot;bringing-it-all-together&quot;&gt;Bringing It All Together&lt;/h4&gt;

&lt;p&gt;In the diagram below, I’ve indicated how the IO devices integrate with the UI logic:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/fulls/BlogWireframe.jpg&quot; class=&quot;fit image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the red box is the system under test (SUT). It contains all of the classes that we are testing for this screen. At first glance, it might appear that we’ve failed to test a great deal of the system. On closer inspection, we can see that all the interesting logic and data structures are contained solely in the red box. The &lt;a href=&quot;https://github.com/Tylerc230/CleanArchitectureSample/blob/master/CleanArchitectureSample/Usecases/ViewBLEList/BLEListSceneCoordinator.swift&quot;&gt;green box&lt;/a&gt; is only responsible for shuttling data back and forth between the IO devices and the state object. It has a cyclomatic complexity of one. The three IO devices in the orange box may contain their own logic and state (queues and retry logic etc) but would be covered under a different set of tests.&lt;/p&gt;

&lt;h4 id=&quot;an-aside-on-viewcontrollers&quot;&gt;An Aside on ViewControllers&lt;/h4&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/Tylerc230/CleanArchitectureSample/blob/master/CleanArchitectureSample/Usecases/ViewBLEList/UI/BLEListViewController.swift&quot;&gt;view controller&lt;/a&gt; on the bottom right is especially interesting. We are so used to the view controller being the real meat and potatoes of any screen, its hard to imagine it not containing anything worth testing. In this example when something in the model changes, a new TableViewModel is pushed to the view controller along with a RowAnimations object (both structs) describing the animations. All the view controller does is copy values out of that model and into the table view cells and run the animations. Again, there is no logic in the VC, it has no knowledge of the underlying data it represents, it simply updates itself with the model which is pushed to it. The result is that the VC is easy to reuse.&lt;/p&gt;

&lt;p&gt;There is no logic in the TableViewModel, it is simply a data transfer object. The values in these data transfer objects are what we will be verifying in our tests.&lt;/p&gt;

&lt;h4 id=&quot;in-conclusion&quot;&gt;In Conclusion&lt;/h4&gt;

&lt;p&gt;Using this approach won’t uncover every conceivable bug in your project. There will be issues integrating the repository, the BLE interface and the UI. We will cover the interaction of those components using integration tests. If each component is rigorously unit tested, we will be more confident when we go to integrate them.&lt;/p&gt;

&lt;p&gt;In my next post I’ll illustrate some patterns and heuristics I use to keep Swift testable. See you next time!&lt;/p&gt;</content><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><summary>In my last article I touched on a few ideas to make Swift testable. Here I’d like to demonstrate these ideas by implementing a hypothetical feature. The feature is written using TDD and exhibits these virtuous patterns. Before I go on, I’d like to describe the attributes which make a test good.</summary></entry><entry><title>Software Intimacy</title><link href="https://sfsoftwareist.com/2018/02/07/software-intimacy/" rel="alternate" type="text/html" title="Software Intimacy" /><published>2018-02-07T00:00:00+00:00</published><updated>2018-02-07T00:00:00+00:00</updated><id>https://sfsoftwareist.com/2018/02/07/software-intimacy</id><content type="html" xml:base="https://sfsoftwareist.com/2018/02/07/software-intimacy/">&lt;p&gt;&lt;img src=&quot;/images/fulls/IMG_0100.jpg&quot; class=&quot;fit image&quot; /&gt;
&lt;em&gt;Enlightenment is intimacy with all things.&lt;/em&gt; —Ehei Dogen (1200-1253)&lt;/p&gt;

&lt;p&gt;What is intimacy in software? It’s a funny concept which I’ve wanted to write about for some time. Like interpersonal intimacy, it’s hard to define. So, instead I will illustrate it with a few examples.&lt;/p&gt;

&lt;p&gt;The first time I lacked intimacy with a codebase was on a project in which I had been asked to do some backend work. The server engineers set up my PHP environment and, to my chagrin, they weren’t using any type of debugger. Their process was to make a change locally, push it to develop and then test the feature using curl. If it didn’t work as expected, they would add some print statements, ssh into the server and tail the logs. Ouch! I felt like I was observing the code through a straw.&lt;/p&gt;

&lt;p&gt;With a setup like this, it is hard to be sure what the server is doing at any given moment. I could only observer the values for which I had had the foresight to print beforehand. Many debugging insights occur by chance, through observing values in the debugger. All the properties look normal, but “oh wait, this property over here looks off” which leads us in a new direction. These chance observations are less likely to happen if we are required to add print statements apriori. Limited debugging combined with the tedious, ‘edit -&amp;gt; upload -&amp;gt; test -&amp;gt; tail the logs’ cycle means that we are much less likely to find the root cause of an issue, and more likely to add band aid fixes.&lt;/p&gt;

&lt;p&gt;Once we were able to debug a running process over a socket, and could watch the program as it ran, our feeling of intimacy with the project grew. We could see the details of the running program more clearly now. By watching a program run in a debugger we learned how the program worked more innately. This kind of intimacy is especially important when learning a new codebase.&lt;/p&gt;

&lt;p&gt;The next change to my process that increased my intimacy with a codebase was when I added unit testing to my toolkit. Using the debugger allows us to view a process as it runs; similarly unit testing allow us to see how our code behaves under different conditions. I like to think of my test suite as a little laboratory where I can test my subjects under tightly controlled conditions. Not only do I know how my code behaves under normal circumstances, now I know how it behaves under error cases and other obscure scenarios. I also know that all the assumptions I’ve made about the code still hold true after a change. Knowing that things still behave properly after a big refactor is a huge confidence booster.&lt;/p&gt;

&lt;p&gt;The most recent change I’ve made to my process, and one I’m still experimenting with, is doing UI development in Playgrounds. The ability to observe the effect of a code change immediately in the interface is very powerful. With a properly factored UI, it is possible to inject all sorts of data and see the effect in real time.&lt;/p&gt;

&lt;p&gt;My normal flow when building UIs was to do layout in interface builder, compile, run, navigate to the screen I was building and observe my changes. If I wanted to test an edge case, I would hardcode some data and feed it to the view. Once I had verified that the UI behaved as expected, I would remove the mock data. Adding hardcoded values is tedious and not easily reproducible.&lt;/p&gt;

&lt;p&gt;Now, I load my view in a playground, along with different sets of mock data, and can instantly see my changes as they’re made. This technique is a great way to observe how the UI will behave under different conditions. It also speeds up the UI development process since I don’t have to navigate to the screen I’m building. Playgrounds are still in their infancy but in the future, they will be a useful development tool in additions to being a great learning device.&lt;/p&gt;

&lt;p&gt;It isn’t possible to observe what a computer is doing directly, so developers have created powerful tools to see how things behave at runtime. By using these tools we can become more intimate with our software. This allows us to easily debug issues as they arise and refactor aggressively to prevent them from appearing in the first place.&lt;/p&gt;

&lt;p&gt;A lack of intimacy motivates developers to make smaller local changes in order to fix issues instead of making larger refactors which will make the codebase more coherent. Knowing intimately how code behaves gives developers the confidence to make larger changes that improve the codebase, making it more maintainable.&lt;/p&gt;

&lt;p&gt;The take home message is to embrace tools that help you understand what your software is doing and integrate them into your daily process..&lt;/p&gt;</content><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><summary>Enlightenment is intimacy with all things. —Ehei Dogen (1200-1253)</summary></entry><entry><title>Pt. 1 Effective Unit Testing in Swift</title><link href="https://sfsoftwareist.com/2017/10/04/pt-1-effective-testing/" rel="alternate" type="text/html" title="Pt. 1 Effective Unit Testing in Swift" /><published>2017-10-04T00:00:00+00:00</published><updated>2017-10-04T00:00:00+00:00</updated><id>https://sfsoftwareist.com/2017/10/04/pt-1-effective-testing</id><content type="html" xml:base="https://sfsoftwareist.com/2017/10/04/pt-1-effective-testing/">&lt;p&gt;&lt;img src=&quot;/images/fulls/IMG_0071.jpg&quot; class=&quot;fit image&quot; /&gt;
I’m coming clean. I’m embarrassed to admit it, but I’ve been a professional software developer for twelve years and have hardly written any tests. I’ve embraced the unit testing cult a few times, but every time I did, I spent more time hacking my code to make it testable than writing new features. My velocity went into the toilet, my once beautiful code became riddled with concessions to make it testable, tests would break after small changes, and worst of all, they never seemed to surface any genuine defects. I would eventually give up with the excuse that “iOS code isn’t testable” or “unit tests are for people who write bad code”. Such hubris!&lt;/p&gt;

&lt;p&gt;The cycle would repeat itself several times over the course of my career. Eventually the proponents of unit testing got louder and louder, even smart people in the iOS community. Clearly I was missing something. By this point I had been consulting for a few years, and had worked with several companies that enforced test coverage. They all suffered from the same problems I did. Everyone was recommending tests but few were doing it effectively.&lt;/p&gt;

&lt;p&gt;At some point I stumbled upon the &lt;a href=&quot;https://www.destroyallsoftware.com/talks/boundaries&quot;&gt;Boundaries&lt;/a&gt; and &lt;a href=&quot;https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell&quot;&gt;Functional Core, Imperative Shell&lt;/a&gt; talks by Gary Bernhardt. Finally, I found someone else who understood my pain and, more importantly, had a way forward. I consumed all material I could find relating to the subject and found more people espousing the same ideas. The venerable Uncle Bob discusses similar concepts in his &lt;a href=&quot;https://vimeo.com/43612849&quot;&gt;Clean Architecture&lt;/a&gt; talks and book.&lt;/p&gt;

&lt;p&gt;At a high level, these speakers introduced several ideas that were new to me: Mocks should be avoided, logic and I/O should be separate, source code dependencies (#imports) should point from implementation details like the network or database toward the core business and application logic, and that the core should be more functional than OOP. Many of these ideas seemed counter to common practice.&lt;/p&gt;

&lt;p&gt;For the last decade my architecture hadn’t fundamentally change. Classes perform some logic and then write data to a database or network. They were difficult to test because data in the DB would have to be verified or network connections mocked in order to verify what was posted to the server. These tests involved a lot of arrangement code before the actual test, it wasn’t obvious what they were doing and they would often break after small changes.&lt;/p&gt;

&lt;p&gt;The problem was that I was testing too many layers of my app. I hadn’t separated my logic from my controllers, network/database or UI. To verify the logic I’d have to fake interactions from the user and verify requests made to the backend. I would need mock users, mock authentications and mock network requests. I was trying to test my code as one big lump. The unit tests had become quasi integration tests.&lt;/p&gt;

&lt;p&gt;If you fundamentally separate the code into two different categories these problems disappear. One side is made of structs and other value types. It contains all the business and application logic. It does no I/O, and has little or no external or volatile dependencies; which is to say it makes no contact with the outside world. It is functional in nature and doesn’t make any asynchronous calls. This half of the source code represent the app’s ‘state’; the part that changes over the lifetime of the app. It is what you write unit tests against, nothing else.&lt;/p&gt;

&lt;p&gt;The other side is comprised of controller, coordinator and manager classes. It handles all of the network, database and interface I/O (yes, the screen is an I/O device). The dependency arrow points from these classes to the logic code above. The goal is to have no logic here whatsoever. It’s purpose is to marshal data and events back and forth to the logic level. Ideally it has a cyclomatic complexity of 1 (meaning it contains no conditional statements) and no state at all. These classes are not unit tested. They are simple to the point that they can be verified by looking at them and do not change often.&lt;/p&gt;

&lt;p&gt;The logic layer can be tested at whatever granularity you wish. It is comprised of simple value types so there is no need to mock anything. No unnecessary protocols or interfaces are needed to facilitate testing. Values are much easier to verify than database writes or JSON blobs. These tests run faster since they aren’t writing to a database and don’t depend on any app scaffolding. They can be run without a simulator, meaning they complete in milliseconds instead of seconds.&lt;/p&gt;

&lt;p&gt;The implication is that nothing under test will have dependencies on UIKit (or any other *Kit). There wont be any tests against views or view controllers, but that’s ok, the action isn’t located there anyway. As an example, instead of instantiating a view controller, passing mock data to it and verifying a label’s text property, tests would be written against a view state struct that would have a text property on it. Tests would verify this property instead. It is true that it’s impossible to achieve 100% test coverage with this approach but there are diminishing returns in trying to cover every single line.&lt;/p&gt;

&lt;p&gt;Mock objects are a useful tool but must be used conservatively and with care because they have some considerable drawbacks. Mocks make tests brittle since they must be updated whenever the interface they are mocking changes. They are complicated to arrange before each test and many times they require their dependencies to be mocked as well. They also trigger more false positives since they don’t always behave the way the real object might. Another drawback mocks have in strongly typed languages like Swift is that they require a protocol where you wouldn’t otherwise need one. Unnecessary abstractions make code harder to reason about and is an example of test induced design damage.&lt;/p&gt;

&lt;p&gt;By keeping the dependency arrows pointing from the controllers toward the business logic, we ensure that our logic is testable and dependency free. This is achieved through dependency injection; the controller implements a protocol defined by the logic layer. To test the system at a macro level, simply mock and inject the I/O controller. This is one place where mocks are useful.&lt;/p&gt;

&lt;p&gt;That’s enough for today. Thanks for taking the time to listen to my thoughts. The take away is to separate the logic from other aspects of the source code, if you find yourself writing too many nested mocks you may have taken a wrong turn and make sure the controller/manager/coordinator classes are dependent on the logic objects and not the other way around.&lt;/p&gt;</content><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><summary>I’m coming clean. I’m embarrassed to admit it, but I’ve been a professional software developer for twelve years and have hardly written any tests. I’ve embraced the unit testing cult a few times, but every time I did, I spent more time hacking my code to make it testable than writing new features. My velocity went into the toilet, my once beautiful code became riddled with concessions to make it testable, tests would break after small changes, and worst of all, they never seemed to surface any genuine defects. I would eventually give up with the excuse that “iOS code isn’t testable” or “unit tests are for people who write bad code”. Such hubris!</summary></entry><entry><title>Obscure Programming Laws And What They Can Do For You</title><link href="https://sfsoftwareist.com/2017/08/22/obscure-programming-laws-and-what-they-can-do-for-you/" rel="alternate" type="text/html" title="Obscure Programming Laws And What They Can Do For You" /><published>2017-08-22T00:00:00+00:00</published><updated>2017-08-22T00:00:00+00:00</updated><id>https://sfsoftwareist.com/2017/08/22/obscure-programming-laws-and-what-they-can-do-for-you</id><content type="html" xml:base="https://sfsoftwareist.com/2017/08/22/obscure-programming-laws-and-what-they-can-do-for-you/">&lt;p&gt;&lt;img src=&quot;/images/fulls/IMG_0102.jpg&quot; class=&quot;fit image&quot; /&gt;
In my last post I explained some of the common anti-patterns that developers fall into. In this article I’d like to explore some architectural principles that help make code more robust and extensible. Like all ‘rules’ in software development, these are really only guidelines, so if something feels awkward or forced, it probably is.&lt;/p&gt;

&lt;h4 id=&quot;law-of-demeter&quot;&gt;Law of Demeter&lt;/h4&gt;

&lt;p&gt;The first principle I’d like to discuss is the Law of Demeter. Demeter is the Greek god of software development (that’s not true). Demeter’s law or “The principle of least knowledge” provides guidelines on to which object another object may access. It states that an object ‘A’ implementing a method ‘m’ may invoke methods on: 1) itself (‘A’), 2) any objects passed as a parameter to ‘m’, or 3) any objects instantiated by ‘A’, either as a property or as a local variable. Instances of ‘A’ may not interact with any other objects; specifically ‘A’ shouldn’t invoke methods on objects returned from calls to other objects.&lt;/p&gt;

&lt;p&gt;As an example, something like &lt;code class=&quot;highlighter-rouge&quot;&gt;self.myObjectB.getC().doSomething()&lt;/code&gt; should be avoided. Instead you might do something like &lt;code class=&quot;highlighter-rouge&quot;&gt;self.myObjectB.doSomethingToC()&lt;/code&gt; (I hope you’re a little more creative with your method naming).&lt;/p&gt;

&lt;p&gt;At first this seems highly restrictive but the advantage is that you’re limiting the dependencies of your object; ‘A’ no longer needs to know anything about ‘C’. ‘C’ could be easily refactored or removed from the codebase and ‘A’ would not need any modification. The “surface area” of an object is comprised of all its methods &lt;em&gt;plus&lt;/em&gt; all of the methods of any objects it exposes publicly. By making ‘C’ private and modifying it through ‘B’s public methods, &lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;/span&gt; B’s surface area has been reduced. This makes it easier to reason how changes to ‘C’ will affect the rest of the codebase. Again, this is only a guideline and wont always be appropriate.&lt;/p&gt;

&lt;h4 id=&quot;dry&quot;&gt;DRY&lt;/h4&gt;

&lt;p&gt;Ok, this one isn’t very obscure but it is often overlooked. It stands for Don’t Repeat Yourself. It means that redundant functionality should be factored out. Code gets duplicated when a feature is implemented in one part of the code, and then similar functionality is needed elsewhere. Instead of making the initial feature generic so that is will work in multiple places, the original implementation is copy/pasted to its new location, and potentially modified slightly for its new purpose. The problem is that a bug in the original code must be fixed in two places. If additional functionality is added to one implementation, the other doesn’t reap the benefits. Code can be made more versatile in a number of ways. Reusable code can be achieved through generic/template functions if your language supports them, by extracting the generic functionality into its own methods and passing in the unique functionality via function pointers or closures, or by putting the generic code into a base class with unique functionality added to derived classes.&lt;/p&gt;

&lt;h4 id=&quot;kiss&quot;&gt;KISS&lt;/h4&gt;

&lt;p&gt;KISS stands for Keep It Simple, Stupid. While it sounds a little harsh, it is actually good advice. There is a tendency for developers to think their job is done once the code functions as designed. In reality working code is just the first step. From there the code needs to be boiled down and simplified. Are you using two data structures when you could accomplish the same thing with one? Are some properties of a class redundant? Has some operation been repeated in several places (i.e. is it DRY)? Should some logic be wrapped in its own class? Could a block of code be shortened and its intension be made more clear? By taking the time to simplify and refactor new code once it is working, the code will be easier to reason about and modify in the future.&lt;/p&gt;

&lt;h4 id=&quot;the-openclosed-principle&quot;&gt;The Open/Closed Principle&lt;/h4&gt;

&lt;p&gt;This principle states that classes and functions should be “Open for extension but closed for modification” meaning that it should be possible to extend the functionality of an existing class without having to open it up and modify it directly. An example of a class that violates this principle would be a ShapeRenderer class which draws different shapes to the screen and has the functionality for drawing each shape (drawSquare(), drawCircle() etc) added as methods to the ShapeRenderer. Any time a new type of shape is needed, the ShapeRendered class must be opened up and modified. What if rendering to a file is needed? The ShapeRenderer class would need to be modified for this as well. The problem is that the developer needs to understand the implementation details of the ShapeRenderer class completely in order to modify it. A better ShapeRenderer would be one that accepts different shape objects to be rendered. Each shape object would know how to render itself and ShapeRenderer would not have to know the specifics about each shape. To add a new triangle shape, ShapeRenderer wouldn’t have to be modified at all, the triangle drawing code would be implemented in Triangle, a subclass of Shape.&lt;/p&gt;

&lt;p&gt;Now lets say that we want to be able to render our shapes to a file instead of to the screen. The ShapeRenderer class could be modified to take a RenderTarget object. The RenderTarget subclass would be responsible for actually writing the renderings to the screen or to a file. This would make it simpler to add another render destination, such as a printer. A RenderTarget subclass would contain all the printer specific code. No need to modify ShapeRenderer.&lt;/p&gt;

&lt;h4 id=&quot;single-responsibility-principle&quot;&gt;Single Responsibility Principle&lt;/h4&gt;

&lt;p&gt;This principle states that a class should “have one reason to change”. I always had trouble with this definition. A class could have any number of reasons to change. The description seems too vague to be useful. To adhere to this principle, you kind of have to follow your instincts. Classes always have responsibilities, they are in charge of certain functionality. Ideally each class is only in charge of one specific task or a small collection of related tasks. If a class is in charge of multiple unrelated things it should be split up and they should communicate through some sort of interface. The problem with having 2 orthogonal pieces of functionality in the same class is that their implementations become intertwined. It becomes difficult to reason about one without understanding how the other works. Their implementations become tightly coupled and it becomes difficult to modify one without breaking the other. A good heuristic is that if a subset of methods and properties in a class all deal with one aspect of its functionality, they might be a good candidate for pulling out into their own class.&lt;/p&gt;

&lt;h4 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;That is the short list of principles I’ve used to help guide my work. There are many others but these are the ones which resonate with me and I hope you find them useful as well. As a word of caution, I find that whenever I learn a new paradigm or discover a new axiom, I tend to over apply it, so like everything in life, finding balance is key.&lt;/p&gt;</content><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><summary>In my last post I explained some of the common anti-patterns that developers fall into. In this article I’d like to explore some architectural principles that help make code more robust and extensible. Like all ‘rules’ in software development, these are really only guidelines, so if something feels awkward or forced, it probably is.</summary></entry><entry><title>iOS Code Smells I’ve Smelt — Common Pitfalls of a Junior iOS Developer</title><link href="https://sfsoftwareist.com/2015/05/28/ios-code-smells-ive-smelt-common-pitfalls-of-the-junior-ios-developer/" rel="alternate" type="text/html" title="iOS Code Smells I’ve Smelt — Common Pitfalls of a Junior iOS Developer" /><published>2015-05-28T00:00:00+00:00</published><updated>2015-05-28T00:00:00+00:00</updated><id>https://sfsoftwareist.com/2015/05/28/ios-code-smells-ive-smelt-common-pitfalls-of-the-junior-ios-developer</id><content type="html" xml:base="https://sfsoftwareist.com/2015/05/28/ios-code-smells-ive-smelt-common-pitfalls-of-the-junior-ios-developer/">&lt;p&gt;&lt;img src=&quot;/images/fulls/IMG_0066.jpg&quot; class=&quot;fit image&quot; /&gt;
Being a freelance iOS developer, I get the opportunity to work on a variety of projects, written by developers with varying degrees of experience. This has given me the opportunity to catalog the most common iOS anti patterns or &lt;a href=&quot;http://en.wikipedia.org/wiki/Code_smell&quot; title=&quot;'Code Smell'&quot;&gt;‘Code smells’&lt;/a&gt; I’ve smelt. I will enumerate the most common smells and some possible solutions to guide you on your path to mobile app nirvana.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MVC&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most common error that junior developers make is constructing the ‘Massive View Controller’ and its cousin, the ‘Massive App Delegate’. People commonly place bits of logic in these two classes because they don’t know where else it should go. If this pattern isn’t curtailed early on, view controllers can become 400 (4000?) line behemoths. This is a sign of an unhealthy code base because the code isn’t easily reused, leading to code duplication and unnecessary dependencies. The other, more insidious problem is that, inevitably, your view controller will implement multiple systems in the same class, their logic will become hopelessly entangled and difficult to reason about. Attempting to &lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;/span&gt; modify one system can easily introduce bugs in another. &lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;/span&gt; Any given class should do only one thing and have a clean interface exposing its functionality.&lt;/p&gt;

&lt;p&gt;To keep view controllers slim, remember they should only be responsible for transferring changes from the model layer to the views, or passing user input back to the model layer. View controllers should be the most boring classes in your project. Similarly the app delegate should simply relay system messages to the data layer. When it comes down to it, the reason these two classes become so bloated is that they are the only classes that Xcode generates automatically for you. The solution is to simply pull out a piece of paper and draw some boxes representing your classes. Then write down a list of all the public methods that each class exposes. After that, draw some arrows showing their dependencies to each other. Do this before writing a single line of code and your project will be more modular and flexible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;APIs define explicit relationships between objects&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The second stinkiest smell I’ve smelt has many different manifestations but all share a common root. I’m going to call this one the ‘Lack of Well Defined APIs’ smell. People think an API is something you slap on top of a library right before you ship it. On the contrary, any object you create should have a carefully considered interface before work begins on the implementation. If your project has even two classes, each should have a well defined list of public methods describing the functionality of the class. For bonus points it should even have all of its dependencies exposed in the constructor (see &lt;a href=&quot;https://sites.google.com/site/unclebobconsultingllc/blogs-by-robert-martin/dependency-injection-inversion&quot; title=&quot;Dependency Injection&quot;&gt;Dependency Injection&lt;/a&gt;). The approach new developers take is to dive right into the implementation and not consider how classes relate to one another.&lt;/p&gt;

&lt;p&gt;There are many different forms the ‘ill defined API’ code smell can take. One example is a custom table view cell which exposes all of its subviews to the world. Users of this custom cell are expected to access the labels and buttons of this cell directly. Instead, all access to the subviews should be through an API. This makes the code easier to read, explains exactly what the cell does, and allows the developer to change the implementation of the cell without changing any other class. In the example below, I don’t need to change any code outside of the cell when I later decide to use use the ‘attributedText’ property instead of the ‘text’ property in the cell’s highScoreLabel.&lt;/p&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//This is a leaky cell API
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;highScoreLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSString&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;stringWithFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@“&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;”&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;highScore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//This method abstracts away the implementation of the cell, leading code that is easier to modify
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;highScore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;highScore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Another common example of a poor API is when embedding a button in a cell, often developers will set the target/action pair on the button in the data source. My approach is to expose a block in the cell’s interface which gets executed when the button is tapped. This allows me to capture the data object that the cell represents in cellForRowAtIndexPath:.&lt;/p&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//This is a leaky abstraction
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;favoriteButton&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addTarget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;forAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toggleMarkFavorite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forControlEven&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UIControlEventTouchUpInside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//A better alternative
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;favoriteButtonTapped&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BOOL&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isFavorite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isFavorite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cellObject&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;markAsFavorite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cellObject&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;unmarkAsFavorite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In the same vain, modifying the UI by walking the view hierarchy, is a design anti pattern. Code that either iterates over subviews calling “&lt;code class=&quot;highlighter-rouge&quot;&gt;isKindOf:“&lt;/code&gt; searching for a particular view, or searches up the hierarchy calling superview.superview, is a code smell. Making assumptions about the structure of a view hierarchy is extremely brittle and will easily break with simple changes to the view structure. I once worked on a project where a previous developer had referenced table view cells by calling superview.superview from an embedded subview. Once iOS 7 rolled out, apple changed the internal structure of the cell and ALL THE CODE BROKE. The solution is to add direct references (properties) to any views which need to be modified at run time through Interface Builder.&lt;/p&gt;

&lt;p&gt;Another symptom of poorly considered object relationships is excessive use of NSNotifications. Notifications are, in and of themselves, not a bad thing and do have many legitimate uses. However using them to facilitate communication between two objects instead of a direct dependency is a code smell. At first glance, Notifications make writing code easier; changes to one object are easily propagated to other objects without defining an explicit relationship between them. The down side to this approach is that the relationship between these two objects isn’t obvious by looking at their public APIs. It’s better to make a direct relationship between two objects, either through a ‘has a’ relationship, the delegate pattern or a more specific observer pattern (blocks also facilitate interaction between objects but see my next point).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Too much of a good thing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When blocks were first introduced, I thought they were the best thing since the ‘for’ loop. I quickly discovered that, while blocks make asynchronous code easier to read, they became difficult to follow and debug as they become more deeply nested. The beauty of blocks is that you can capture the state of your program at any point and do operations on it later. The problem is that it can be difficult to determine the order that operations occur if too much of your code is executed in blocks. Don’t get me wrong, blocks are a good thing and are absolutely appropriate for many circumstances. However, whenever creating a block nested inside another block, ask yourself if there is a way to combine them. Alternatives to blocks are: the delegate pattern, an observer pattern, NSOperations or a Promises library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Polymorphic views&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Xib files make interfaces easy to assemble but can make reusing components difficult. This gives rise to the ‘overloaded view’ code smell. This happens when you define a custom view, such as a table view cell, in IB. Then elsewhere in the UI you see a similar view, not quite the same but similar, so you decide to reuse the same xib file, possibly passing in a ‘type’ enum to the cell to differentiate between the two. The view shows and hides various subviews depending on it’s ‘type’. These view ‘types’ seem to grow in number and are only superficially related to one another. Code paths which are unrelated accumulate in one place and become hopelessly entangled. The result is one class representing many views in your app which might share some minor commonalities but, in reality, have very little to do with one another. You know there is a problem when the view is littered with switch statements; adding and hiding views depending on some state. This is a problem because code written for one ‘type’ &lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;/span&gt; can inadvertently get executed for a completely separate type. It also makes the code harder to reason about and debug.&lt;/p&gt;

&lt;p&gt;A better approach is to factor out the common components into a separate .xib file. The xib then gets added as a subview where needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Just make it an object already&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A smell I see quite often, especially when working with RESTful APIs, is the ‘Dictionaries as Objects’ smell. JSON objects, received from the server, are parsed intro dictionaries and used directly throughout the app. The problem is that dictionaries are stringly typed; as in you have to use strings to access the values. This makes the code verbose and can lead to bugs if keys are misspelled. It is also impossible to attach functionality to a dictionary to process the data like you would with methods on classes. Additionally the kinds of values you can store in a dictionary are restricted (no primitive types). It is preferable to define classes for all JSON objects and convert the dictionary responses to objects as soon as you receive them. The advantage is that you can access properties using getters instead of keys, you can use primitive types as values and you can you can add functionality to the data if need be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ya ain’t gonna need it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Poor grammar but good advice. A lot of code I come across is littered with commented out code or worse, functions and classes that aren’t used anywhere but were left in the code base, collecting digital dust. The habit of developers to save code because ‘they might need it later’ is fairly pervasive. The problem with stale, unused code is that it still needs to be mentally parsed and understood when reading the code and still needs to be maintained when refactors occur. It is difficult to remove later because a method might appear to be used, but in reality might actually be called from an unused branch of code. If some functionality has been removed, just delete all the code associated with it. It will exist forever in version control &lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;/span&gt; in case it is needed in the future. Furthermore, code is cheap to write and expensive to maintain. No matter how brilliant you think your snippet of code is, just delete it, it could probably be recreated later if necessary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caching considered harmful&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The final code smell I would like to discuss is the dangers of caching. Most developers have a good idea of what caching is; they could probably give an example involving local storage of downloaded images. It’s important to recognize the subtler forms of caching and how they can be detrimental. Some examples of subtle caching are: 1) Performing a calculation at startup and saving the result, 2) creating an object once and using it for the lifetime of the app, 3) fetching objects from Core Data and keeping them in memory, 4) pulling objects from the server and storing them in Core Data. The main problem with these sorts of caching is that now you have two places where the data is stored and they can become inconsistent. The complexity in determining when a cache is stale and needs to be refreshed can introduce bugs to a code base. Before deciding to cache or ‘memoize’ &lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;/span&gt; a value, be certain that you need the performance boost, otherwise you’re optimizing prematurely. This anti pattern crops up a lot with Core Data, or when constructing singletons (unless you truly have some state that needs to be maintained for the entire life of your app, it’s better to create new *Manager objects for every view controller that needs access to them). Also, consider keeping data pulled from the server in memory and refresh it when the app launches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’ve outlined the seven stinkiest code smells found in iOS projects. Taking the time up front to structure your code properly will always pay dividends down the road.Refactor old code, design clean APIs, create new classes when needed, avoid premature optimization and generally keep your project clean and lean, and your codebase will remain flexible and less error prone. New features will be added easily and old ones will be modified with little friction. The source of and solution to bugs found in your code will be apparent and easy to fix. If you can avoid these code smells, you’ll be miles ahead of your peers. Happy coding!&lt;/p&gt;</content><author><name>Tyler Casselman</name><email>tyler@13bit.io</email></author><summary>Being a freelance iOS developer, I get the opportunity to work on a variety of projects, written by developers with varying degrees of experience. This has given me the opportunity to catalog the most common iOS anti patterns or ‘Code smells’ I’ve smelt. I will enumerate the most common smells and some possible solutions to guide you on your path to mobile app nirvana.</summary></entry></feed>
