The Missing Manual For Swift Development
The Missing Manual For Swift Development
Development
Bart Jacobs
This book is for sale at
http://leanpub.com/the-missing-manual-for-swift-development
Welcome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Part 1: Foundation . . . . . . . . . . . . . . . . . . . . 3
1 Your Foundation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
What Is Your Foundation . . . . . . . . . . . . . . . . . . . . . . . 4
There Is No Clear Path . . . . . . . . . . . . . . . . . . . . . . . . . 9
2 Where to Start . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Setting Yourself Up for Success . . . . . . . . . . . . . . . . . . . 12
A Path Without Distractions . . . . . . . . . . . . . . . . . . . . . 13
Choose Your Teacher Wisely . . . . . . . . . . . . . . . . . . . . . 18
Be Critical . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5 Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Make It Hard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Plain Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Obfuscating Information . . . . . . . . . . . . . . . . . . . . . . . 32
Fetching Sensitive Information . . . . . . . . . . . . . . . . . . . . 33
Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Privacy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Logging and Debugging . . . . . . . . . . . . . . . . . . . . . . . . 34
Educating Your Client . . . . . . . . . . . . . . . . . . . . . . . . . 34
9 Design Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Model-View-Controller . . . . . . . . . . . . . . . . . . . . . . . . . 40
Model-View-ViewModel . . . . . . . . . . . . . . . . . . . . . . . . 47
Singletons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Dependency Injection . . . . . . . . . . . . . . . . . . . . . . . . . 61
References, Delegation, and Notifications . . . . . . . . . . . . . 70
Master These Patterns . . . . . . . . . . . . . . . . . . . . . . . . . 78
6 Protocol-Oriented Programming . . . . . . . . . . . . . . . . . . 79
7 Reactive Programming . . . . . . . . . . . . . . . . . . . . . . . 83
Part 2: Swift . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Protocol-Oriented Programming . . . . . . . . . . . . . . . . . . . 89
Type Safety . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Best Practices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Forget What You Know . . . . . . . . . . . . . . . . . . . . . . . . 91
2 Be Critical . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
3 Embracing Optionals . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Warning Sign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Elegance and Beauty . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Swift to the Rescue . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Embrace Optionals . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Caveats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
3 Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Technical Debt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Building for the Future . . . . . . . . . . . . . . . . . . . . . . . . 177
The Fallacy of Sunk Cost . . . . . . . . . . . . . . . . . . . . . . . . 178
Starting Anew . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
5 Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
Minimize Dependencies . . . . . . . . . . . . . . . . . . . . . . . . 187
What Is a Dependency . . . . . . . . . . . . . . . . . . . . . . . . . 188
Fewer Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Mapping the Liabilities of a Project . . . . . . . . . . . . . . . . . 189
Don’t Make Your Life Too Easy . . . . . . . . . . . . . . . . . . . . 190
Rolling Your Own . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
Choose Wisely . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Becoming a Better Developer . . . . . . . . . . . . . . . . . . . . 191
Watch Out for the Defaults . . . . . . . . . . . . . . . . . . . . . . 192
Challenge Yourself . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
6 Automation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
CONTENTS
Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
Build Phases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
Automated Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
Continuous Integration . . . . . . . . . . . . . . . . . . . . . . . . 195
fastlane . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
Keep It Simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
7 Privacy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Protecting the User’s Privacy . . . . . . . . . . . . . . . . . . . . . 197
Who Do You Work With . . . . . . . . . . . . . . . . . . . . . . . . 197
Giving the User Control . . . . . . . . . . . . . . . . . . . . . . . . 198
Third Party SDKs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Choose Wisely . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
you’re developing for Apple’s ecosystem, then you’ll find a lot of useful
information, regardless of your experience.
There are very few shortcuts in software development. You pay a price
for most of the shortcuts you read about, one way or another. But there
are a handful of shortcuts that can speed up your learning and your
career. A proper education is one of them.
I hope that my book helps you in some way, big or small. If it does, then
let me know. I’d love to hear from you.
Enjoy,
Bart
Part 1: Foundation
1 Your Foundation
Developers that come to Apple’s platforms have many different back-
grounds, and some of us are better prepared than others. Regardless of
your background, though, you can make sure that you’re a good fit for
Apple’s ecosystem by investing in your foundation. That’s the subject of
this chapter.
This may sound boring at first, and for some it is boring, but it’s essential
if you plan to create robust, scalable applications and if you want to have
a long career in the mobile space.
There’s a slew of reasons why developers are drawn to Apple’s ecosys-
tem. Many of us make the jump because of the shiny stuff. ARKit and
Core ML are good examples of what I like to refer to as shiny stuff. Both
are amazing technologies, and I’m sure you’ve seen stunning examples
of developers taking advantage of ARKit. ARKit and Core ML are the
cherries on the cake. And the cake is your foundation. Without the cake,
there are no cherries.
Swift
I’m going to assume that you already have a good grasp of the Swift
language or, at a minimum, you’ve browsed The Swift Programming
Language1 and you’ve written a handful of lines in a playground.
I’m sure I don’t need to convince you of the importance of knowing and
understanding the Swift language. How are you going to write a fantastic
novel if you don’t master the language the novel is written in? Why would
this be any different for software development?
But this doesn’t mean you need to spend days, weeks, or months
learning the Swift language. I recommend a different approach that’s
more fun and more practical. I don’t like spending hours or days learning
a new library, framework, or API. I learn best by applying what I read and
learn. The same is true for the Swift language.
Start with the basics and use it. You can pick up the basics of any
language in no time. But, as with any language, you only get what you’ve
learned by applying it. That means writing Swift. You can use Swift
in a playground or start with a simple Cocoa application. Apple did a
fantastic job by introducing playgrounds alongside the unveiling of the
Swift language. Use them. Launch Xcode, create a playground, and play
with Swift.
Optionals
Many developers will go through a phase in which they struggle with the
language. That’s fine. Let yourself be frustrated for a while. It’s natural,
and it means that you’re noticing aspects of Swift that are core to the
language. Be skeptical and ask questions.
Based on conversations with students and readers, optionals are one of
the most common obstacles developers need to overcome. I genuinely
love optionals, but I too was frustrated when they first crossed my path.
This wasn’t surprising considering my background in Objective-C. As you
probably know, Objective-C isn’t as strict about nil pointers. Dealing with
nil is an entirely different story when you’re writing Swift.
1
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_
Language/
1 Your Foundation 6
If you’re still struggling with optionals or don’t see how they fit in the
language, then I need to ask you to trust the language for now. It will
click at some point, but you need to embrace optionals. Don’t use the
exclamation mark to plow your way through a forest of optionals. Op-
tionals are an integral part of the language and an essential component
of one of Swift’s key features, safety.
The more you use the language, the more you start to appreciate it. What
I tend to do is gradually add more complexity to the code I write. Learn
about value types and reference types. Discover what protocols are and
why they’re useful. You may want to explore generics at some point. Take
a close look at enumerations and find out why they’re so much more
powerful than their Objective-C counterparts.
If you think you know the Swift language, then I recommend taking
another look at The Swift Programming Language2 . Every time I read
Apple’s guide, I learn something new. Most of the times, I can directly
apply it to the code I write day to day. I love it. Swift was designed to be
more expressive, and it feels richer than Objective-C. That’s something
you can and should take advantage of in the code you write.
Concepts
Even if you still use Objective-C, there are concepts that you need to
know about, regardless of the language you use. These concepts are
often scary to new developers, such as memory management, asyn-
chronous programming, and grand central dispatch. These are concepts
and technologies that are often ignored or overlooked. Unfortunately,
this leads to memory leaks, crashes, and a lot of frustration.
This frustration often leaves a bad taste in your mouth, and it can even
affect your fondness for the language and the platform. There’s nothing
2
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_
Language/
1 Your Foundation 7
SDK
You can do quite a bit with the Swift language that doesn’t involve Apple.
The language is available on Linux, and there are several frameworks
that you can use to build web APIs powered by Swift. There are also a
number of tools and libraries you can use to write scripts using Swift,
such as Marathon3 , Rainbow4 , and Commander5 .
But most of us use Swift to power mobile or desktop applications, which
means we need to become familiar with a bunch of tools, frameworks,
and libraries. The most common ones are Foundation, the bread and
butter of every Cocoa developer, UIKit and AppKit, and several other
ones, such as Core Data, AVFoundation, CloudKit, and HealthKit. The
time you spend exploring and learning about these frameworks and
libraries is time well spent.
Design Patterns
There are dozens and dozens of design patterns you can pick and choose
from and a handful of these design patterns are used by the frameworks
and libraries you use on a daily basis. At a minimum, you need to know
about and become familiar with these fundamental design patterns. Let
me give you a quick overview of the most important ones. Later in this
book, I zoom in on a few of these design patterns.
Model-View-Controller
The first design pattern you inevitably come into contact with when you
create your first project in Xcode is the Model-View-Controller pattern.
3
https://github.com/johnsundell/marathon
4
https://github.com/onevcat/Rainbow
5
https://github.com/kylef/Commander
1 Your Foundation 8
It’s this pattern that powers most Cocoa applications. If you’ve been
reading Cocoacasts for a while, then you know that I’m not a raving fan
of this design pattern. It falls short in a number of ways, and I mostly use
the Model-View-ViewModel pattern instead.
The Model-View-Controller pattern is easy to pick up, and it’s a good fit
for building Cocoa applications. Apple’s SDKs are impregnated with this
pattern and most of us have used the Model-View-Controller pattern for
years and years, and not only for building Cocoa applications. It’s a widely
used, versatile design pattern that has earned its stripes over several
decades.
Delegation
Notifications
While delegation is a good fit for objects that have a one-to-one re-
lationship, notifications are ideal for distributing messages to one or
more unrelated objects. Know and understand what the differences are.
Delegation and notifications aren’t interchangeable design patterns.
Like delegation, notifications are very common in Apple’s frameworks
and libraries. They’re an essential ingredient of every Cocoa application.
1 Your Foundation 9
Xcode
One of the first tasks you need to take care of if you decide to build a
Cocoa application is downloading, installing, and launching Xcode. De-
velopers rarely take the time to learn the ins and outs of Apple’s powerful
IDE (Integrated Development Environment). Spend some time exploring
the basics of Xcode. There are many, many tips, tricks, and features you
only pick up after using Xcode for a while, but it’s nevertheless important
to learn the basics.
Focus
When Apple released the iPhone in 2007, we didn’t have an SDK to work
with. The more experienced developers among us reverse engineered
the operating system and built applications for the first iPhone. Ten
years later, Apple has given developers access to a rich ecosystem with
the tools we need to build amazing software. As a Cocoa developer,
you can build software for your computer, your phone, your tablet, your
watch, and even for your television. These are amazing times. But, again,
it’s easy to be overwhelmed. Focus is important.
I know several developers that build software for both Apple’s and
Google’s ecosystems. While this may seem appealing, it isn’t something
I recommend. It’s very challenging to stay up to date about one platform
let alone two. There certainly are advantages to this approach, but it’s
more important than ever to specialize.
Your attention is a valuable asset, and I recommend to focus, focus
aggressively. If your employer expects you to be up to date on iOS, tvOS,
macOS, and watchOS, then they’re expecting too much. Chances are that
they’re not technical or don’t know much about Apple’s ecosystem. Gone
are the days that you know every framework and library inside out.
I choose to focus on Apple’s ecosystem, with a strong emphasis on iOS.
I also build tvOS and watchOS applications, and the occasional macOS
application, but those aren’t my main focus. This focus allows me to build
robust, performant applications.
Apple applies that same focus, or it used to. Choosing a new Apple
computer used to be a simple task because you only had a handful of
options. While that’s no longer true, it emphasizes the power of focus
and simplicity. And it’s the reason I choose to build a career on Apple’s
ecosystem.
1 Your Foundation 11
I talk more about this later in the book, but I need to repeat myself by
saying that focus is essential. If you’re starting out as a developer, then
make sure you’re not jumping from topic to topic. Choose a proven path.
A resource I often recommend to developers is the book about Cocoa
development published by Big Nerd Ranch6 . It’s this book by Aaron
Hillegass7 that taught me Cocoa development. Aaron and his team have
decades of experience teaching people Cocoa development.
There are three reasons for choosing a trusted source. First, you learn
the fundamentals. Second, you can ignore the abundance of information
and focus. Third, you’re sure you’re learning things the right way. Big
Nerd Ranch, for example, has been around for almost two decades, an
eternity in the technology industry.
Focus, focus, focus. That’s what’s going to keep you sane in today’s world.
That’s one of the first things I teach the students I coach. It’s fine to ignore
most of what you read and focus on one thing at a time. Your productivity
will skyrocket, and your confidence will follow suit.
6
https://www.bignerdranch.com
7
https://www.bignerdranch.com/about/the-team/aaron-hillegass/
2 Where to Start
In this chapter, I describe the path I recommend to people that are new
to Cocoa and Swift development. If you’re new to programming, then I
recommend taking a basic course on programming first.
The path I present in this chapter requires you to learn a collection of
skills, patterns, and paradigms. Remember from the previous chapter
that it’s essential that you remain focused. It’s tempting to jump from
topic to topic because there’s a lot you need to learn.
Before we explore the path to learn Cocoa and Swift development, it’s
important to understand that it takes time. Not only does it take time
to learn the various topics I cover in this chapter, it takes time to let
everything sink in.
You will encounter concepts that only click a day, a week, or a month
after you’ve read about them in a book or seen them explained in a
video. Don’t let yourself become frustrated if you don’t get everything
right away. That’s perfectly normal.
The Swift language is easy to pick up, but the finer details and more
advanced features are more challenging. The Cocoa SDK with its many
frameworks and APIs can seem daunting, but if you know what to focus
on when and understand why you’re learning something, then the pieces
of the puzzle start to fit together, showing you the bigger picture.
2 Where to Start 13
The first step is the most obvious one, learning the Swift language. Learn-
ing the language and the frameworks at the same time isn’t something
I recommend, unless you’re already familiar with Objective-C. That’s
why I always recommend to learn the basics of the Swift language first.
The Swift Programming Language8 is a very good starting point and it’s
what I recommend you read. If you’re new to Swift and Objective-C, I
recommend skipping A Swift Tour9 because it will confuse you more
than it will teach you.
The Swift Programming Language is available from the Swift website10
and you can download it for free from iTunes11 . But don’t take the book
and read it from cover to cover. Take out your computer, install Xcode,
and write code. Let everything sink in by applying what you learn. You
only learn the language by writing it, using its syntax, and becoming
familiar with the various concepts. Write, write, write.
8
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_
Language/
9
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_
Language/GuidedTour.html
10
https://swift.org/documentation/
11
https://itunes.apple.com/book/id1002622538
2 Where to Start 14
This also means it’s time to install Xcode. Visit the Apple Developer
website12 and download a copy of Xcode13 . You can also download Xcode
from the Mac App Store14 . Fire up Xcode, create a playground, and write
code as you read The Swift Programming Language. This is one of the
best approaches to learn the language.
I browse The Swift Programming Language several times a week.
Because it contains so much information, it’s virtually impossible to learn
and understand everything about the language after one read.
When is it time to continue to the next step? You’re ready to move on if
you understand the basics of the language. How do you know if you do?
It means that you understand and can apply the following concepts and
paradigms.
You’ll learn a lot more along the way, such as error handling, inheritance,
properties and methods. You should now be ready to build your first
application.
Once you have a basic understanding of the Swift language, it’s time
to start building something that runs on an iPhone or an iPad. Even
though playgrounds are fantastic to learn Swift, you started this journey
to build applications. One of the most exciting moments of my journey as
a software developer was the day I ran my first application on a physical
device.
I encourage you to create your first application as soon as you have a
good grasp of the language. The application won’t do much, but it puts
the language and the frameworks together. It should also get you excited
about what’s to come. There’s nothing as exciting as running your very
first application on your phone or tablet.
The application you build in the previous step won’t make a dent in the
universe, but it whets your appetite. It’s time to become familiar with
the frameworks and tools you need to build robust applications, which
includes learning about the Foundation framework, the Swift standard
library, and UIKit (iOS) or AppKit (macOS). A good book or course on
Cocoa development covers the important aspects of these frameworks
and tools.
For iOS developers, it’s essential to be familiar with views and view
controllers. Understand how a view relates to a view controller and
how both fit into the Model-View-Controller pattern. While you could
create the user interface in code, I don’t recommend this. Apple pushes
developers to storyboards and that’s something you need to become
familiar with. But don’t ignore XIB files. They’re a fine alternative if you
don’t like working with storyboards.
2 Where to Start 16
Auto Layout is a layout engine that makes building user interfaces easier.
You need to become familiar with constraints, layout guides, and view
hierarchies. Don’t skip this step. Many developers do and pay the price
later.
Almost every iOS application includes a table view or a collection view.
As you learn how they work, you also pick up the delegation and data
source patterns, which we discussed in the previous chapter.
Navigation controllers are another essential ingredient of most iOS ap-
plications. It may be challenging to wrap your head around the concept,
but once it clicks you’ll find them easy to use. The same applies to tab
bar controllers.
Storing data is a task of most applications. There are many solutions
available. The simplest solution provided by the Cocoa SDK is the de-
faults system. The defaults system is nothing more than a key-value
store. You’ll find yourself using it very often. I also recommend learning
about more advanced types of data persistence, such as storing data in
a file on disk or in a database.
Later in this chapter, I emphasize how important it is to choose a
resource that teaches you these fundamentals. It pays to invest in a good
book or course. You’re investing in your foundation.
Step 7: Publish
While you can go through these steps on your own, I recommend that
you look for help. You can learn the Swift language by reading The
Swift Programming Language. Learning the Cocoa SDK is a bit more
challenging. That’s the step in which most developers lose track.
Pick up a book or course that covers the fundamentals in such a way
that you learn everything you need to build a simple yet functional ap-
plication. Later in this book I talk about the importance of choosing your
teacher. Make sure you learn from someone you trust. That someone
teaches you best practices and they also show you which practices to
avoid. Your teacher keeps you sane and confident as you learn your
craft.
I can recommend anything published by Big Nerd Ranch15 , such as iOS
Programming: The Big Nerd Ranch Guide16 . That said, there are various
books and courses that are very good. Don’t pick any book or course.
Make sure you team up with someone who knows his or her stuff.
Don’t pick or choose random tutorials you find on the web. I strongly
recommend choosing for a solution that show you the complete path.
The result is almost always confusion and frustration if you pick and
choose. This approach is fine once you’ve nailed the fundamentals. As a
beginner, though, I recommend sticking with a proven solution.
If you have money to spend and you want to speed up your learning,
you can enroll in a bootcamp to immerse yourself in Swift development.
The result is that you learn a lot in a very short period.
15
https://www.bignerdranch.com
16
https://www.amazon.com/iOS-Programming-Ranch-Guide-Guides/dp/0134682335
3 Know Your Tools
An important part of your foundation is knowing the tools you work
with. And this goes beyond just Xcode. I always encourage developers,
regardless of the company you work for, to know about every aspect of
building, testing, and shipping a Cocoa application. This chapter covers
the tools you need to know about and become familiar with. Let’s start
with the workhorse of every Cocoa developer, Xcode.
Xcode
Xcode is the most popular IDE for building Cocoa applications. There are
alternatives, such as JetBrains’ AppCode17 , but I won’t cover those in this
book. While Xcode has served me well over the years, there is, and has
always been, room for improvement.
While it’s important that you become familiar with Xcode’s user interface,
it’s not important to spend hours or days learning the ins and outs of
Xcode. My experience has taught me that developers usually don’t have
a hard time getting up to speed with Xcode. The basics are the same for
most IDEs and you learn about the more intricate features of Xcode over
time.
But that doesn’t mean you shouldn’t dig a bit deeper from time to time.
Xcode has a slew of hidden features and keyboard shortcuts. It’s worth
spending an hour here and there reading up on Xcode, watching a
WWDC session, or simply playing around with Xcode’s user interface.
I’d like to highlight a few components of Xcode that deserve special
attention and that you need to know about.
17
https://www.jetbrains.com/objc/
3 Know Your Tools 20
Documentation
Devices
The Window menu also gives you access to the Devices and Simulators
window. This is useful if you need to download the container of an
application or add a simulator.
Organizer
Xcode’s Organizer
Developer Portal
Even though Xcode can communicate with Apple’s servers on your
behalf, you sometimes need to visit Apple’s developer portal to take care
of specific tasks, such as creating a certificate or configuring an App ID.
It used to be tedious to work with the Developer Portal. This has
become easier and Xcode takes care of many trivial tasks, such as adding
capabilities to an App ID and generating provisioning profiles.
Provisioning
Most developers cringe when someone drops the word provisioning. An
application needs to be provisioned for it to run on a device. This is a
3 Know Your Tools 23
Instruments
Command Line
Tower
Tower is my favorite Git client and it gets better with every release. I use
the command line for simple Git operations, but most of the time I use
Tower to get the job done. It’s a perfect fit for my workflow.
Reveal
You probably know that Xcode includes a view debugger, allowing you to
inspect the view hierarchy of a Cocoa application. Reveal is a standalone
application that performs a similar task, but it does this much, much
better. Reveal has been around for several years and it also includes
support for tvOS applications.
Charles
set up, it works very well and can be a lifesaver for debugging network
issues.
PaintCode
The term best practices is overused in my opinion. I prefer to use the term
good practices. What I like about software development is that there’s
rarely one solution to solve a problem. That also implies that there are
no best practices, only good practices and habits.
Apple unveiled Swift only three years ago. Unless you’re Chris Lattner21 ,
the language is still very new to us. Many of us are still looking for
good practices to adopt. But how do you spot a good practice? Some
developers intuitively spot a good practice when they see one. It’s often
a solution to a problem that feels right. It looks elegant and, more often
than not, it’s easy to implement.
Take dependency injection as an example. This is one of the patterns
I teach in my book Learn the Four Swift Patterns I Swear By22 . Even
though many developers have a hard time wrapping their head around
21
https://twitter.com/clattner_llvm
22
https://cocoacasts.com/learn-the-four-swift-patterns-i-swear-by/
4 Adopt Best Practices 27
Patterns
Patterns are an important aspect of software development. They’re
proven recipes to solve problems. They allow you to get work done
instead of reinventing the wheel over and over.
Later in the book, I zoom in on several patterns I strongly recommend
you take a look at. They have become an integral part of my development
workflow. It doesn’t mean that you need to use or adopt these patterns
in your projects, but it can be eye-opening to explore them and learn
from them.
Anti-patterns
There are very few patterns I recommend that you avoid altogether.
They’re often referred to as anti-patterns. There’s one pattern that I have
a strong opinion about, the singleton pattern. While I don’t consider
the singleton pattern a bad pattern or an anti-pattern, I advise to use
it sparingly. Very, very sparingly.
4 Adopt Best Practices 28
The primary reason the singleton pattern has a bad reputation is misuse.
A common reason developers adopt the singleton pattern is conve-
nience. Do you remember what I said about convenience?
You probably know that the use of globals is an anti-pattern in most pro-
gramming languages. The singleton pattern gives you global access to
the singleton object. Doesn’t this start to smell? Unfortunately, this side
effect of the singleton pattern is the primary reason many developers
adopt the pattern. Don’t do that.
Embrace Optionals
The more I use Swift, the more I fall in love with the language. Value types
are one of the aspects I adore about Swift. We have structs and enums
in Objective-C, but they’re not nearly as powerful or easy to use as their
counterparts in Swift. Enums are fantastic and structs are a good fit for
a wide range of problems.
Value types and reference types each have their place and we need
references types to build Cocoa applications. The next time you define a
class, though, consider creating a struct or enum. Would that also work?
Later in the book, I go into more detail about the differences and the
benefits of value types and reference types. Use value types whenever
you can and use reference types when it feels you need them. You don’t
23
https://developer.apple.com/arkit/
4 Adopt Best Practices 30
need to choose one or the other. They complement one another quite
well.
The Swift language is composed of a small number of core values or core
ingredients. Once you discover what they are, you better understand
how the language works best and should be used. I already mentioned
value types and optionals. Later in the book, I also talk about protocols
and protocol-oriented programming.
Be Critical
Make It Hard
I once read that, if someone wants to access your data, then they will
succeed. How badly they want to access your data determines whether
they’ll succeed. I don’t know whether this is true, but I tend to err on the
side of safety.
Why is this important? It changed my perspective on security. It’s naive
to think that you can outsmart people that are trained to find and
extract the information they need. That doesn’t mean you need to be
complacent or ignore the advice you read. It simply means that your
actions and motivation change slightly.
An effective approach to security is to have the mindset to make it hard
for the other party to access the data you’re trying to protect. In other
words, you add several layers of security to protect the data of the user.
Let’s start with the basics.
Plain Text
If you have some experience developing software, you most likely know
that you shouldn’t store sensitive information in plain text. Ever. Don’t
5 Security 32
store the user’s username and password in the user defaults database,
for example. Use the keychain to protect this type of sensitive informa-
tion.
The same applies to networking. Apple and Google are actively forcing
developers to move away from HTTP and use SSL by default. Apple’s
App Transport Security encourages developers to be aware of the
security risks of their applications. Make sure that your application
communicates with remote services over a secure connection. This isn’t
always possible if you aren’t in control of the remote service. In such a
scenario, it’s up to you to decide what the next best option is.
But SSL may not always be sufficient. Your application is still susceptible
to, for example, man-in-the-middle attacks24 . You can remedy this by
adopting certificate pinning, adding an extra layer of security.
Obfuscating Information
Encryption
Encryption is an effective solution to protect the user’s data. Realm,
for example, has built-in support for encrypting the data stored in its
database. For Core Data, however, this is less trivial. I hope Apple will
make this less cumbersome in a future release of the framework.
The data the user stores on their device is automatically encrypted if
the device is protected with a password or Touch ID. Only you, the user,
can unlock the data stored on your device because you hold the key to
decrypt it, not Apple. It’s great to see that Apple continues to invest in the
privacy and security of its customers. Apple’s motivation25 is a bit more
nuanced, though.
Privacy
A lot has been written about privacy and protecting the user’s pri-
vacy. Unfortunately, many developers don’t realize that this also means
protecting the user’s privacy from companies that offer services they
use day in day out. If your application uses analytics or displays ads,
then you’re exposing the user’s personal information to the companies
behind these services.
I used to use Fabric for crash reporting and analytics, but I no longer
do for personal projects. As a developer, it’s my responsibility to protect
25
https://www.apple.com/privacy/approach-to-privacy/
5 Security 34
the user’s privacy and they expect that from me. I understand that many
developers don’t have this luxury, but I still believe that you should, at
a minimum, consider the option and be aware of the information you
may be exposing to third parties.
If you include a third party SDK in your application and you don’t have
access to the source, then how do you know what information you’re
sharing with this third party? You don’t. That’s important to keep in mind.
One of the most important pieces of advice in this book is simple but so
important, invest in your foundation. Once you have a solid foundation,
you’ll notice that picking up a new framework or solving a challenging
problem is possible. It’s no longer complex, it’s simply challenging.
But if you land a job at a company that kindly forces you to use the
in-house framework then your foundation is compromised. I’m sure
you can build beautiful applications that work very well. But I wonder
if you know and understand what’s happening under the hood? What
happens if you move to a new company? An in-house framework is
almost always the company’s intellectual property. Do you know how
to build applications without it?
Dependencies
This brings us to dependencies, a topic I cover in more detail later in the
book. I always try to minimize the number of dependencies I include in
6 Don’t Ignore Your Foundation 37
a project. Every dependency needs to earn its way onto the project. The
reality is that most don’t make it into the project’s Podfile or Cartfile,
which is a good thing.
I’m a big fan of lightweight abstractions or wrappers around frameworks.
Core Data is a fine example. I don’t use a library to work with Core
Data, but I create a handful of files that include convenience methods
to interact with the framework. These are usually specific to the project.
At the same time, you should be aware of the limitations of the API you’re
using. This is difficult when you’re starting out. Take the user defaults
system as an example. The user defaults database is meant for storing
small chunks of data. These are stored as key-value pairs.
While you can store complex object graphs in the user defaults database
(as long as you stick to the supported types) don’t be naive and store
megabytes of data in the user defaults database. It’ll probably work, but
it won’t be a performant or scalable solution.
Model-View-Controller
What Is MVC
Model
The model layer is responsible for the business logic of the application.
It manages the application state, which also includes reading and writing
data, persisting application state, and it may even include tasks related
to data management, such as networking and data validation.
9 Design Patterns 41
The M In MVC
View
The view layer has two important tasks, presenting data to the user and
handling user interaction. A core principle of the MVC pattern is the
view layer’s ignorance with respect to the model layer. Views are dumb
objects. They only know how to present data to the user and they don’t
know or understand what they’re presenting. This makes them flexible
and easy to reuse.
9 Design Patterns 42
The V In MVC
Controller
The view layer and the model layer are glued together by one or
more controllers. In an iOS application, that glue is a view controller,
an instance of the UIViewController class or a subclass thereof. In a
macOS application, that glue is a window controller, an instance of the
NSWindowController class or a subclass thereof.
9 Design Patterns 43
The C In MVC
A controller knows about the view layer as well as the model layer.
This often results in tight coupling, making controllers the least reusable
components of an application based on the Model-View-Controller pat-
tern. The view and model layers don’t know about the controller. The
controller owns the views and the models it interacts with.
9 Design Patterns 44
Model-View-Controller in a Nutshell
Advantages
Separation of Concerns
Reusability
While controllers are often not reusable, view and model objects are
mostly easy to reuse. If the Model-View-Controller pattern is correctly
implemented, the view layer and the model layer should be composed
of reusable components.
Problems
If you’ve spent any amount of time reading books or tutorials about iOS
or macOS development, then you’ve probably come across people com-
plaining about the Model-View-Controller pattern. Why is that? What’s
wrong with the Model-View-Controller pattern?
A clear separation of concerns is great. It makes your life as a developer
easier. Projects are easier to architect and structure. That’s only part of
the story, though. Much of the code you write doesn’t belong to the view
layer or the model layer. No problem. Dump it in the controller. Problem
solved? Not really.
An Example
An Example
The creation date of an invoice is stored in the model layer and the
view displays the formatted date. That’s obvious. But who’s responsible
for formatting the date? The model? Maybe. The view? Remember that
the view shouldn’t need to understand what it’s presenting to the user.
But why should the model be responsible for a task related to the user
interface?
Wait a minute. What about our good old controller? Sure. Dump it in the
controller. After thousands of lines of code, you end up with a bunch of
overweight controllers, ready to burst and impossible to test. Isn’t MVC
the best thing ever?
In recent years, another pattern has been gaining traction in the Cocoa
community. It’s commonly referred to as the Model-View-ViewModel26
pattern, MVVM for short. The origins of the MVVM pattern lead back
26
https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel
9 Design Patterns 47
Model-View-ViewModel
Model-View-ViewModel in a Nutshell
Despite its name, the MVVM pattern includes four components or layers,
the Model, the View, the View Model, and the controller.
27
https://en.wikipedia.org/wiki/.NET_Framework
9 Design Patterns 48
Advantages of MVVM
Let me start by asking you a simple question. What do you do with code
that doesn’t fit or belong in the view or model layer? Do you put it in the
controller layer? Don’t feel guilty, though. This is what most developers
do. The problem is that it inevitably leads to massive controllers that are
difficult to test and manage.
The Model-View-ViewModel pattern presents a better separation of
concerns by adding view models to the mix. The view model translates
the data of the model layer into something the view layer can use. The
controller layer is no longer responsible for this task.
Improved Testability
View (iOS) and window (macOS) controllers are notoriously hard to test
because of their close relation to the view layer. By migrating some
responsibilities, such as data manipulation, to the view model, testing
becomes much easier. Testing view models is surprisingly easy. Testing?
Easy? Absolutely.
Because a view model doesn’t have a reference to the view controller
that owns it, it’s easy to write unit tests for a view model. Another benefit
9 Design Patterns 49
Transparent Communication
Basic Rules
There are six key elements that define the Model-View-ViewModel pat-
tern. I sometimes refer to these as rules. However, once you understand
how the Model-View-ViewModel pattern does its magic, it’s fine to bend
or break some of these rules.
Rule #1
First, the view doesn’t know about the view controller it’s owned by.
Remember that views are supposed to be dumb. They only know how
to present what they’re given by the view controller to the user. This is a
rule you shouldn’t break. Ever.
9 Design Patterns 50
The view doesn’t know about the view controller it’s owned by.
Rule #2
Second, the view or window controller doesn’t know about the model.
This is something that separates MVC from MVVM.
9 Design Patterns 51
Rule #3
The model doesn’t know about the view model it’s owned by. This is
another rule that you shouldn’t break. The model should have no clue
who it’s owned by.
9 Design Patterns 52
The model doesn’t know about the view model it’s owned by.
Rule #4
Rule #5
The view or window controller owns the view or window. This relation-
ship remains unchanged.
9 Design Patterns 54
Rule #6
And finally, the controller owns the view model. It interacts with the
model layer through one or more view models.
9 Design Patterns 55
Give It a Try
If you’re new to Cocoa and Swift development, then I recommend
sticking with the Model-View-Controller pattern. It’s a proven pattern
that many of us have used for years to build software. But if you notice
that you’re starting to hit the limits of the Model-View-Controller pattern,
then it may be time to look for an alternative.
The Model-View-ViewModel pattern has changed how I write and think
about software. Even though the changes it introduces are modest,
the results are substantial. Combine the Model-View-ViewModel pattern
with reactive programming, which I discuss later in this chapter, and you
have a potent recipe to build software.
Singletons
The singleton pattern is a pattern developers quickly become familiar
with. When I first started dabbling with Cocoa development, I almost
9 Design Patterns 56
immediately came into contact with the singleton pattern. Many Cocoa
frameworks, including UIKit and Foundation, use the singleton pattern.
Because the Cocoa SDK makes use of the singleton pattern, developers
think that it’s fine to use singletons. It is fine to use singletons, but it’s
more nuanced than this.
Singletons Everywhere
Whenever I talk about singletons, I like to bring up Maslow’s hammer
analogy.
… but isn’t the manager object accessible from anywhere in your project?
This means that the user model object can be modified from anywhere
in your project. If you’re still with me, then I hope you can see that this
is starting to sound less and less like the great idea it initially appeared
to be.
How are you going to make sure that the objects that depend on the
currently signed in user are notified when the user is modified? Easy.
Notifications. Another popular option is to use a pattern similar to
Java’s observer pattern. You could use key-value observing, but do you
really want to observe the properties of an object that’s managed by a
singleton? That sounds like asking for trouble.
I agree that the singleton pattern seems convenient and it may occasion-
ally be warranted to use it, but the drawbacks almost always outweigh
the benefits. Unfortunately, the drawbacks are very subtle at first and
that’s what misleads many developers.
The structure of the project may seem flexible and loosely coupled, but
it’s anything but that.
1 class User {
2 var firstName = ""
3 var lastName = ""
4 }
5
6 class NetworkController {
7
8 let user: User
9
10 init(user: User) {
11 self.user = user
12 }
13
14 }
but it pays dividends in the long run. It adds clarity to the codebase,
unambiguously showing which objects depend on which objects.
It’s an advantage that passing an object by reference is less convenient.
Huh? It forces you to consider your decision. Does the NetworkController
class need access to the user model object? Would it suffice to pass the
user’s username and password instead? Dependency injection can be a
useful tool to define the requirements of an object.
A few years ago, I started working on a client project that was littered with
singletons. Some singletons even referenced other singletons, adding to
the problem. After several rounds of refactoring, I managed to eliminate
most of the singletons from the project, which drastically increased
transparency and robustness.
Have you ever worked on a project nobody in your team wanted to
touch? Modifying a handful of lines in one class could cause mayhem
in a distant, unrelated component of the project? This is not uncommon
for projects that make heavy use of singletons.
Another benefit of ridding a project of singletons relates to testing.
Writing unit tests without having to worry about singletons is fantastic.
It really is. Combine this with dependency injection and you have a great
combination to work with.
one time. That, however, is not the goal many developers have in mind
when using singletons.
Singletons are very much like the good things in life; they’re not bad if
used in moderation. The next time you’re about to create a singleton,
consider your motivation for creating it. Is it convenience? Then you
should not create that singleton. Period. That’s the simple rule I apply.
Dependency Injection
What Is It
An Example
1 import UIKit
2
3 class ViewController: UIViewController {
4
5 var requestManager: RequestManager?
6
7 }
We can set the value of the requestManager property one of two ways.
The first option is to task the ViewController class with the instantiation of
the RequestManager instance. We can make the property lazy or initialize
the request manager in the view controller’s initializer. That’s not the
point, though. The point is that the view controller is in charge of creating
the RequestManager instance.
9 Design Patterns 63
1 import UIKit
2
3 class ViewController: UIViewController {
4
5 var requestManager: RequestManager? = RequestManager()
6
7 }
This means that the ViewController class not only knows about the
behavior of the RequestManager class. It also knows about its instantiation.
That’s a subtle but important detail.
Another Example
Let me show you another example to emphasize the point I made in the
previous section. Take a look at the following example.
9 Design Patterns 64
1 protocol Serializer {
2
3 func serialize(data: AnyObject) -> NSData?
4
5 }
1 class DataManager {
2
3 var serializer: Serializer? = RequestSerializer()
4
5 }
I hope the above examples have at least captured your attention. Let me
list a few additional benefits of dependency injection.
Transparency
Testing
Separation of Concerns
Even though the DataManager class is concerned with the behavior of its
serializer, it isn’t, and shouldn’t be, concerned with its instantiation. What
if the RequestManager of the first example also has a number of dependen-
cies. Should the ViewController be aware of those dependencies too?
Coupling
The example with the DataManager class illustrated how the use of pro-
tocols and dependency injection can reduce coupling in a project. Pro-
tocols are incredibly useful and versatile in Swift. This is one scenario
in which protocols really shine. Later in this chapter, I write more about
protocols and protocol-oriented programming.
9 Design Patterns 67
Types
These types shouldn’t be considered equal, though. Let me list the pros
and cons of each type.
Initializer
1 class DataManager {
2
3 private let serializer: Serializer!
4
5 init(serializer: Serializer) {
6 self.serializer = serializer
7 }
8
9 }
9 Design Patterns 68
1 import UIKit
2
3 class ViewController: UIViewController {
4
5 var requestManager: RequestManager?
6
7 }
9 Design Patterns 69
Methods
1 class DataManager {
2
3 func serializeRequest(request: Request, withSerializer serialize\
4 r: Serializer) -> NSData? {
5 ...
6 }
7
8 }
Even though the DataManager class loses some control over the depen-
dency, the serializer, this type of dependency injection introduces flexi-
bility. Depending on the use case, we can choose what type of serializer
to pass into serializeRequest(_:withSerializer:).
Singletons
References
Delegation
Like any other view, a table view is in charge of responding to user inter-
action. Even though a table view can detect user interaction, it doesn’t
know how to interpret the touch events. This seeming disadvantage is
what makes table views reusable components.
A table view informs its delegate about the touch events it detects. It’s the
responsibility of the table view’s delegate, a view controller, for example,
to handle table view interactions. A table view is loosely coupled to its
delegate through the UITableViewDelegate protocol. The delegate object
is also loosely coupled to the table view. All it needs to do is conform to
the UITableViewDelegate protocol by implementing the methods defined
by the protocol.
Any class instance conforming to the UITableViewDelegate protocol can
act as the table view’s delegate. The table view doesn’t care and doesn’t
need to know which object acts as the table view’s delegate as long as it
conforms to the UITableViewDelegate protocol.
This is an example of protocol-oriented programming, which we cover
later in this chapter. As the name implies, the table view delegates tasks
to the delegate object. Delegation is a very common design pattern in
Cocoa applications and frameworks.
Notifications
The object that broadcasts the notification uses the same notification
center to post a notification with a particular name. It can optionally
include additional information in the form of a dictionary.
1 NotificationCenter.default.removeObserver(self)
9 Design Patterns 73
Be Careful
Notifications are an essential aspect of Cocoa development. Apple’s
frameworks define dozens and dozens of notifications for various pur-
poses. This may give you the impression that notifications are a proven,
reliable, and robust solution to send messages from one object to
another. While that’s true, there’s a catch.
Coupling
We like loose coupling. Right? Tight coupling is bad. This is true, but
how loosely coupled is the notification pattern. If you have an object
that subscribes to the UIApplicationDidEnterBackground notification, you
implicitly tie its implementation to the UIKit framework. There’s nothing
wrong with this, but it’s important to consider this. You’re implicitly
adding a dependency to the UIKit framework.
Debugging
handful of good practices if you do. Don’t use string literals to name
your notifications. Ever. Do yourself a favor and create an extension
for Notification and follow Apple’s lead. You can use your own naming
scheme, but I advise you to use constants for notification names.
1 import Foundation
2
3 extension Notification.Name {
4
5 static let DidResetStatistics = Notification.Name(rawValue: "Did\
6 ResetStatistics")
7
8 }
References
Delegation
Notifications
Great. I’m going to stick with notifications. For everything. It offers the
most flexibility, well, not exactly. It’s true that notifications are great for
9 Design Patterns 76
1 struct Item {
2
3 var title: String
4 var content: String
5
6 }
To add an item, the user taps a button in the navigation bar. This action
instantiates an instance of the AddItemViewController class. The class
declares a didAddItem property of type DidAddItemHandler?, a type alias for
a closure that accepts an Item instance as an argument. This closure is
invoked when the user creates and saves a new item.
9 Design Patterns 77
Before presenting the add item view controller, we set its didAddItem
property. The closure accepts an Item instance as its only argument
and that enables the items view controller to add the new item to the
array of items it manages. Not only removes this pattern the overhead
of creating and implementing a delegate protocol, it also keeps related
code together.
Reactive Programming
Later in this chapter, I talk about reactive programming. If you feel
comfortable using the Cocoa SDK and the Swift language, then it may
be time to look into reactive programming. It may seem daunting at
first, but it’s going to change how you think about code and software
development.
make heavy use of these patterns and it’s important to understand how
they work and when to use them. Even if you never define a delegate
protocol yourself, you inevitably need to use them if you build Cocoa
applications. And the same applies to notifications. And remember, this
is no rocket science.
6 Protocol-Oriented Programming
Before I continue, I need to tell you about Dave Abrahams33 . Dave works
at Apple and is a member of the Swift Core Team. A few years ago, at
WWDC 2015, Dave gave an amazing presentation that made waves in the
Swift community. In his presentation, Protocol-Oriented Programming in
Swift34 , Dave challenges, with a dash of humor, the defaults most of us
are used to.
I strongly encourage you to take some time to watch Dave’s presen-
tation about protocol-oriented programming. He does a much better
job explaining what protocol-oriented programming is and how you can
33
https://twitter.com/daveabrahams
34
https://developer.apple.com/videos/play/wwdc2015/408/
9 Design Patterns 80
benefit from it. Dave also zooms in on some of the key driving forces of
the Swift language. Like Dave emphasizes in his talk “Swift is a protocol-
oriented programming language.” and “At its heart, Swift is protocol-
oriented.”
What Is It
Let me start with a bit of context. The idea isn’t as difficult to grasp
as you might think. Most of us are used to the obvious benefits of
object-oriented programming, such as encapsulation, access control,
and inheritance. These are features we love and usually take for granted.
The truth is that object-oriented programming comes at a cost. We pay
a price for the conveniences it offers. Object-oriented programming has
its downsides and, without realizing it, we fight them on an almost daily
basis.
What are some of those downsides? Inheritance is great, but you need to
carefully choose the superclass your class inherits from. It’s not always
clear which methods a subclass can override and which ones it should
override.
Inheritance also means that subclasses inherit stored properties from
their superclass. That’s a good thing. No? Complex class hierarchies can
add a lot of cruft to your classes, and, because Swift requires you to
provide an initial value for every stored property, initialization can be
messy.
Classes are reference types and, while this is often exactly what you
want, it can lead to complex problems that are hard to debug. Shared
mutable state often leads to complexities that bite you at some point.
Flexibility
Using protocols instead of inheritance has its pros and cons. You prob-
ably know the advantages of inheritance. What does protocol-oriented
programming gain us?
In Swift, a class has only one superclass while a type can conform to
multiple protocols. While value types don’t support inheritance, structs
and enums can conform to protocols.
Be Careful
While protocols may seem convenient and flexible, they can also com-
plicate your codebase. I’ve worked on projects that were difficult to
understand because of the overuse of protocols.
Chris Eidhof wrote about this problem36 a few months ago. He illustrates
the versatility of a protocol-oriented design, but he also emphasizes that
it shouldn’t be your default choice.
7 Reactive Programming
As a developer, you’ll have several aha moments in your career. The
discovery of reactive programming was one of those moments for me.
When I first heard about reactive programming, I was skeptical. It looked
exotic and magical, and I discarded it almost immediately. A few years
later, RxSwift37 crossed my path and it clicked.
It’s true that there’s a learning curve, especially if you read random
tutorials on the web. But once it clicks, you see the benefits and what
reactive programming brings to the table.
What Is It
As I mentioned earlier, I was skeptical when I first heard and read about
reactive programming. I didn’t see why I should invest time in yet another
technology. Objective-C and Swift had served me well for many years. It
didn’t click for me at the time. Yet reactive programming has become an
integral part of my workflow. Why is that? What changed my mind?
Simplification
Removing State
While it’s this simplification that draws most developers to reactive pro-
gramming, you receive another important benefit if you decide to adopt
reactive programming. Because you’re observing and responding to
streams of values, you no longer maintain state. Why is that important?
Why is this a big deal?
Almost every application manages state in some form or shape. If you’re
developing a mobile application, then you need to reflect some of that
42
http://reactivex.io
9 Design Patterns 85
state in the user interface. While this may seem easy on paper, it’s much
harder than it looks. I’m sure you know what I mean if you’re working on
projects that have a bit of complexity to them.
Reactive programming makes this much easier. For the past few months,
I’ve been working on an application with a complex timer engine. This
would have been a nightmare without reactive programming. Instead of
keeping track of the state of the timer, the time, the current segment,
and on and on, the application observes and responds to the values of
several observable sequences. It’s amazing.
Coupling
All or Nothing
Model-View-ViewModel
Protocol-Oriented Programming
Type Safety
Best Practices
The more you read about Swift and the longer you spend time in the
Swift community, the more you realize that Swift is still a very young
language, especially if you compare the language with C and Objective-
C. A common problem developers face is the lack of best practices. They
look for strategies to solve common problems and struggle to find them.
Best practices are slowly taking form as more people use the language
in real-world scenarios.
This isn’t surprising. The Swift community is still exploring the language,
finding out what’s possible and how things can or should be done. The
language is still developing at a rapid pace and the open sourcing of the
language is another component that drives this swift evolution.
Several best practices are slowly taking shape, such as the adoption of
protocol-oriented programming, the value of immutability, and the use
of value types over reference types.
Warning Sign
Before the struggle ends, though, brute force is used to attack the
problem that optionals appear to be. After discovering the exclamation
mark, every optional is considered a nail that needs to be hit with
the proverbial hammer. Forced unwrapping and implicitly unwrapped
optionals are temporarily seen as the solution to the problem.
The exclamation mark is in Swift what you may intuitively expect it
to be, a warning sign. If you use the exclamation mark, you’re about
to perform an operation that may backfire. Forced unwrapping an
optional that doesn’t contain a value throws a runtime error, crashing
your application. The exclamation mark warned you this could happen,
though.
I recently received an email from a reader about the use of the excla-
mation mark. The company she works for has a simple policy, “Don’t
use the exclamation mark.” This may at times result in code that’s a bit
verbose, but the benefits are obvious. The code they write is safe and it’s
consistent.
3 Embracing Optionals 94
Swift doesn’t leave developers out in the cold. The language offers
a number of constructs for working with optionals, such as optional
binding and optional chaining.
Optional binding is used to safely unwrap the value that’s stored in
an optional. If the optional has a value, then that value is bound to a
constant that’s available in the if clause.
3 Embracing Optionals 95
This solution is more elegant than verifying whether message has a value
and then forced unwrap the optional using the exclamation mark.
1 if message != nil {
2 print(message!)
3 } else {
4 print("no value")
5 }
1 label?.textColor = UIColor.blackColor()
Embrace Optionals
While it may seem great that you can send messages to nil in Objective-
C, it’s an empty promise. If you consider your application not crashing
when you send a message to a nil pointer, then think again. Also,
consider that optionals can be used for any type while nil only applies
to pointers in Objective-C.
A few days ago, I had to open up an old project that was primarily
written in Objective-C. The absence of type safety and optionals was
immediately obvious. It may sound odd, but I miss optionals every time
I need to work with Objective-C.
If you’re serious about Swift, then it’s important that you become familiar
with optionals, which problems they solve, and embrace them in the
code you write.
4 Mind the Exclamation Mark
I’m sure the exclamation mark is a necessary aspect of the Swift lan-
guage, but I wouldn’t blink an eye if it were removed from the language
tomorrow. The exclamation mark is a warning sign, but too many devel-
opers ignore this and use it because it’s more convenient. Note that I’m
not referring to the logical NOT operator. That’s a perfectly valid use of
the exclamation mark.
As I mention later in the book, the use of the exclamation mark is often a
code smell. Because you’re trading safety for convenience, it should be
used sparingly.
Use Cases
The exclamation mark is used in several situations. The most common
use is forced unwrapping the value stored in an optional. As you know,
a runtime error is thrown if that optional doesn’t hold a value.
You also use the exclamation mark to declare an implicitly unwrapped
optional or when you want to disable error propagation. The same rule
applies. If you access the value of an implicitly unwrapped optional that
doesn’t contain a value or a throwing function throws an error when
error propagation is disabled, a runtime error is thrown.
Don’t Be Lazy
You probably heard the phrase “A lazy developer is a good developer.”
This saying is true, but it depends on what’s understood by lazy. Many,
many developers use the exclamation mark because it’s convenient. In
other words, they’re being lazy. I’d like to say that laziness or convenience
is never a valid reason for using the exclamation mark. Unfortunately, it’s
difficult to argue with that explanation.
Outlets
Outlets that should always have a value are declared as implicitly un-
wrapped optionals. As with every use of the exclamation mark, I only
declare an outlet as an implicitly unwrapped optional to conveniently
access its value. That’s the only reason. You can declare outlets as
optionals. That’s perfectly fine too.
If an outlet is declared as an implicitly unwrapped optional and it doesn’t
have a value when it’s accessed, then I made a mistake I need to fix.
Bear in mind that it’s possible to have optional outlets. In some projects,
I create a UIViewController class that serves as the base class for other
view controllers of the project. This class declares an optional table view
outlet. Because not every view controller has a table view, it’s wise and
necessary to declare the outlet as an optional.
4 Mind the Exclamation Mark 99
Required Properties
Swift works fine with the Cocoa SDK, but there are some rough edges.
You probably know that every stored property of a class or structure
needs to have a valid initial value by the time an instance of the type
is created. This is fine, but it presents some problems if you’re working
with storyboards. If you’re using storyboards, then you’re not in charge
of instantiating the view controllers of your application. This means that
you can’t implement a custom initializer that accepts values for every
stored property.
An approach that’s often used is that you configure the destination view
controller in the prepare(for:sender:) method of the source view con-
troller. At that time, the destination view controller is already initialized
and every stored property has an initial value. If you want to pass a
model object to the view controller, you need to declare the property
for that model object as an optional or, you guessed it, as an implicitly
unwrapped optional.
As I mentioned earlier, the motivation for declaring a property as an
implicitly unwrapped optional is always convenience. The reasoning
behind this choice, however, is more nuanced. Let’s assume you’re
implementing a view controller that displays the details of a note. You
pass the note to the detail view controller. The detail view controller is
useless if it doesn’t have a valid note to work with. In other words, the
note property of the detail view controller should always have a value.
No exceptions.
Later in this book, I discuss fatal errors. In this situation, I prefer to throw
a fatal error if the note property doesn’t have a value because that should
never happen in production. Unfortunately, I haven’t found an elegant
solution to implement this, which is why I use implicitly unwrapped
optionals instead.
4 Mind the Exclamation Mark 100
Resources
There’s one other use case in which I use the exclamation mark. If the
application needs to access a resource from its bundle, I don’t want to
deal with optionals. Why is that?
The resource, an image or a storyboard, should be present in the
application bundle. If it isn’t, then that means I have bigger problems
to worry about. Take a look at this code snippet to better understand
how I use this technique.
1 extension UIImage {
2
3 enum Icons {
4
5 enum Profile {
6
7 static let Segments = UIImage(named: "icon-profile-segme\
8 nts")!
9 static let Configuration = UIImage(named: "icon-profile-\
10 configuration")!
11
12 }
13
14 }
15
16 }
I also apply this technique to URLs that are hard-coded in the project.
4 Mind the Exclamation Mark 101
1 enum Audio {
2
3 static let Silence = Bundle.main.url(forResource: "rocknroll", w\
4 ithExtension: "mp3")!
5
6 }
7
8 enum API {
9
10 static let BaseUrl = URL(string: "https://api.myawesomeapplicati\
11 on.co")!
12
13 }
A Personal Choice
While it’s a personal choice when you use the exclamation mark and
what your motivation is, it’s important that understand why you’re using
the exclamation mark and what the consequences are. The next time
you append an exclamation mark to a variable, consider your motivation
and the risk. Choose wisely and don’t be lazy.
5 Exclamation Marks and Fatal
Errors
Fatal errors have a negative connotation and with reason. You should
use them sparingly if you want to avoid having your application crash
and burn at the slightest hiccup. Despite their negative undertone, fatal
errors are an integral part of my workflow as I write elsewhere in this
book.
Whenever I write or speak about my use of fatal errors, I usually see
two types of responses. Developers unfamiliar with fatal errors and how
they can be used safely are surprised and excited. They spot the benefits
fatal errors can bring to a project. Can you guess what the second type
of response sounds like?
1 // MARK: - Navigation
2
3 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
4 guard let identifier = segue.identifier else { return }
5
6 switch identifier {
7 case Segue.SelectProfile:
8 guard let destination = segue.destination as? SelectProfileV\
9 iewController else {
10 fatalError("Unexpected Destination View Controller for S\
11 egue")
12 }
13
14 ...
15 default: break
16 }
17 }
1 // MARK: - Navigation
2
3 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
4 guard let identifier = segue.identifier else { return }
5
6 switch identifier {
7 case Segue.SelectProfile:
8 let destination = segue.destination as! SelectProfileViewCon\
9 troller
10
11 ...
12 default: break
13 }
14 }
I understand that this practice is a bit controversial, but I’ve seen its
effectiveness. It’s why I’m a big fan of this pattern. As I mentioned earlier
in this chapter, the issue I have with the exclamation mark is that it isn’t
explicit enough, it’s too subtle. It’s easy to overlook it while browsing a
codebase.
The difference between the use of fatal errors and the use of the
exclamation mark is subtle. You could also say that the difference is easy
to miss, which is exactly why I bring it up. Give it a try and let me know
what you think.
6 Smelly Code
Pixelsync was the first iOS application I published on the App Store.
For a first project, it was quite complex and far more challenging than
I had anticipated. The project grew quickly as I added more features and
maintainability quickly became an issue I couldn’t ignore.
Looking back, the project was littered with anti-patterns, bad practices,
and code smells. Adding features to a large, complex codebase is chal-
lenging if it lacks direction and structure.
Many developers start out this way and learn as they go. It’s fine to make
mistakes as long as you learn from your mistakes and find solutions that
work better. In this chapter, I want to focus on common signs of code
smell in Swift.
Once you get used to optionals, you come to appreciate their value. Not
only are optionals making your code safer, they also make your code
more readable. An optional carries a message that says “I may not have
a value. Be careful.”
Developers new to Swift often see optionals as a hurdle, forcing them
to jump through a bunch of unnecessary hoops. Optionals need to be
unwrapped and that requires more code. There’s a shortcut, though.
It’s possible to forced unwrap optionals. Take a look at the following
example.
6 Smelly Code 107
This looks fine. Right? We’re certain that the dictionary of launch op-
tionals isn’t equal to nil, that the UIApplicationLaunchOptionsKey.url is
present, and that its value is of type URL.
It doesn’t matter how certain you are, an optional should be treated with
caution. Forced unwrapping or forced conversion is asking for trouble.
As I discussed in an earlier chapter, there are situations in which you can
use the ! operator, but do not forced unwrap an optional to avoid a guard
or an if statement or a few extra lines of code.
The updated example shows you how the guard statement can elegantly
and safely handle optionals. The guard statement tells us what we expect,
but, at the same time, it hints that we may not get what we expected.
Monster Classes
Massive Methods
Helper Methods
Property Observers
are several benefits, one of them being that it keeps the configuration
close to the outlet’s declaration.
I’m sure several developers frown when they see this pattern in the wild.
While I’m not sure, I believe I learned this trick from Natasha Murashev51 .
Credit where credit is due.
Ignoring Errors
It’s great to see that error handling is tightly integrated into the Swift
language. In Objective-C, it’s easy to ignore errors, a bit too easy if you
ask me. Have you ever seen something like this?
51
https://www.natashatherobot.com
6 Smelly Code 111
1 [managedObjectContext save:nil];
I don’t know any developer who enjoys error handling, but if you want to
write code that works and applications that can recover when things go
haywire, then you need to accept that error handling is part of the job.
Ignoring errors also makes debugging more difficult. Putting your head
in the sand isn’t the solution when things go wrong. Don’t worry, though.
Later in this book, we explore error handling in a bit more detail.
Singletons
String Literals
As I mentioned earlier, the goal of this chapter is to review the code you
write. How can I improve this? What side effects does this implementa-
tion have? Should I forced unwrap this optional? It rarely pays off to take
a shortcut.
7 Value Types and Reference
Types
When talking about object-oriented programming, most of us intuitively
think about classes. In Swift, however, things are a bit different. While
you can continue to use classes, Swift has a few other tricks up its
sleeve that can change the way you think about software development.
This is probably the most important shift in mindset when working with
Swift, especially if you’re coming from a more traditional object-oriented
programming language like Ruby or Objective-C.
An Example
It’s important that you understand the above concept so let me explain
this with an example.
1 class Employee {
2
3 var name = ""
4
5 }
6
7 var employee1 = Employee()
8 employee1.name = "Tom"
9
10 var employee2 = employee1
11 employee2.name = "Fred"
12
13 print(employee1.name) // Fred
14 print(employee2.name) // Fred
1 struct Employee {
2
3 var name = ""
4
5 }
6
7 var employee1 = Employee()
8 employee1.name = "Tom"
9
10 var employee2 = employee1
11 employee2.name = "Fred"
12
13 print(employee1.name) // Tom
14 print(employee2.name) // Fred
Value types are great for storing data. And they are even better suited
for storing immutable data. Assume you have a struct that stores the
balance of the user’s bank account. If you pass the balance to a function,
that function doesn’t expect the balance to change while it’s using it.
By passing the balance as a value type, it receives a unique copy of the
balance, regardless of where it came from.
Knowing that a value won’t change is a powerful concept in software
development. It’s a bold promise and, if used correctly, one that value
types can keep.
Manipulating Data
Value types usually don’t manipulate the data they store. While it is fine
and useful to provide an interface for performing computations on the
data, it’s the owner of the value that manipulates the data stored by the
value.
This results in a control flow that is transparent and predictable. Value
types are easy to work with and, another great benefit, they behave
admirably in multithreaded environments.
Why is that? If you fetch data from a remote API on a background thread
and pass the data, as a value, from the background thread to the main
thread, a copy is made and sent off to the main thread. Modifying the
original value on the background thread won’t affect the value that’s
being used on the main thread. Clean, simple, and transparent.
7 Value Types and Reference Types 118
While I hope I’ve convinced you to start using value types more often,
they’re not a good fit for every scenario. Value types are great for storing
data. If you pass around the balance of someone’s account in your
application, you shouldn’t be using a class instance. What you are doing
is passing around a copy of the current balance of the account.
But if you need to pass around the account itself, then you want to make
sure the objects that have a reference to the account are working with
the same account, the same instance. If the name of the account holder
changes, you want the other objects that have a reference to the account
to know about it.
Value types and reference types each have their value and use. It would
be unwise to choose one over the other. Andy Matuschak52 has a clear
stance on the benefits of value types and reference types in software
development and has given several presentations on the topic. Andy
describes the objects of an application as a layer that operates on the
value layer. That’s a great way to put it.
52
https://twitter.com/andy_matuschak
8 Catching Errors
I was thrilled to find out that error handling is built into the Swift
language. As I wrote earlier, it’s too easy to ignore errors in Objective-
C. You can still ignore errors in Swift if you choose to go that route, but
you need to be explicit about it.
This chapter won’t repeat what The Swift Programming Language53
has to say about error handling in Swift. Instead, I’d like to take the
opportunity to give you some tips about error handling. When should
you handle errors? Should you always notify the user if something goes
haywire? Where should you handle errors?
Error handling in Swift is intuitive and flexible. You can propagate errors
and handle them where it feels appropriate. The question is then,
“Where is it appropriate to handle errors?” The rule I apply in most
scenarios is simple and easy to adopt. Whenever an object performs an
operation and an error is thrown, the error is handled by the object that
still understands what the error is about. Let me explain what I mean by
this with an example.
53
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_
Language/
8 Catching Errors 120
approach is ideal, but the latter group is at least informed when some-
thing goes wrong.
User Action
Many operations can go wrong or backfire. When should you notify the
user? Let’s start with the most obvious scenario. When the user performs
an action that backfires, she should be notified that her action was
unsuccessful.
Is this a hard rule? No. If the user likes a post on Facebook and the API
request was unsuccessful, you may only want to notify her if she’s still
on the page she liked. If the failed API request is the result of a poor
network connection, then that would mean the user is notified after the
network request timed out. That may be too late for the user to make
sense of the error.
Background Operations
1Password
If something goes funky, the user can read about it in the settings of the
application.
8 Catching Errors 123
I’m sure you’ve seen error messages with a cryptic message or error
code. You should avoid this at any cost. It doesn’t help the user to see
an alert with an HTTP status code. In fact, it may concern and annoy the
user.
The downside of mobile applications is that you can’t easily monitor your
application’s performance or health in real time. This is very different for
web applications.
How are you going to stay informed about your application’s perfor-
mance and health the moment it’s in the hands of your customers? Are
you going to wait until your customers email you? We cover this in more
detail later in the book. For now, I want to emphasize that you need eyes
on your application from the moment your application is in production.
How often does your application crash? Which errors occur most often?
What is the cause of these errors?
I think that knowing how, when, and where to handle errors is what stops
many inexperienced developers from handling errors properly. There is
no clear-cut recipe for error handling and that can be frustrating. The
guidelines I present in this chapter should give you a better idea where
to start and I hope it’s clear that you shouldn’t ignore errors.
9 Using Fatal Errors to Write
Elegant Swift
Speaking of errors, a few months ago I stumbled on a discussion in
the thoughtbot guides56 about the use of fatal errors in Swift. It seems
every developer has an opinion about fatal errors and a consensus
hasn’t been reached yet in the Swift community. The only mention in
The Swift Programming Language57 is in the section that discusses the
guard statement and early exit.
Ever since I started working with Swift, I’ve been struggling with the
implementation of the tableView(_:cellForRowAt:) method. If you think
that sounds silly, then take a look at the following example.
56
https://github.com/thoughtbot/guides/issues/440
57
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_
Language/index.html
9 Using Fatal Errors to Write Elegant Swift 125
There are several variations of the above implementation and I’ve tried
all of them. The idea is simple. We expect an instance of the Set-
tingsTableViewCell class if we ask the table view for a cell with the reuse
identifier of the SettingsTableViewCell class. Because the dequeueReusable-
Cell(withIdentifier:for:) method returns a UITableViewCell instance, we
need to cast the result to an instance of the SettingsTableViewCell class.
This is inconvenient since we always expect to receive a SettingsTable-
ViewCell instance if we ask the table view for a cell with the reuse iden-
tifier of the SettingsTableViewCell class. We could use the as! operator
instead of the as? operator, but that isn’t a solution I feel comfortable
with. Remember that I avoid the exclamation mark whenever I can.
If for some reason, something goes wrong, we return a UITableViewCell
instance from the tableView(_:cellForRowAt:) method. But that should
never happen. Right?
While this is fine and necessary to make sure we return a UITableViewCell
instance from the tableView(_:cellForRowAt:) method, I hope you can see
that we’re implementing a workaround for a scenario we don’t expect, a
scenario that should never occur.
9 Using Fatal Errors to Write Elegant Swift 126
The application crashes if a fatal error is thrown. Why is this better? This
is a better solution for two reasons.
Unexpected State
This doesn’t mean that you need to use fatal errors whenever you want
to avoid error handling or the application enters a state that’s hard to
recover from. I use fatal errors only when the application can enter in a
state it wasn’t designed for. Take a look at the following example.
1 import Foundation
2
3 enum Section: Int {
4
5 case news
6 case profile
7 case settings
8
9 var title: String {
10 switch self {
11 case .news: return NSLocalizedString("section_news", comment\
12 : "news")
13 case .profile: return NSLocalizedString("section_profile", c\
14 omment: "profile")
9 Using Fatal Errors to Write Elegant Swift 128
Choosing a Template
Give the project a sensible name and check Include Unit Tests and
Include UI Tests. I never check Use Core Data for production projects.
1 A Brand New Project 132
I always start by cleaning up the project. This simply means putting the
application delegate in a separate group, organizing the view controllers,
and making sure no files live at the root of the project. Small projects
don’t have the problem of becoming cluttered, but large projects do, and
very quickly at that.
The idea is simple. This is the project Xcode has created for us.
1 A Brand New Project 134
And this is the project after adding some structure. Later in this book, I
take a closer look at organizing a project in Xcode and how to use groups
and folders to keep everything nice and tidy.
1 A Brand New Project 135
1 # Project Name
2 ## Author: Bart Jacobs
3 ### Description: Lorem ipsum dolor sit amet, consectetur adipiscing \
4 elit. Curabitur ac dolor justo, ac tempus leo. Etiam pulvinar eros a\
5 t lectus sollicitudin scelerisque. Aliquam erat volutpat. Suspendiss\
6 e eu eros non elit blandit suscipit. Morbi scelerisque euismod tempu\
7 s.
8
9 ### Dependencies:
10 - Unbox
11 - RxSwift
12 - RxCocoa
13 - Reveal
1 #########################
2 # **.gitignore** file for Xcode4 / OS X Source projects
3 #
4 # NB: if you are storing "built" products, this WILL NOT WORK,
5 # and you should use a different **.gitignore** (or none at all)
6 # This file is for SOURCE projects, where there are many extra
7 # files that we want to exclude
8 #
9 # For updates, see: http://stackoverflow.com/questions/49478/git-ign\
10 ore-file-for-xcode-projects
11 #########################
12
13 #####
14 # OS X temporary files that should never be committed
15
16 .DS_Store
17 *.swp
18 profile
19
20
21 ####
22 # Xcode temporary files that should never be committed
23 #
24 # NB: NIB/XIB files still exist even on Storyboard projects, so we w\
25 ant this...
26
27 *~.nib
28
1 A Brand New Project 138
29
30 ####
31 # Xcode build files -
32 #
33 # NB: slash on the end, so we only remove the FOLDER, not any files \
34 that were badly named "DerivedData"
35
36 DerivedData/
37
38 # NB: slash on the end, so we only remove the FOLDER, not any files \
39 that were badly named "build"
40
41 build/
42
43
44 #####
45 # Xcode private settings (window sizes, bookmarks, breakpoints, cust\
46 om executables, smart groups)
47 #
48 # This is complicated:
49 #
50 # SOMETIMES you need to put this file in version control.
51 # Apple designed it poorly - if you use "custom executables", they a\
52 re
53 # saved in this file.
54 # 99% of projects do NOT use those, so they do NOT want to version c\
55 ontrol this file.
56 # ..but if you're in the 1%, comment out the line "*.pbxuser"
57
58 *.pbxuser
59 *.mode1v3
60 *.mode2v3
61 *.perspectivev3
62 # NB: also, whitelist the default ones, some projects need to use\
63 these
1 A Brand New Project 139
64 !default.pbxuser
65 !default.mode1v3
66 !default.mode2v3
67 !default.perspectivev3
68
69
70 ####
71 # Xcode 4 - semi-personal settings, often included in workspaces
72 #
73 # You can safely ignore the xcuserdata files - but do NOT ignore the\
74 files next to them
75 #
76
77 xcuserdata
78
79 ####
80 # XCode 4 workspaces - more detailed
81 #
82 # Workspaces are important! They are a core feature of Xcode - don't\
83 exclude them :)
84 #
85 # Workspace layout is quite spammy. For reference:
86 #
87 # (root)/
88 # (project-name).xcodeproj/
89 # project.pbxproj
90 # project.xcworkspace/
91 # contents.xcworkspacedata
92 # xcuserdata/
93 # (your name)/xcuserdatad/
94 # xcuserdata/
95 # (your name)/xcuserdatad/
96 #
97 #
98 #
1 A Brand New Project 140
As you can see it includes references to Xcode 4, which shows you how
long I’ve been using this .gitignore file. It works well for me. While most
of the contents are easy to understand, there are a few details that are
worth pointing out.
At the bottom, you can see a reference to CocoaPods, the dependency
1 A Brand New Project 141
manager of my choice. The /Pods entry means that I ignore the entire
Pods directory. This is a personal choice and it has its pros and cons. I’ve
never run into the cons, which is why I’ve stuck with this option.
While ignoring the Pods directory is fine and up to you to decide, you
should never ignore Podfile.lock or, if you’re using Carthage, Cart-
file.lock. As the extension of the file implies, a lock file locks the current
configuration. A project’s Podfile or Cartfile describes the project’s
dependencies, optionally specifying the version that should be used. The
project’s Podfile.lock or Cartfile.lock locks the current configuration,
including the version that is used by the project.
Putting lock files under source control is especially important if you’re
working in a team. When a team member checks out the repository and
installs the project’s dependencies by running pod install or carthage
bootstrap, you want to make sure they’re including the correct version
of each dependency.
The .gitignore file also defines that I ignore any personal preferences
and settings. This is recommended for teams. You don’t want to clutter
the repository with the preferences of every team member that worked
on the project.
To be clear, I didn’t create this .gitignore file from scratch. I don’t recall
where I picked it up, but it’s important to be critical of things you pick up
from elsewhere. Make sure you understand every line of the .gitignore
file you use in your projects.
The most popular version control system in the Cocoa and Swift com-
munities is Git59 . It’s a wonderful piece of software with many features
and it’s easy to get started with. This book won’t cover the details of Git,
59
https://git-scm.com/
1 A Brand New Project 142
1 git init
2 git add .
3 git commit -m "Project setup"
I very much enjoy using GitHub60 and, to make sure my work is safe,
I create a private repository and push the project to GitHub. You can
use other solutions as well, such as Bitbucket61 or GitLab62 . Once you’ve
created the repository on GitHub, you only need to add it as a remote
and push the repository.
You can take it a few steps further and, if you’re working in a company,
that may be necessary. These steps usually include adding a Gemfile63 ,
setting up continuous integration or creating a project in a management
tool. These steps are optional, though.
63
http://bundler.io/gemfile.html
2 Project Structure
The application templates that ship with Xcode aren’t the best examples
for developers new to Cocoa development. A new project in Xcode isn’t
structured in any way and the project folder on disk isn’t either. This isn’t
an approach that scales and it’s not something I can recommend.
One of the subtle details students appreciate about my books and
courses is that they see what a production project can look like. Can not
should. I believe it’s important to stick to a set of guidelines to make sure
you introduce consistency and structure into your projects.
That’s probably what I appreciated most when I created my first Ruby
on Rails application. David Heinemeier Hansson64 emphasizes that Ruby
on Rails is an opinionated framework providing sensible defaults. Such
an approach has its pros and cons. A definite upside is that a Ruby
on Rails application expects a particular project structure. Developers
new to Ruby on Rails like this, but I can imagine that more experienced
programmers develop their own opinions over time.
I’m sure you agree that any structure is better than no structure. The
approach I use has evolved over the years. For example, when I started
to adopt the Model-View-ViewModel pattern in my projects, I made a
few tweaks to my projects’ structure. That’s fine. The core idea is to be
consistent and to have a project structure that works for you and your
team.
An Example
to give you a peek behind the scenes of one of my recent projects. Every
project I create and work on adopts this project structure. It works for
me, but I understand that other solutions work equally well. Remember
that consistency is key.
As I wrote in the previous chapter, the first thing I do when I create a new
project in Xcode is refactor the project’s structure. I put the application
delegate in its own group and I create a group named, View Controllers,
for the modules of the application. For me, a module is nothing more
than a screenful of content or a reusable user interface.
2 Project Structure 146
View Controllers
Storyboards
Core Data
Resources
UIKit Subclasses
View Controllers
The View Controllers group is split up into several subgroups, one for
each module of the application. This split is almost always specific to
2 Project Structure 149
the project. Use your common sense and see what works best for your
project.
Every module contains subgroups for the view controllers of that mod-
ule and such a subgroup usually contains several subgroups, such as
protocols, view models, table view cells, and collection view cells. This is
very often specific to the project.
Test Target
UIKit Subclasses
It frequently happens that I create mock and other helper types. These
are also lumped together in separate groups, Mocks and Helpers re-
spectively.
2 Project Structure 150
On Disk
Prior to Xcode 9, a group in Xcode’s Project Navigator didn’t correspond
with a folder on disk. This has finally changed. In Xcode 9, a group by
default corresponds to a folder on disk. This means that the project
structure you create in Xcode more or less corresponds to a folder
structure on disk.
If you’re using an earlier version of Xcode, I strongly recommend that you
manually create a folder for every group you create in Xcode’s Project
Navigator. This is tedious, but it’s well worth the investment. And it isn’t
difficult.
You create a group in the Project Navigator and copy the name of the
group. Open the File Inspector on the right, click the folder icon in the
Location section, and create a new folder with the same name as the
group in the Finder window that appears. Choose the newly created
folder and click Choose to link the group to the folder. Any files or other
groups that you add to the group in Xcode are automatically added to
the folder that’s linked to the group.
What Do I Gain
Sticking to a project structure makes it easier to find what I’m looking
for, but it also allows me to focus on what matters, that is, the code that
I write. Focus is a topic I mention a lot in this book because it’s essential if
you want to get meaningful work done. An organized project that sticks
to a structure that makes sense is one less distraction to worry about.
Tools
There are several tools and scripts that help you with organizing your
projects. The best known tool is liftoff65 , created by the folks at thought-
65
https://github.com/liftoffcli/liftoff
2 Project Structure 151
bot66 . It’s a command line tool that allows developers to quickly create a
new Xcode project that sticks to a predefined project structure.
This can be useful if you’re working in a team and every project needs
to, and should, use the same project structure.
Caveats
This project structure works for many projects, but there are a few
caveats. What happens if your project manager or the designer intro-
duces major changes? In such a situation, you need to make changes
to the structure of your project. That’s the downside. The question is
whether this is necessary and warranted. Shouldn’t the developer start
developing once the design and feature set is agreed on?
66
https://thoughtbot.com
3 Project Hygiene
In the previous chapter, I wrote about structuring the projects you work
on. This applies to every software project. What I didn’t discuss in the
previous chapter is project hygiene. What should be kept under source
control? What do you do with old files and assets?
Projects Evolve
As a project grows and ages, more stuff makes its way into the reposi-
tory. That isn’t a problem because it’s inevitable. Fortunately, the project
is under source control. You’re using source control. Right?
Whenever I inherit an existing project, I start by exploring the project’s
repository and its history. You’d be surprised by what I sometimes
discover in projects. Two things that stand out, though, obsolete files
and files that shouldn’t be kept in a repository.
Obsolete Files
From the moment you no longer need or use a file, delete it. It’s that
simple. Some developers are reluctant to delete stuff and clean up a
project. They usually have a clear motivation. It’s either laziness or the
fear that they might need it later. Some day.
Good programmers are lazy, but this isn’t the type of laziness that the
adage is referring to. This is sloppiness that you should avoid. If you’re
a team lead, make sure you avoid this type of behavior in your team.
Project hygiene is just as important as taking your car to the shop every
so often.
3 Project Hygiene 153
The fear some developers have when they need to delete a file is
unwarranted if you’re embracing source control. The idea underlying
source control is exactly why you don’t need to be afraid to experiment
or delete stuff. Trust your version control system, make sure you have
backups of your repository, and hit the delete button when something’s
no longer needed.
Comments
The same applies to comments. Comments are great. I love comments,
a bit too much according to some people. But comments shouldn’t be
used to comment something out, commit it, and save it for later. If a
chunk of code is no longer used, then delete it. Should you need it later,
then source control is there for you.
Whenever I see a piece of code commented out, a warning bell goes off in
my head. Clean it up and commit it to the repository. Seriously. Embrace
source control and learn to trust it.
Documentation
Keeping documentation up to date can be challenging. I’m not aware
of a infallible solution to this problem. That said, make sure you reg-
ularly update the documentation of your projects. Take a look at the
documentation and make sure recent changes are reflected in the
documentation.
Did you switch from CocoaPods to Carthage? That means you probably
need to update the project’s README. Is there still a Podfile at the
project’s root? And what about the Pods project? Obsolete configuration
files are more common than you think. Did someone experiment with a
command line tool that generated a configuration file and didn’t bother
to removing it when they no longer needed it? It happens.
The best strategy that I know of to keep documentation up to date is
surprisingly simple. It works best if it’s made explicit by turning it into
3 Project Hygiene 154
into an issue? No problem. Debug the problem and update the README
to make sure this doesn’t happen in the future. That’s not unreasonable.
Is it?
Make It Easy
Documentation is only useful if people use it. If you hide the style guide
of your team in a hard to find folder structure that’s shared on Google
Drive or Bitbucket, then the chances are that nobody’s going to make an
effort to look for it, let alone use it. It doesn’t matter what solution you
use, as long as you make sure your team can access it with a few clicks
or key strokes.
There are several open source solutions that make it easy to automati-
cally generate documentation for libraries or projects. This means that
the documentation is automatically updated when you push a commit.
Looking into an automated solution may be well worth your time.
You can even integrate your documentation with documentation browsers
or make them available online. CocoaDocs68 is a nice example of this
strategy. I believe it’s no longer maintained, but the tools that power
CocoaDocs are open source and available for you to use.
What to Document
The short answer is simple. Everything. The reason I recommend to
document everything is simple. It’s always a pain to figure something
out and most of the time you don’t have the time to mess around.
I remember that, years and years ago, I created a step by step guide
to set up a LAMP stack on macOS. This changed with every release,
and every time I installed a fresh copy of macOS or purchased a new
computer, I had to figure out how to set up a LAMP stack. Having this
step by step guide was a life saver. Every. Single. Time.
68
http://cocoadocs.org/
4 Document Everything 158
Up to Date
What do you do if you are a team of one? You’re a freelancer or you run a
small product business. The same rules apply. It simply means that you
need to take care of everything yourself. The rules are simpler. You’re
the owner, which means that you’re in charge of keeping everything up
to date.
Don’t make the mistake that you’ll remember how to set up Jenkins six
months from now. You won’t. Write it down and document it. You’ll be
glad you did six months from now.
Some people go the extra mile and write a blog post. They document
their frustrations by providing a step-by-step guide to, for example, set
up a build server. Thousands of people will thank you for it.
Make It a Habit
If you’re a team leader or a manager, then make sure your team makes
documenting a habit. This can be challenging, but it’s necessary. Every
developer should learn that not every aspect of software development
is fun or enjoyable.
A developer who makes documenting a habit understands what soft-
ware development is about. It’s more than writing code and making
beautiful user interfaces. Software development is creating something
that lasts. It should work today and a year from now. Documentation is
a tiny gear in the machine that makes that possible.
Time Is Money
Isn’t it also true that no company measures how much time is lost
figuring out things that should have been documented? Think about that
and then consider the return on investment of proper documentation.
Part 4: Workflow
1 Testing
Developers often feel guilty when I start talking about testing. They
sheepishly turn their head or mumble that they’ve been planning to
write tests but haven’t found the time. You shouldn’t feel ashamed if
you’ve never written a test. That said, you should consider starting today.
Where to Start
If you’re unfamiliar with testing, then the subject feels abstract and com-
plex. That’s the feeling I had before I started writing unit tests. The truth
is that testing isn’t that difficult if you break it down. Like documentation,
it’s a topic many developers don’t give much consideration.
Start Simple
The easiest tests to write are usually those that test the model layer of
your application. If you’re new to unit testing, then it’s a good idea to
start there. Don’t start with testing view controllers or Core Data models.
If you’re new to unit testing, then that will only confuse you.
Choose a tiny class or struct, create a test target, and write your first unit
test. Run the unit test and be surprised by how easy that was.
Code Coverage
While you can test a project without it, code coverage gives you an idea
of how well your project is covered by your test suite. There are various
tools and techniques for calculating code coverage. Apple added native
support for code coverage in Xcode 7.
1 Testing 163
Revealing Weaknesses
There’s a more important reason why I was excited when Apple added
support for code coverage to its IDE. Code coverage reveals weak spots
in the unit tests that I write. Xcode shows you which code paths are
triggered when the test suite is run. Green means that a code path is
triggered by the test suite and red means a code path isn’t triggered by
the test suite. In other words, red means that I need to write more unit
tests.
This occasionally happens when edge cases are in play. We have the
tendency to test the happy paths and overlook or ignore the edge cases.
What happens if the backend returns an empty result or the format of
the file you’re loading isn’t what the application expects?
When you write a test for a function or method, you’re forced to think
about the implementation of that function or method. You approach the
implementation from a different perspective.
Break It Down
Lengthy methods and massive view controllers are almost always symp-
toms of code smell, subtly telling you that it’s time for a round of
refactoring. An important benefit of writing tests is that it pushes you
to keep methods short and focused.
As a general rule, a method should focus on one thing and one thing
only. If you adopt that strategy, methods no longer span dozens or,
heaven forbid, hundreds of lines. Massive methods are very hard to test.
Not only is it difficult to understand what you’re testing, too many
variables are in play, each affecting the implementation and the corre-
sponding tests. The number of code paths you need to test becomes
unwieldy and the result is often that no unit tests are written or the
method isn’t properly covered by unit tests.
Keep It Simple
It’s better to have a handful of short and focused methods than one
monstrous one. Why is that? The most obvious benefit is that con-
cise methods are easier to understand. It’s easier to wrap your head
around the method’s implementation. You have a better understanding
of what’s going on and what the possible outcomes are.
Another important benefit is the naming of methods. If you create a
method that spans dozens of lines and is responsible for half a dozen
tasks, then what are you going to name that method? If you break that
method down into smaller methods, each with a particular focus or task,
naming these methods will be easy and straightforward.
By keeping it simple, you gain clarity. By creating massive methods or
classes, you create chaos and lose focus.
1 Testing 165
Dependency Injection
From the moment I became serious about unit testing, I lost my fondness
for singletons and came to like dependency injection. It felt as if I
graduated as a programmer and no longer needed the singleton pattern
to glue the pieces of a project together.
Dependency injection is a wonderful concept that’s often ignored or
discarded in favor of the singleton pattern. Even though I don’t dislike
singletons, I always ask myself whether there’s a better solution to solve
the problem that doesn’t involve a singleton. Hint. There often is.
Dependency injection, mocking, and testing is a powerful and flexible
combination. Mocking and stubbing also become much easier with
dependency injection.
Xcode’s support for testing has gradually improved over time. With its
support for code coverage, you now get a nice test report and the source
editor shows you if a particular code path was triggered by the project’s
test suite.
1 Testing 166
As I mentioned earlier, code coverage isn’t magical and it has its flaws.
You shouldn’t solely rely on code coverage when writing unit tests. That
said, it makes it much easier to spot holes in your project’s test suite.
Even though XCTest has improved over the years, I usually use a few
additional libraries for making testing easier and more powerful. For
Objective-C projects, I have come to love and rely on OCMock69 , a mock-
ing library for Objective-C. Because OCMock hooks into the Objective-C
runtime, there currently isn’t an equivalent for Swift projects.
OCMock allows you to test more aspects of your code. It’s easy to mock
objects and stub methods, enabling you to test parts of your codebase
you wouldn’t be able to test with only XCTest in your toolbox.
Another library that’s great for testing is OHHTTPStubs70 . As the name
implies, this library makes stubbing network requests effortlessly. With
OHHTTPStubs, you no longer have an excuse to ignore networking logic
in your project’s test suite.
Not writing unit tests doesn’t make you a bad programmer. But you
should ask yourself why you’re not writing unit tests. Most studies show
that you save time in the long run because breaking changes are easier
to find and bugs are less likely to creep into your project’s codebase. It
also gives you more confidence in the code you write.
Earlier in this chapter, I briefly touched on a topic that’s very often
overlooked by developers, especially those that are new to unit testing.
What are you testing?
69
http://ocmock.org/
70
https://github.com/AliSoftware/OHHTTPStubs
1 Testing 168
Public Only
There is one caveat you need to be aware of. As a tester, you’re not
interested in the private methods and properties of the entity you’re
testing. That’s fine because that’s what black-box testing is about. But
it also means that you need to carefully craft the unit tests you write. It
71
https://en.wikipedia.org/wiki/Black-box_testing
1 Testing 169
can often mean that you need to write multiple unit tests for one public
method or property. Why is that?
If you want to have complete code coverage for the entity you’re unit
testing, you need to make sure every code path of the entity under test
is executed, including those of private methods and properties.
As I discussed earlier in this chapter, Xcode can help you with this. If
you enable code coverage, Xcode to collect code coverage data for you.
It visualizes code coverage for an entity in the gutter on the right of
the source editor. The number indicates how many times the unit tests
entered a particular code path. This is helpful to find out where your unit
tests fall short.
It Takes Time
What Is It
The name continuous integration may sound daunting or scary, but it
really shouldn’t. The idea is simple. One or more developers work on
a project and push their changes to a shared repository. Whenever a
push is detected, a series of automated steps is set into motion. This
usually involves creating a build, executing a test suite, and performing
a number of quality assurance steps.
There are several benefits to using continuous integration. One of the
benefits I appreciate most is that no human interacts with the final
product after code is committed to the repository. Other benefits include
test automation, code analysis, and build optimization.
TestFlight
I used to use Fabric for distributing test builds to testers. Apple’s acqui-
sition of TestFlight has changed this for me. The reason is simple. I only
need to send one binary to Apple’s servers. The same binary is used
by Apple to create a test build and a build for the App Store. My job
is limited to selecting the build I want to deploy to the App Store. What
your testers are testing is what your customers are going to download
and use. Fantastic.
This is the goal you need to try to reach regardless of the solution you’re
using. The build that your testers are testing should be identical from a
functional perspective to the one you send to Apple. This implies that
both builds reference the same commit in the repository. TestFlight
makes this very easy. Other solutions, such as Fabric and HockeyApp,
may require you to do a bit of additional work since these solutions don’t
neatly integrate with iTunes Connect as far as I know.
Choose a continuous integration solution that integrates with TestFlight,
if you opt for TestFlight, and that’s able to send builds to iTunes Connect.
2 Continuous Integration 173
You don’t want to do this manually. Remember that choosing the correct
build or archive to upload to iTunes Connect is another manual step you
need to avoid. You don’t want to be the one that uploaded the wrong
build to iTunes Connect.
Painless Releases
You need to avoid that releases are stressful and chaotic. An automated
workflow can and should help you with this. I realize that not every devel-
oper has the fortune to work in a company that embraces automation
and testing. Why don’t you make a start by writing a build script that
automatically updates the build number?
You can even leverage existing open source tools for that, such as fast-
lane72 , a powerful suite of command line tools that automate common
tasks, such as building, testing, generating screenshots, and sending
builds to iTunes Connect.
Make It Robust
Transparency
Notifications
If a build fails or unit tests don’t pass, then every person working on the
project, including the project manager, should be notified of this event.
It should always be obvious who needs to take action to fix the problem.
If the team’s workflow is sloppy and not respected by the people working
on the project, then notifications pile up and they’re ignored. This is very
similar to warnings in Xcode. From the moment you ignore one warning,
it’s very easy to ignore the second and third warning. After a while, you
no longer pay attention to warnings, which is a critical, and often painful,
mistake.
Notificationitis
Learning Curve
Technical Debt
software, you know that there’s working and working. If a developer tells
me “It works.” and he shrugs his shoulders, then I know it’s time for a
code review.
Core Data is a fine example. If you’ve worked with Core Data, then
you know that getting the data model right is a crucial aspect. It’s not
unusual that a data model changes over time as the application gains
features and complexity. Those changes, however, are evolutionary.
They build on what you already have. Getting the data model wrong in
a fundamental way, however, is a pain. You don’t want to go through
several lightweight or heavyweight migrations to fix something you
could have fixed from the start.
I’m currently working on a project with a complex timer engine. It has
taken me several rounds of refactoring before I ended up with a solution
I’m happy with. Why is that? Implementing a solution to a complex
problem often feels like putting together a puzzle in the dark. It takes
time before you see the bigger picture. It takes time before you can see
every component that’s involved and the various edge cases.
Think ahead and define in the data model that an account can have mul-
tiple users. And to make your current work easier, define a computed
property, user, that fetches the first user. In other words, you’re currently
working in code as if an account has one user, but the data model already
has support for multiple users.
The line between premature optimization and anticipating growth is
fine, but it really pays off to spend some time considering these deci-
sions. Code reviews and analysis can really help with this. Let yourself
be challenged by another team member. Listen to their arguments,
questions, and input.
It’s possible that you’ve invested hours, days, or even weeks into the
implementation of a solution to a challenging problem you’re faced with.
You’ve poured hours and hours into this solution. It works, well, most
of the time. The longer you spend on the problem and implementing a
solution, the more you realize that your solution is flawed. That can be
a hard pill to swallow.
Some of us are too proud to throw their work into the trash and start
anew. Sometimes you don’t even have that luxury. It can be particularly
frustrating if you’re working for yourself and you’ve invested time and
money into a solution that you’re not happy with.
It takes courage and confidence to take responsibility and admit to
yourself that you need to come up with a new solution. Many of us are
blinded by the fallacy of sunk cost. You’ve invested time and money into
a problem and that means it needs to make its money back. The truth
is that you won’t ever get that time or money back. However, you can
save yourself time and money in the future by taking another look at
the problem, learning from your mistakes, and coming up with a better
solution.
If you think this only happens to rookie developers, then you’d be
mistaken. It’s the experienced developer that has the audacity to start
3 Refactoring 179
afresh with a clean slate and that knows and sees the solution won’t cut
it, for whatever reason. But, again, there’s a fine line between knowing
when the solution isn’t good enough and striving for a perfect solution
that doesn’t exist. Be honest with yourself and, as always, ask advice
from team members or fellow developers.
Starting Anew
Starting with a clean slate is almost always a hard sell if the client makes
the decisions. Unfortunately, I’ve worked on projects that would have
cost less if the client had had the courage to start anew. That’s the fallacy
of sunk cost. Truth be told, it’s difficult to predict the future and it’s easy
to write this in hindsight.
While refactoring is an integral aspect of software development, you
sometimes need to have the audacity to start from scratch. Learn from
the mistakes that were made and create something that is ready for the
future. While it’s rare that you’re given this opportunity, you can erase
months or years of technical debt that slow the product’s evolution down
by starting from square one. That’s a very tempting offer for a developer.
Is it not?
4 Source Control
The day I discovered source control was one of those aha moments. I’m
a self-taught programmer and that was clearly visible in the early days of
my career. I’m sure you can guess what type of source control strategy
I used before I found out about Git74 . Let me give you a hint. It involved
copying folders. Ignorance is bliss, but not if you’re a developer.
Whenever I’m hooked by a new tool or technique, I try to learn everything
there is to know about it. Git was no different. In this chapter, I show
you what you absolutely need to know about source control, the basics.
I take it one step further by introducing you to the workflow that I’ve
been using for the past few years, a workflow that’s been working very
well for me.
The Basics
The most popular source control solution in the Cocoa and Swift commu-
nities is Git. That doesn’t mean it’s the best solution, but it’s the one I have
the most experience with. I love it. If you’re new to source control, then I
urge you to put down the book and learn more about Git. Seriously. Put
the book down. I’ll be here when you come back. The folks at Fournova75
have a bunch of great resources to learn the basics.
It’s nice to see that Xcode has improved support for Git over the years.
Xcode 9 takes it up a notch and it sure looks promising. I use a combina-
tion of the command line and a dedicated Git client, Tower76 .
74
https://git-scm.com/
75
https://www.git-tower.com/learn/
76
https://www.git-tower.com/mac/
4 Source Control 181
Elsewhere in the book, I write that once you know the rules and what
they stand for, it’s fine to break them. That rule does not apply to source
control. There are a few simple rules I stick to religiously. Let me give you
an overview.
Develop on Develop
Commits
Commits and commit messages are your window into the project’s
history. This means that it’s important to carefully craft your commits
and commit messages. That’s one of the reasons I use a Git client
because it allows me to pick and choose which code changes make it
into the next commit. You can do the same from the command line, but
it’s less convenient. How you interact with Git is a personal choice.
There are several methods for creating a commit message. It doesn’t
matter which one you choose, but make sure you’re consistent and, if
you work on a team, adopt the same methodology across the team.
Avoid large commits. It’s true that this can sometimes be a problem if
you’re modifying the project file of an Xcode project. Not only is this
important for clarity and communication, but it’s also important for
practical reasons. If you want to cherry pick a commit, then you want
to make sure the commit you’re cherry picking only includes what you
think it includes. The same is true for rolling back commits.
Stashing
I’m always surprised by the number of developers that are new to the git
stash command. The concept is surprisingly simple. Imagine that you’re
working on a new feature on a feature branch. Your project manager
taps you on the shoulder and asks you to hotfix a problem on master.
Your workspace is littered with changes. What do you do? Do you commit
what you’re working on just to make sure you don’t lose your work? No.
Don’t do that.
The git stash command stashes the changes in the working directory
and the staging area for later use, leaving you with a clean working
directory and staging area. The stashed changes are pushed onto a stack
and you can create as many stashes as you need.
To stash the changes in the working directory and the staging area, you
execute the git stash command. The changes in the working directory
4 Source Control 183
and the staging area are safely stored for later use. You switch to the
release branch, create a build, return to the branch you were working on,
and apply the stash you created earlier. It’s that simple. To apply a stash,
you pop it from the stack of stashes with the git stash pop command.
If you frequently use stashes, I recommend naming the stashes you
create. This makes it easy to find stashes and apply or remove a stash
by name.
Patching
and apply the patch you created earlier. If you’re both working on the
same branch and modifying the same files, then it’s still possible that
you still need to perform a manual merge.
Keep in mind that a reset is a potentially dangerous operation that
can lead to data loss. Always bear this in mind when using the reset
command.
Git Flow
A project with any degree of complexity needs a robust branching model.
The branching model77 I have come to appreciate is the one outlined by
Vincent Driessen78 . Vincent’s model may look daunting at first, but it’s
easy to adopt in most software projects.
The idea is simple. A project adopting Vincent’s branching model has a
master and a develop branch. We covered that earlier in this chapter. If you
decide to work on a feature, you create a feature branch that branches
off of develop. When a feature is ready to be released, the feature branch
is merged back into develop.
When the time comes to schedule a release, a release branch is created
that branches off of develop. The goal of the release branch is to prepare
the release and fix critical bugs. A release branch is never used to
implement features. After a successful release, the release branch is
merged into master, merged into develop, and merged into downstream
release branches.
Merging into develop and downstream release branches is important to
guarantee that any work done on the release branch, such as bug fixes,
is also included in feature and downstream release branches.
Earlier in this chapter, I discussed hotfix branches. If you need to push
a hotfix to production, you create a hotfix branch that branches off of
master. After releasing the hotfix, the same merge strategy is applied as
for release branches.
77
http://nvie.com/posts/a-successful-git-branching-model/
78
https://twitter.com/nvie
4 Source Control 185
This branching model works really well for me and the projects I work
on. I recommend prefixing branch names with feature/, release/, and
hotfix/ to avoid confusion. If you apply this naming convention, then
most Git clients automatically group every branch type in a folder.
Some Tips
I’d like to end this chapter with a few tips that I picked up over the years.
Does It Build
You should only make a commit if the project builds successfully, without
warning and errors. This isn’t always easy, especially if you’re refactoring
a section of a project.
Make sure you use an up to date .gitignore file. Elsewhere in this book,
I share the .gitignore file I use in Cocoa projects. Regardless of which
.gitignore file you use, make sure you understand what it includes.
Don’t include one you found on the web if you don’t understand what
it ignores.
Configuration
It’s important to know and understand which files to keep under source
control. A developer checking out the project should be able to build and
run the project with minimal effort. This means that you don’t need to
include the Pods directory if you’re using CocoaPods, but you need to
include the Podfile and Podfile.lock files.
4 Source Control 186
Sensitive Information
Minimize Dependencies
What Is a Dependency
Dependencies come in many forms and shapes. The most obvious de-
pendencies are open source solutions you manage with a dependency
manager like Carthage, CocoaPods, or the Swift Package Manager82 .
Managing dependencies with a robust dependency manager is trivial.
It’s almost too easy.
Inexperienced developers make the mistake of including too many
dependencies. After a while, the project feels like a car held together with
tape and glue, ready to crash and burn at the slightest bump in the road.
It’s true that dependencies can significantly speed up the development
of a project, but, again, shortcuts come at a price.
Remember that Parse offered developers a tempting solution, a mobile
backend with support for data storage, push notifications, and more.
Most of the projects that relied on Parse were forced to pay a hefty price
when the platform was shut down.
As I mentioned earlier, dependencies come in many forms and shapes.
Swift is a dependency of every project you work on. If you’re a Swift
developer, then you have no other option. Some dependencies are
unavoidable. Xcode is probably another dependency of your projects.
That too is out of your control unless you switch to JetBrain’s AppCode83 .
80
https://cocoapods.org
81
https://github.com/Carthage/Carthage
82
https://swift.org/package-manager/
83
https://www.jetbrains.com/objc/
5 Dependencies 189
Fewer Dependencies
The idea is simple. The fewer dependencies your project has the better.
I hope we can agree on that. Every time I add a dependency to a project,
I carefully analyze whether it deserves to be part of the project. What
are the alternatives? How long would it take me to implement a custom
solution? How healthy is the dependency? Is it a liability for the project?
Every audit I set up with a developer or a company starts with a session
that, among other things, analyzes the dependencies of the project. The
lead developer of the project must be able to justify why the project
depends on a particular library, platform, or technology. If the project
uses CocoaPods to manage dependencies, for example, we inspect the
contents of the project’s Podfile.
I understand that dependencies can save time and, in the short term,
money. But what happens if you need to replace a dependency that’s
used throughout the project? What if you need to switch out a vital
component of the project and replace it with an alternative?
Every dependency is a liability. Plain and simple. Even the Swift program-
ming language is a liability. Don’t believe me? Ask the tens of thousands
84
https://github.com/ReactiveX/RxSwift
85
https://github.com/Moya/Moya
86
https://github.com/Alamofire/Alamofire
5 Dependencies 190
Choose Wisely
I already wrote that a typical software project has many hidden depen-
dencies, such as the programming language and the developer tools we
use. Some of these dependencies are easily overlooked. How do you
collect crash reports or analyze user engagement? I bet you don’t use
Apple’s analytics. Do you rely on Fabric, Firebase, or Mixpanel? These
are mature platforms, but they’re dependencies too.
Challenge Yourself
I’d like to challenge you. The next time you create a Cocoa application, a
side project maybe, avoid relying on any third party dependencies. See
how far you can go without including third party libraries or frameworks.
Impossible? Think again. At its core, a developer is someone that solves
problems. This is a problem you can solve. Believe me.
6 Automation
“A good developer is a lazy developer.” It’s a phrase I use several times
in this book. I believe the term “lazy programmer” was first coined by
Philipp Lenssen. The idea is that a programmer wants to avoid being
repetitive whenever possible. But that’s not the only reason automation
is important.
Automation can also minimize human error. Continuous integration,
which we discussed earlier in this book, is an example of this. By
automating a sequence of steps, we reduce or eliminate the number
of manual steps a team needs to take to deploy a build to production.
Automation doesn’t need to be rocket science, though. The Cocoacasts
website is backed up automatically. This is a trivial example of automa-
tion, but the result is that I have peace of mind and, when things hit the
fan, I won’t lose any data.
Let’s start with the basics of automation, scripting.
Scripting
Build Phases
Xcode build phases are ideal for automating tasks you tend to skip or
forget. For personal projects, I use Realm’s SwiftLint94 to make sure the
code I write is consistent and sticks to a set of guidelines. SwiftLint is easy
to set up and integrate with Xcode in a build phase. You can even trigger
SwiftLine using fastlane95 .
Automated Testing
It’s no secret that I’m a fan of automated testing. It isn’t hard to set up
and it builds confidence. Every commit you push to a shared repository
triggers the test suite, immediately showing you if you’ve broken any-
thing. This feedback loop allows you to confidently build a robust, stable
product. Not having to think about running your tests is essential.
Documentation
If you or your team maintain a framework or library, then you need to
make sure its documentation is up to date. As I mentioned elsewhere in
91
https://github.com/johnsundell/marathon
92
https://github.com/nsomar/Swiftline
93
https://github.com/kylef/Commander
94
https://github.com/realm/SwiftLint
95
https://fastlane.tools
6 Automation 195
Continuous Integration
Earlier in this book, I wrote about continuous integration and its benefits.
It’s a more sophisticated form of automation that can help you and your
team stay on top of larger, complex projects with many moving parts.
Remember that one of the goals of automation is reducing the number
of manual steps you need to take to deploy your product to production.
From the moment a developer pushes the last commit to the shared
repository, no human should tinker with the build that’s deployed.
If you work at an agency or a development shop that manages dozens
of products, then having a robust continuous integration solution isn’t a
luxury. It’s essential. No two projects are the same and every project has
its own requirements, dependencies, and configuration. You don’t want
to remember those and you don’t want to manually tweak build settings
moments before you trigger a production build. Take your work and that
of your clients serious and invest in a continuous integration solution.
fastlane
A few years ago, Felix Krause97 started developing a suite of tools for
automating common tasks related to Cocoa development. This suite of
96
https://github.com/realm/jazzy
97
https://github.com/KrauseFx
6 Automation 196
Keep It Simple
Even though privacy isn’t a fancy topic and it isn’t top of mind for most
developers, I hope you’re at least keeping privacy in mind when you’re
building software. You sometimes have no other option, for example,
if you’re developing an application for a bank. But there is a range of
less obvious application types that privacy is important for, for example,
applications that have a link to the user’s health.
You’ve probably heard the phrase “If you’re not paying for the product,
then you are the product.” Some companies collect and sell information.
They collect user information, such as browsing behavior and location
data, and sell it to advertisers. While the services they offer are free,
there’s a catch.
It’s not always easy to discover which companies are legit and which ones
to avoid, but if you, the developer, include a third party’s service in your
application, then it’s your responsibility to make sure it doesn’t violate
the user’s privacy. You’re on the hook if something happens with the
user’s data.
You can remedy this by publishing a privacy policy for your application
in which you explain what happens, or doesn’t happen, with the user’s
information. This also means that you need to know how the third
parties you work with use your application to collect information. This
can be tedious. It’s ironic that it’s usually easier to include a third party
SDK than to find out how the third party uses your application for their
own gain.
As I mentioned earlier, I no longer include third party services, such as
analytics and advertising in the projects I work on. That’s a conscious
decision and I have the luxury to do this. Unfortunately, this isn’t possible
for everyone. In fact, it may be rare.
than nine years, the company sticks with its ambition to keep the App
Store safe and healthy.
Whenever I install an application from Apple’s App Store, I know that
I won’t be installing a piece of malware that sends the contents of my
address book to a remote server. App Review isn’t perfect or bulletproof,
but it’s demonstrated that it does a pretty good job at protecting you and
me from people and companies with dubious practices.
You need to give an application your explicit permission for it to access
your address book, photos, and location. This is a good thing because
it puts you, the user, in charge of managing your privacy. While this
solution isn’t perfect, it at least gives you the opportunity to be conscious
of your privacy if that’s what you want. Some people don’t care about
their privacy and that’s fine. The user is in charge.
Choose Wisely
Consider the companies you implicitly, or explicitly, work with. I don’t
want to imply that you shouldn’t trust Apple, Google, and Facebook,
7 Privacy 200
but you need to be mindful of the services your application and your
business uses.
8 What to Do When You Inherit
a Software Project
As an employee, freelancer, or consultant, you inevitably end up with a
foreign codebase on your plate at some point in your career. In a way,
inheriting a software project is much like receiving the keys to a house
or car you don’t know anything about. You hold your breath, afraid for
what’s about to come. But you’re also a little excited, curious to find out
what you’ll be working on for the next weeks, months, or longer.
A new project can be overwhelming. Depending on its size and state,
opening a project for the first time can be downright shocking. Don’t let
this intimidate you, though. Some things are hard, but that doesn’t mean
they’re impossible.
Take your time to explore the codebase and learn more about the
project as you go. The first few days can be disorienting and it may feel
as if you’re not making any progress. And that’s fine.
If the previous owner of the project is still around and able to do a formal
handover, then you’re in luck. This is a major advantage. Prepare a list of
questions and fire away during the handover. Don’t be shy. You’re new
to the project, which means there are no silly or dumb questions.
Is the previous owner not around, then try to get a hold of someone who
worked on or is familiar with the project. That’s the next best thing.
8 What to Do When You Inherit a Software Project 202
Source Control
Compatibility
Depending on the software project, you need to make sure your devel-
opment environment is compatible with the project’s technology stack.
A Cocoa application, for example, requires a machine running macOS
with a copy of Xcode installed.
It may even be necessary that you need a specific version of macOS or
Xcode to bring the project to life. As I mentioned earlier, if you can talk to
someone that used to work on the project, then you’re saving yourself a
lot of time and frustration.
The moment of truth arrives when you compile the project for the very
first time. Give it a try. Build and run the application on a device or in the
simulator. This step is critical because it reveals some of the project’s
8 What to Do When You Inherit a Software Project 203
Collect Data
With the project up and running on your development machine, it’s time
to get to know your new best friend. It’s important to understand how
the project works and, more importantly at this stage, find out what its
requirements are.
For a Cocoa application, for example, the deployment target is an
important piece of information. It tells you what APIs you can use and
which devices the application is compatible with. Are you dealing with
a universal application or does it only support iPhone and iPod Touch?
Has the project been updated for retina displays? Do you think that’s a
silly question? Think again.
Some projects have been collecting dust for years. This can sometimes
mean that you need to make significant changes before you can submit
a build to Apple’s App Store. As of June 2015102 , for example, Apple
requires new applications and updates to existing applications to include
64-bit support. If the project depends on a third party framework or
library that hasn’t been updated in years, this may be a problem.
100
https://cocoapods.org/
101
https://github.com/Carthage/Carthage
102
https://developer.apple.com/news/?id=04082015a
8 What to Do When You Inherit a Software Project 204
Dependencies
Speaking of dependencies, you’re probably starting to get a pretty good
picture of the project’s dependencies. It’s time to take a closer look.
Are the dependencies managed by a dependency manager or are they
included in the main project?
With a bit of luck, the previous owner used a dependency manager
to separate the dependencies from the main project. In that case, it’s
straightforward to verify the current version of each dependency and,
at a later stage, update them.
In some cases, dependencies are included in submodules or, if you are
less fortunate, they’re mixed in with the project. The latter makes up-
dating dependencies a pain. Migrating third party dependencies outside
the main project with the help of a dependency manager is a worthwhile
investment. It’ll save you many hours and headaches.
Document Everything
No matter what project you work on, it’s important to document as
much as possible. The README of the project is a good starting point.
8 What to Do When You Inherit a Software Project 205
And Beyond
Technical Debt
Technical debt can creep into a project without the product owner
knowing about it. The development team usually knows, though. If the
team is led by a senior developer and code reviews are baked into the
company’s culture, technical debt is easy to spot.
A fast approaching deadline can cause even the best to ignore technical
debt. The symptoms start to appear when new features take longer to
build than expected and regressions make their way into the product.
These are the early symptoms of technical debt.
In advanced stages, technical debt takes a project hostage. Nobody
wants to touch the project anymore. Features take ages to complete
and are often compromised by technical limitations caused by technical
debt. Days, weeks, or months of bug fixing are needed to stabilize the
project. I’m not exaggerating.
In the meantime, the product itself evolves at a snail’s pace. The speedy
start that was once so important for the project’s success has long been
forgotten and, looking back, wasn’t that important after all. It rarely is.
Focus
If the client wants to ship in three weeks, the correct answer is removing
features. For projects with a long shelf life, you want to avoid technical
debt at any cost. Technical debt is very much like a virus. It’s hard to
eradicate and, if it isn’t treated in its early stages, it spreads out rapidly
across the project’s codebase.
Focus is essential to avoid technical debt. Instead of rushing out a
feature, you take the time to craft something that stands out. This
doesn’t only relate to the final product; it also involves the development
aspect of the feature.
You don’t need to overengineer the solution, but you need to make sure
the feature can grow beyond its current scope. You plan and anticipate
how it can or could evolve.
9 Speed, Quality, and Technical Debt 208
Refactoring
The least radical approach is refactoring the project, focusing on one
problem at a time. If you’re in luck, one round of refactoring is sufficient.
However, most projects suffering from technical debt have many prob-
lems that need fixing.
As I mentioned earlier, technical debt spreads like a virus and that means
many areas of the codebase are infected. I strongly advise against a
single round of refactoring. Map the problems you plan to attack and
spread the refactoring over several releases. This ensures the release
cycle isn’t blocked as long as the refactoring is ongoing.
In the meantime, make sure you don’t introduce new problems. Hold off
on new features if possible. Don’t make the same mistake twice.
If you’re working on a large project with years of history, be prepared
to spend weeks or months refactoring. That’s the price you pay for
technical debt.
Clean Slate
The most radical approach is starting anew. This means you don’t need
to spend months refactoring. This isn’t an option for every project. If you
have the opportunity to start with a clean slate, though, you’re in luck.
While it means that you need to implement every feature from scratch,
it’s an opportunity many developers would grab with both hands. Learn
from your mistakes, or those of your colleagues, and create an amazing
product.
I’ve worked on several projects that would have cost less if the project
was rebooted. But that’s often a very hard sell. The client doesn’t see
9 Speed, Quality, and Technical Debt 209
the problems the developer sees. They only start to see the symptoms
of technical debt when deadlines are missed or features become very
expensive.
Taking Shortcuts
Just Start
Code reviews don’t necessarily need to have a goal. Pick a time and date
to sit together with one of your colleagues, or as a team, and have him
or her scrutinize your code. The simplest questions are often the most
powerful ones. A common misconception is that code reviews are only
useful to debug an issue or find problems in a project.
Code reviews are first and foremost a tool to improve yourself. I’ll talk
more about that later in this chapter.
When a senior developer sits down with a junior developer, the mistake
that’s often made is biting off too much at a time. If the junior developer
made dozens of commits since the last code review, adding hundreds
or thousands of lines of code, then the code review is going to feel
overwhelming. You need focus and direction.
Keep a code review small and focused, especially if you’re training
someone. The goal isn’t to cover as much ground or code as possible.
The goal is to go through a chunk of code, ask questions, and brainstorm
ideas and alternative solutions. Even senior developers can learn from
developers with much less experience.
1 Code Reviews 213
Be Prepared
Tools
There are many, many tools available for organizing and structuring
code reviews. I’m not going to mention any of these tools because I
feel that they’re secondary. Most of these tools have the option to send
someone a code review. While I understand why this feature exists, the
code reviews I’m talking about in this chapter are live code reviews, two
or more people having a discussion about a particular piece of code.
You can still use a tool to keep code reviews organized and structured,
and I recommend you do, but make sure you don’t overlook the essence
of code reviews. That’s the main takeaway of this chapter.
That Hurts
Finding out during a code review that you introduced a bug can be
painful and it can hurt your ego. To be honest, this is a facet of code
reviews that I like. Why is that? Nobody likes to make mistakes and, from
my experience, developers in particular hate to be pointed out that they
1 Code Reviews 214
made one. A fellow developer pointing out that you made a mistake can
be hard to swallow.
It’s therefore essential that code reviews are organized in such a way
that the finger isn’t pointed at someone. Everybody makes mistakes. No
exceptions. If you don’t believe me, then have a look at the crash reports
of the projects you worked on in the past month or year.
It’s a good sign if it stings a little when someone uncovers a bug you
made. It shows that you care. Don’t be arrogant and try to prove them
wrong if you know they’re right. You can only grow as a developer if
you’re willing to grow and learn from your peers. Learning from smart
developers is one of the few shortcuts to speed up your career. Take
advantage of this shortcut whenever you can.
Convincing Management
Frequency
How often should you schedule code reviews? That depends. If you
schedule code reviews only once a month, then you may overwhelm
1 Code Reviews 215
Give It a Try
Code reviews have many benefits. If you’re new to code reviews, then I
encourage you to give it a shot. I recommend running a trial for at least
a few weeks or months. Give your team the chance to become familiar
with the process and tweak it as you go. You won’t get it right from the
start.
2 Adopt a Style Guide
Even if you’re working on your own, in a team of one, adopting a style
guide can be very helpful and useful. It ensures that you stick to a set of
guidelines you define. The result is that your code is consistent and easy
to read.
Automation
I’ve worked in teams with a formal style guide that wasn’t enforced in any
way. Team members were simply expected to stick to the style guide. If
you decide that a style guide can benefit your team, then I recommend
2 Adopt a Style Guide 217
you also invest in automation to enforce the rules defined in the style
guide.
This is very easy to set up if you’re using Xcode. Adding a build phase to
the project that triggers a shell script or a command line tool should do
the trick. Be careful that the style guide you enforce locally is up to date.
If you open an old project, make sure it uses the most recent version of
the style guide.
Rough Transition
Working in a team can be a joy with many benefits, but it can also be a
challenge. Every team member has a responsibility towards the team,
and this determines in a significant way how effective the team is.
Leadership
A team needs a leader, even small ones. One person needs to make
decisions and have the last word when push comes to shove. A leader
often has a significant impact on the team and the team’s ethos.
Having a healthy mix of junior and more senior developers is a good
strategy. Attracting someone who has experience working in and build-
ing a team is a big plus.
3 Working In a Team 219
Communication
Elsewhere in the book, I write about focus and productivity. At times, it’s
necessary to put on your headphones and focus. That’s unavoidable if
you want to get work done.
What I’ve also noticed is that this culture of headphones can sometimes
result in a lack of communication. Talking to your teammates is as
important as getting work done, especially if you’re working towards the
same goal.
You can solve this seeming conflict by organizing team meetings that
focus on team building. Take the afternoon off for a team event that
doesn’t have anything to do with work. Or organize a weekly lunch to talk
about a technical topic. Start a discussion and leave room for everyone
to share their opinions.
Give It Time
It takes time to turn a group of people into a team. It isn’t necessarily a
natural process and don’t expect it to be. A solid team isn’t built overnight
nor does it happen by accident.
A good team strengthens when it gets tough. When something goes
wrong, there’s usually one person to blame, but you take the hit as a
team. It’s a team effort, and you need to avoid that someone is singled
out, taking the blame. You’re in this together. People should be allowed
to make mistakes.
Respect
Not everyone is cut out to work in a team and you can’t always choose
the other members of your team, which can cause friction. That’s why
hiring is such an important aspect of a growing company and something
many struggle with. I’m sure you can think of a few examples.
3 Working In a Team 220
to an effective and efficient team. They’re the glue that binds clients,
designers, developers, and testers together. An experienced project
manager owns the project and takes the final responsibility for every
aspect of the project.
And developers need to do the same. If something goes amiss, then the
person responsible for that aspect needs to step up and take care of the
problem.
When something goes haywire and people start pointing fingers at each
other, then there’s a problem that needs to be addressed. It should be
obvious who’s responsible and who needs to take action. That person
shouldn’t be blamed for what went wrong, though. It merely eliminates
the discussion who needs to step in and fix the problem.
I’m sure it’s obvious that you should share what you know with the team
and learn from your teammates. It’s one of the shortcuts in software
development that you should take advantage of. Stack Overflow is great,
but nothing replaces a healthy discussion with your teammates about a
technical topic or a problem you’re trying to solve.
And don’t forget to include designers and managers. I’ve had many in-
teresting discussions with team members that weren’t technical. There’s
more to software development than writing code.
4 Being a Leader
As a freelancer, I don’t have much experience leading teams, but I’ve
been part of several teams as a subcontractor. Leading a team and
acting as a leader can be challenging for developers because they’re not
always asking for this type of promotion. As a company grows, teams
are formed, and a team needs a leader.
The most memorable leaders I worked with are modest and humble.
They can bring the best out of you, taking advantage of the strengths of
each member of the team.
4 Being a Leader 223
Work as a Team
Most of the team or project leads I’ve worked with had too much on their
plate. That’s a very, very common problem for people leading a team or a
company. Their workload isn’t always the cause of the problem, though.
Two causes are very common.
The first cause is wanting to do everything yourself. Inexperienced
leaders, especially those with a healthy dose of pride, find it hard to ask
the members of their team for help. You won’t be able to do everything
yourself and you need to learn to delegate tasks to the members of your
team.
This can have a dramatic impact on your workload. At first, it can feel
as if you’re asking someone else to do your job, but that feeling quickly
disappears once you discover that you have more time for other tasks,
such as organizing your team and setting up one-to-one meetings with
the people of your team.
Delegating is something you need to learn and it also means you need
to know the people on your team very well. Each member has their
strengths and weaknesses. It’s up to you to leverage this diversity and
use the strengths of your team to your advantage.
The second cause is closely related to the first. Handing control over
to other people can be scary, very scary. You’re the leader of your
team and that means that you carry the final responsibility. As a result,
inexperienced leaders have the urge to make sure everything is exactly
as they want it to be, as if they did it themselves.
4 Being a Leader 224
This approach isn’t healthy. First, the result is that you increase your
workload for no good reason. Second, you may give other team mem-
bers a feeling of inadequacy, not being good enough. It can sometimes
be good to let things hit the fan. Everyone learns from such an experi-
ence.
If you still struggle with this, then you may want to embrace code reviews
or roundtables. These can be very effective strategies to build your team,
show them how things should be done, and make sure everyone is on
the same page.
Even if you sign up for a crash course in leadership, it takes time for most
people to become a leader and be seen as one. You won’t always know
what to do in certain situations. How do you handle a conflict within your
team? There’s no one or right answer.
4 Being a Leader 225
Lead
Listening to the people you work with and asking for their input is
essential to building a healthy team or company. But always remember
that you’re the leader and you have final say when decisions need to be
made. And that’s what a team member expects from its leader. When
push comes to shove, you need to show that you’re the leader and the
man or woman taking the decisions.
This won’t always be easy, but it’s necessary. It’s as simple as that. You
won’t always know whether that decision is the right one, but that’s
how it is. That’s what sets a leader apart from a team member or an
employee.
Part 6: Career
1 Open Source
The concept of open source has been around for decades, but platforms
like GitHub104 have accelerated the growth of open source initiatives.
Most of us can’t imagine a world without open source software.
Open source software can be a powerful instrument to promote yourself
as a developer. Many respected developers in the Cocoa and Swift
communities have gained name and fame through their open source
projects, think Eloy Dur��n105 , Mattt Thompson106 , and Ole Begemann107 .
Start Small
You may already have a library or project you want to share with the
community. Sharing something with the world can be scary, though.
Make sure you’ve cleaned up the project and don’t share any personal
or confidential information. When you share a repository with the world,
you give everyone access to its history.
For example, if you committed a private key or token at some point and
removed it later, then anyone with access to the repository can retrace
your steps and access that information. Remove the project history if
you want to play it safe. Once the information is public, there’s no way
back.
Documentation
Taking It Seriously
The commitment of some developers is admirable. They cover their
project with unit tests, set up continuous integration, and write pages
and pages of documentation. This is usually a community effort and
that’s what’s wonderful about open source software. Once your project
gains traction, developers automatically start giving back with small, or
large, contributions.
These contributions are very welcome, especially if you have limited
time to spend on your open source project. If you’re a freelancer or an
independent developer, then it can be a breath of fresh air to collaborate
with other developers on a project. That’s a bonus you get for free.
Giving Up Control
For some developers, the hardest part of open sourcing a project is
giving up some of the control they have over the project. You can decide
to manage everything yourself, but that isn’t feasible if your project
becomes popular. It also goes against the spirit of open source software.
To avoid that your project becomes messy and an odd collection of
coding styles, you should adopt and enforce a style guide. This isn’t
difficult to implement. When I submitted my first pull request to the Co-
coaPods project108 , I immediately received automated feedback about
the coding style I was using. I took a look at the project’s style guide,
made a few changes, and submitted an update. Having a style guide
that’s automatically enforced helps to keep your project consistent and
it keeps the maintainer(s) sane.
Taking Responsibility
One of the most challenging aspects of an open source project is
keeping it up to date. It takes time and effort to keep your projects
108
https://github.com/CocoaPods/CocoaPods
1 Open Source 230
up to date. Automation can make this much easier. Know that several
hosted continuous integration solutions offer a free tier for open source
projects. If you’re serious about your project, then that may be worth
looking at.
And remember that you don’t need to do everything yourself. For Cocoa-
casts, I create many, many projects for the tutorials I write and record.
It’s challenging to keep them up to date. If a reader notifies me that a
project hasn’t been updated for the latest version of Swift or Xcode, then
I suggest that they submit a pull request. That’s not unreasonable. Is it?
Open source is a community effort and everyone involved in a project
should take responsibility.
2 You Are the Constant in Your
Career
One of the reasons for writing this book is that it allows me to talk
about subjects that are related to programming, software, and the life
of a developer. Even though they’re related, they’re often overlooked
or ignored. This is especially true for young developers. Don’t feel bad,
though. It’s natural and maybe even a necessary part of your evolution
as a developer.
Most of your time is spent working for someone else, a boss, a manager,
or a client. The technology industry is known for long days and weeks
and sacrificing time with friends and family. But don’t let that distract you
from what’s important. What’s important isn’t the project you’re working
on or the client you’re building a mobile solution for. What’s important
is you. Why is that?
Many developers change jobs every few years. There are many reasons
for doing so. That’s not the point, though. No matter where you end up
next, there’s only one thing you take with you. You. You’re the constant
in your career. This may sound like a simple platitude, but it isn’t.
There have been times that I worked for the same client for several years.
It was good money, but I didn’t feel I was reaching the goals I set for
myself. I felt that I was stagnating as a developer, and that’s not a good
thing for a freelancer. The space is evolving at breakneck speed and you
can’t afford to stagnate.
2 You Are the Constant in Your Career 232
Setting Goals
Every now and then, I set goals for myself to keep me motivated,
accountable, and to make sure I can objectively validate that I’m evolving
as a developer. I’m sure you have a few things on your list that you
want to learn, some day. Who’s keeping you accountable? How long have
these items been on your list?
Looking Back
Steve Jobs famously said that real artists ship their creations. You’ll find
this quote more than once in this book. It’s easy to come up with a
compelling idea, spend a few days or weeks building the product, and
shelve it, elegantly wrapping it in a promise to finish it when you have
more time.
It’s easy, but, more importantly, it’s safe. It’s safer because few people
are willing to show the world what they created. They fear the opinions
of others. They fear people are going to judge their product and, even
worse, its creator.
109
http://justinvincent.com/page/951/the-madness-the-all-consuming-obsession-of-new-projects
3 Build That Application 235
When you’re applying for a job, showing that you have relevant expe-
rience is often essential. Not too long ago, several years of experience
were mandatory for a job as a software developer. Nowadays, employ-
ers are looking more and more at the portfolio of potential candidates.
This is especially true in software development.
People new to software development or graduates looking for their
first job may find it challenging to prove that they have experience
developing software. The truth is that they often don’t have the
necessary experience.
How do you solve this problem? How do you break this vicious circle?
Don’t wait for that first job or project to start gaining experience. Show
potential clients or your future employer that you have experience
building software. It’s never been easier to get started with software
development. What’s stopping you from creating?
Stay Ahead
While it’s fine to learn as you go, it’ll certainly help you if you know the
basics of the most common tasks of software development. Building
and launching a software product is quite an involved process. It doesn’t
stop the moment you have successfully built and deployed your first iOS
application on your iPhone or iPad.
Have you thought about beta testing, launch images, application icons,
and localization? If you can show your future employer that you have
thought of, built, and shipped a software project that’s polished and
carefully maintained, you’re almost certainly what they’re looking for. An
interview is almost guaranteed.
3 Build That Application 236
Working from home is a luxury if you have the discipline to set clear
boundaries for yourself. Unfortunately, it’s a very, very common trap
many people fall into, not only developers. When you make the switch
from working as an employee in a large office to working from home in
a small home office, if you’re lucky to have one, you may naively think
your productivity is about to skyrocket. The opposite is almost always
true, especially in the first few days or weeks.
Making a drastic change, such as moving into a home office, means that
you need to create new habits. Most of us believe it has everything to
do with discipline, but that’s only part of the equation. Take the time to
create a schedule that works for you and the people you work and live
with. That may mean that you start early or put in a few extra hours in
the evening when the kids are asleep.
You need to define boundaries, not only for yourself, also for the people
you live with. Working from home is still work.
4 Protect Your Productivity 238
Working In an Office
Working in an office has its pros and cons. The advantage is that every-
one knows and understands that you’re at work to, well, work. Make it
clear that you don’t want to be disturbed. Protect your productivity. This
may sound harsh, but it’s essential if you want to get meaningful work
done.
As a developer, your most important asset is your attention. If you’re
working on a complex task, it takes time to gain momentum and be
productive. Every time you’re interrupted, you need to start from square
one. Not only is this frustrating, it can be mentally taxing.
I once worked in an office that had a simple rule that said that a devel-
oper with its headphones on shouldn’t be interrupted. A room filled with
people wearing headphones isn’t uncommon in the technology industry
where open offices are the norm. You’d be surprised by the number of
developers that wear headphones without actually listening to music.
It’s a trick I’ve used many, many times. This is especially effective if your
headphones have noise cancellation.
While this rule looks great on paper, it doesn’t hold up in most situations.
Everyone is interrupted dozens of times a day. The number of productive
hours we put in is much lower than you’d think. That’s the reality we live
in.
Minimizing Interruptions
Slack and email have become indispensable in most companies, large
and small. They’re great tools for communication if they’re used wisely.
They’re not most of the time. They’re surprisingly often used as distrac-
tions instead of productivity tools.
Make sure you’re not distracted by a slew of, often unimportant, noti-
fications. If you’re constantly interrupted by notifications, then it’s clear
you have no intention of getting work done. Don’t look for productivity
hacks if you’re not serious about the most fundamental elements.
4 Protect Your Productivity 239
If you have a deadline to meet or you absolutely need focus, then looking
for a quiet spot in the office may be your last resort. This isn’t a solution
long term, but it’s sometimes your only option. If you’re in luck, you may
find an empty meeting room, but a couch or the kitchen is fine too. Don’t
forget to bring your headphones.
Deal With It
Distractions and interruptions are part of the world we live in. Working
in the technology industry means that you’re in the eye of the storm.
There’s no perfect solution unless you work from a home office where
you dictate the rules.
5 Building Your Portfolio
A portfolio is one of the most important assets of any developer with
ambition. Mobile applications, for example, are so commonplace that
potential employers or clients will want to see what projects you’ve
worked on in the past. Aspiring developers often ask what they should
show if they haven’t created any applications yet. The answer is simple.
Start creating.
If you’re learning the ropes of software development and you don’t have
any clients yet, then what are you doing all day? You don’t need to learn
everything there is to know about software development to start your
first project.
Scratch an Itch
While not every idea will be a runaway success, the itches you have
are perfect for your first projects. If you’re just getting started, then it’s
important to choose a relatively easy problem to solve.
The first application I shipped was an iPad application that allowed users
to import and tag images from an Aperture or iPhoto library. While I did
eventually publish the application, it was a bit too complex for a first
project.
Start small and build larger, more ambitious projects as you grow as
a developer. By biting off more than you can chew, you may lose
motivation or become discouraged.
Setting Goals
The primary goal of your first project should be simple, creating and
publishing an application that provides value to people. You can set
5 Building Your Portfolio 241
The second goal should be to complete the project you’re working on.
Once you commit to a project or idea, it’s important that you stick with
it. Steve Jobs famously said “Real artists ship.” As a developer, you’re
creating. That also means that you need to ship your creations.
The third goal is the proverbial cherry on the cake. That goal may be
hitting the top charts in your application’s category or reaching a certain
number of downloads. That’s up to you.
Why am I giving you this advice? And what gives me the authority to give
you advice in the first place? Ask any developer how many projects they
started but never finished. Starting projects is fine. But sometimes you
need to ship. Do you want to be taken seriously as a developer, then you
need to be able to show that you can start and finish something.
No matter what path you choose or what language you learn, it’s impor-
tant to start creating. Set a goal, pick a problem you want to solve, and
build a solution. That’s what software development is about.
6 How Badly Do You Want It
It isn’t easy for inexperienced developers to find an attractive job without
years of experience or an impressive portfolio. That shouldn’t be an
excuse, though. It’s never been easier for developers to build a portfolio,
gaining experience along the way. In this chapter, I show a few examples
of how you can build a portfolio and gain experience to help you find
clients or impress your future employer.
Contribute
Build
It’s never been easier to create software. Getting started with software
development isn’t that hard. What’s stopping you from creating your first
mobile application? If you’re looking for a job, then your future employer
will ask you about your portfolio.
Finding clients is hard without a portfolio. Would you hire an architect
who has never built a house before? The fact that you’re looking for your
first job as a software developer or freelancer isn’t an excuse for not
having a portfolio with one or two applications. Build that application.
Maintain
Being a software developer also means that you’re responsible for
maintaining what you create. It isn’t necessary to ship a new feature
every month. What’s more important is making sure existing users are
happy and stay happy.
Take a look at the crash reports of your application. Are there any issues
you can fix? What are people complaining about? Could you improve the
onboarding experience?
Being able to show that you have the skills to build and maintain a
software project goes a long way. Not only will your future employer look
for these skills, you also need them to excel as a software developer.
Test a new feature before releasing it to the public. Involve your existing
users by distributing a beta build of the application through Fabric113 ,
Hockey114 , or Apple’s TestFlight115 .
Adding support for multiple languages is another great improvement
that underlines your commitment to the project. This may involve hiring
a translator.
Gain Experience
Be Yourself
Whether you succeed depends on the question “How badly do you want
it?” Are you willing to work nights and weekends? To make a dent, you
will need to go beyond showing up116 .
It’s important to be honest with yourself and define what you expect
from your career as a software developer. Gary Vaynerchuck is spot on
when he says “If you live for weekends or vacations, your shit is broken.”
Is that you or are you aiming higher?
Are you motivated to get off your butt and make awesome stuff? What
are your goals and dreams? You don’t know? Then that’s the first thing
you need to sort out.
116
http://sethgodin.typepad.com/seths_blog/2013/01/beyond-showing-up.html
7 Freelancing and
Subcontracting
Making a living as an independent freelance developer is great, but it
can be a tough job at times. What I enjoy most about freelancing are the
skills you learn to master, or better, are forced to master. A team of one
has its upsides and its downsides.
What Is Subcontracting
Change of Environments
owner. Some people love that mix of responsibilities. If that’s you, then
subcontracting may take some getting used to.
But if you started freelancing because you enjoy programming more
than anything else, then you may not like those responsibilities all that
much. In that case, subcontracting could be a great fit for you.
In larger companies, developers can focus on what they do best, pro-
gramming. A project manager takes care of client relationships, the sales
team makes sure new projects are lined up for you, and the operations
team handles the infrastructure.
Subcontracting or Employment
The line between subcontracting and employment may seem thin at
times. This is especially true if you’ve been working for the same com-
pany for months or years. There’s nothing wrong with that, but it’s
important that you feel comfortable in that situation.
If subcontracting begins to feel like employment without the benefits
of being an employee, then it may be time to find another project at a
different company or choose a different path altogether.
If this really bothers you, then being an independent freelancer may be
a better fit. Nothing stops you from mixing subcontracting with working
as an independent freelancer. Many freelancers do. The line between
subcontracting and freelancing is sometimes pretty thin.
Both paths will teach you more than you can imagine. But make sure
you don’t become complacent. That’s my one advice. If you choose a
particular path because it makes your bank account happy, then it’s time
to reconsider your choices and priorities.
7 Freelancing and Subcontracting 251
Being Picky
Elsewhere in this book, I explain which steps you need to take when you
inherit a software project. If you’re working as an employee at an agency
and your company acquires a client from a competing agency, this often
means that you also acquire one or more existing projects. This is usually
part of the deal. As an employee, you have very little say in the matter.
Inheriting a software project is rarely a gift.
Things are a bit different as a freelancer. You have the luxury and
freedom to choose who you work with. For example, I no longer take
on existing projects because it usually means several days, weeks, or
months fixing bugs, making minor improvements, and spending a lot of
time fixing issues. I understand that not everyone has this freedom, but
it’s important to know that you can be picky if you choose to be.
Being picky doesn’t only apply to projects. You can also be picky when it
comes to the clients you work with. Working with individuals with a small
budget is rarely worth your time. Not because these people aren’t fun to
work with, but because they have no experience in the space and have
a limited budget to spend. Their focus is almost always on limiting costs
and understandably so. The quality of the product is secondary. This
means that the developer needs to work fast, cut corners, and almost
always defend their decisions.
Taking a Peek
Is It Worth It
Instead of taking on the project, have a conversation with the client to get
an idea of the amount of work they can bring in over the next months. Be
careful, though. I have spoken with many potential clients that promised
more work in the future and never delivered. That’s why I never start a
relationship with a client based on a project that only involves bug fixing
and minor improvements. I understand that such an assignment is ideal
for the client to test the waters. I see that a bit differently.
If a client approaches me for a collaboration, I expect them to trust me.
They contact me for my expertise and I have no intention of convincing
them that I’m a good fit for the job. If they feel I’m not, then they
shouldn’t have contacted me in the first place. Does this seem arrogant
or complacent to you? Think again. I consider it a form of trust and
respect.
Firing Clients
Most freelancers have the feeling that a client chooses them to work on
a project. This is usually true if you don’t have many projects lined up or
if you’re just starting out. Earlier I wrote about being picky and that also
applies to clients.
As a freelancer, it’s important to remember that you’re on your own. No
matter how good your relationship is with your client, they will let you
go if they feel that’s the best decision for their company. This means that
you should always put yourself first, not your client. This applies to your
health, your workload, and your mental sanity.
I’ve always been confused by the use of “freelancer” and “consultant”.
While there is a difference, a good freelancer is also a consultant. An
experienced freelancer is worth its weight in gold and a client should be
lucky to have you. With that attitude, your relationship with the client
changes dramatically. You no longer feel that you should only do what
you’re told. You should also advise the client.
7 Freelancing and Subcontracting 253
If you feel that your input and your advice are ignored by the client, then
you may be starting to wonder why you chose to become a freelancer.
When there’s an issue with my car, I trust my mechanic to decide what
needs to be done. A professional listens to the client and then decides
what should be done. If the client doesn’t respect your advice and insists
that you do what they think is best, then you may want to fire the client.
Wait. What? Fire the client?
It’s Hard
I’ve written about this many, many times because it’s something that
fascinates me. Developers are creative people, and we have an urge to
create. Unfortunately, most of us stop when we lose interest. Motivation
isn’t what’s going to get you from idea to App Store. It’s grit, tenacity, and
persistence.
Solving a problem is what we like to do. Writing release notes, im-
plementing in-app purchases, or localizing an application isn’t what
we enjoy most. But it’s an essential aspect of software development.
Unfortunately, it’s what stops most of us from shipping.
Make It Tiny
It’s fine to dream and to be audacious. But Rome wasn’t built in a day.
What stops many of us from shipping our creations is aiming too high. I
don’t mean to say that you shouldn’t aim high. What I am saying is that
you should aim for consistency.
My latest application is focused and to the point. I have big goals,
and even dreams, for this application, but the first release focuses on
the essentials. I interviewed people that are interested in the product
and asked them which features were essential for them to use the
application. I analyzed the results, went to work, and plan to ship the
first version of the application later this month.
It’s fine that your application is limited in scope. That’s much better than
no application at all. Right? I’m convinced that there are thousands of
applications collecting dust on people’s computers because they aimed
too high for the first release. Keep it small and focused.
Ship Frequently
Once you have something in the App Store, it’s surprisingly easy to
iterate on what you already have. Define the scope for the next release,
keep it focused and small, and ship. Rinse and repeat. Listen to feedback
and improve the application as you go.
It’s an approach that has worked very, very well for me. It also shows my
customers that I’m continuing to invest in the product. It builds trust and
confidence. The App Store is littered with abandoned applications that
no longer receive updates. One of my favorite utilities stopped working
after I updated my phone to iOS 11.
Internal Deadlines
There are numerous tasks you need to handle if you’re building and
shipping products. It can be a chore to prepare a release. To make
this easier, I automate most of the trivial aspects of a release, such
as translation management and creating and uploading screenshots.
Manually creating and uploading screenshots is virtually impossible if
you want to support every device your application can run on. You’re a
developer and you should be automating repetitive tasks.
It pays off to set aside a few hours from time to time and automate your
workflows. I write more about this aspect of software development in
the chapter on automation.
2 Talk to Your Customers
As developers, we have the itch or the need to analyze problems and
craft solutions for them. That’s what drives most developers. If you boil
it down to its essentials, then a developer solves problems, large and
small.
Some of us have bigger ambitions, though. What has always appealed to
me most is the possibility of creating a product and selling it to hundreds
or thousands of people. Apple gets a lot of flak for taking a significant
cut from your earnings, but, credit where credit is due, Apple has made
creating and distributing software easier than ever. It’s no coincidence
that the App Store catalog packs millions of applications. Whether that’s
a good thing is a different discussion.
Solve a Problem
blessing. But the first mistake developers make is trying to come up with
an idea. And many people I’ve talked to get frustrated in this phase.
The solution is surprisingly simple. Turn it around. Instead of looking for
an idea, look for problems and try to come up with a solution. That’s the
seed for a successful business. Why is that?
As developers, we’re focused on the technical aspects of the product.
We’re so immersed in the process of solving the problem that we
forget to ask the most important question. Does anyone want what
we’re building? And this leads to a waterfall of other equally important
questions. Who is the person we’re helping? What is the pain they have?
And how are we trying to make that pain go away?
Ground Zero
Your first task is to validate your idea. It determines whether you will
spend the next days, weeks, or months creating a business or a fantasy.
Every developer I’ve talked to about creating a product business has
made this mistake. Every. Single. One. I’ve made this mistake several
times, even after I knew I had to validate the idea first. It’s just incredibly
tempting to fire up a code editor and start coding.
This roadmap isn’t rocket science. Unfortunately, the path most devel-
opers that turn entrepreneur take is the following.
Start Small
Having big dreams is great. It’s admirable. We need people with vision
and ambition. But everything starts small. Thinking big isn’t a problem
as long as it doesn’t distract you from the work that needs to be done
today. Big goals always start small.
Start small by focusing on that one feature that sets your application
apart from every other application. How can you make it stand out? What
can you do to bring value to the user of your application with that one
feature? Not two. Not three. Only that one feature.
By intensely focusing on one piece of functionality, you force yourself to
make that one feature great, to make it magical. It’s fine to add bells and
whistles, but they shouldn’t distract the user from center stage.
Apple’s original iPod put the company back on the map. It was a revo-
lutionary product. It’s true that it looked amazing and that it was easy
to use. But, at its core, it did one thing very, very well. Playing music.
The product was focused. Apple removed every bit of clutter that could
potentially distract the user. Focus is what made the iPod stand out from
the rest of the market.
Remove Clutter
Many projects have a list of features that goes on and on. And that’s fine.
But is the feature list of your project stopping you from shipping? Are you
3 What Is Stopping You From Shipping 264
delaying the launch of your project because of one or two features that
your application can probably do without?
If your project needs a dozen or more features to add value, it may be
time to go back to the drawing board. If you need the bells and whistles
to cover up that center stage isn’t that great, you have missed the point.
Too many features is all too often the cause of missed deadlines and a
product that isn’t being shipped. I’m currently wrapping up a brand new
application. Some of the people testing the application are asking for
an Apple Watch application. I plan to support Apple Watch, but the first
version won’t include this feature. I know it will take me several weeks
or months to add this feature and that’s not what I have in mind. I want
to have this application in the App Store before the end of this month.
By postponing support for Apple Watch I make sure I can ship the
application sooner, but it also allows me to focus. Focus is a word you
find very often in this book. It has become an essential ingredient to
success in today’s day and age. I know it has for me.
What is stopping you from shipping?
4 Motivation Will Get You Only
Halfway
I bet that you started more projects than you can remember. How many
of those projects have you finished? How many applications did end up
in the hands of customers?
You’ve probably heard the phrase “Follow your passion.” or “Do what
you enjoy doing.” I agree that you should do what you enjoy doing, but
you also need to know that passion often isn’t enough to go from idea
to product, a product people can use and find value in.
Running a Marathon
Perseverance, tenacity, and grit are qualities that are often undervalued
or overlooked. Your boss or clients don’t pay you because you’re pas-
sionate or motivated. They pay you because you convinced them that
you can get the job done.
4 Motivation Will Get You Only Halfway 266
I’ve written about building and shipping products quite a few times in this
book because it’s something I frequently struggle with. Adding features
is nice, but updating translations, making screenshots, tracking bugs,
and responding to customer feedback is much less glamourous.
Building and maintaining a product is more than worth it, though.
Samsara, for example, has been around for several years and people
still email to tell me how much they enjoy using it for their yoga and
meditation practice. These emails get me excited to continue improving
Samsara with every release. It gets you through the tough times when
motivation is low.
Challenge Yourself
Most developers thrive when they’re faced with a problem they need
to solve. Continue to challenge yourself. Pick up a new language or
explore a new library to keep you sharp. Solving problems is exactly what
software development is about. Is it not?
5 How to Make a Living as a
Mobile Developer
Developers often refer to the early days of Apple’s App Store as the
gold rush of the App Store. Paid applications were the norm and prices
were much higher than they are now. What options do you have as a
developer or entrepreneur in today’s App Store? Is it possible to make a
living as an independent developer? In this chapter, I list the options you
have to make money from your applications in Apple’s App Store.
Paid Up Front
The most common approach to make money on Apple’s App Store used
to be asking users for money. Really. It sounds too crazy to be true.
Asking for money in exchange for a product is crazy. Joking aside, from
a business perspective, this makes perfect sense, and it comes with
virtually no overhead from the developer’s perspective.
To make money in Apple’s App Store, paid applications were the norm
for the first few years. This period ended with what’s now known as the
race to the bottom, developers competing with each other by cutting
the prices of their applications. The race to the bottom forced developers
and businesses to find other ways to make money.
While I’ve played with Samsara’s pricing, it has always been paid, and it
has done pretty well compared to the majority of applications out there.
While paid applications still have a future, it’s a less popular option these
days.
5 How to Make a Living as a Mobile Developer 269
Freemium
The freemium model predates the mobile era. Desktop and web applica-
tions used the freemium model long before the iPhone was introduced.
The idea is simple. You offer a product for free, getting it in the hands of
as many people as possible. To generate revenue, you do your best to
convince a subset of your users to pay for a premium experience.
Offering the product for free has two important benefits. Your product
spreads faster and more easily, and you have a foothold in the cus-
tomer’s life.
How you define a premium experience depends on the product. Ev-
ernote118 is a fine example of a company that has successfully applied
the freemium model. The company has tens of millions of customers. A
fraction of those customers pays for Evernote’s premium services. The
company would have had a harder time gaining market share if it had
offered its suite of products paid up front or with a monthly subscription.
Freemium isn’t without risk, though. For years, Rob Walling119 has been
warning developers and entrepreneurs that freemium is difficult to pull
off, especially for small, bootstrapped companies.
If your product has a backend, for example, then keep in mind that cus-
tomers that don’t pay for your product also make use of that backend.
Hosting costs can skyrocket if your product gains traction. In that case,
the conversion rate of free to paid customers will determine whether
your business is viable in the long run.
Advertising
model only works if your application has lots and lots of users and if
your users frequently use your application.
Games are a good fit for ads. Flappy Bird120 showed that developers can
potentially make millions of dollars through advertising as long as the
application has enough users that frequently play the game. Flappy Bird
was incredibly addictive, and that was the key to its short success.
David Smith121 is a successful, independent developer and he published
a very interesting article122 about how his business has evolved over the
years. In the early days of the App Store, the majority of David’s revenue
came from paid applications. Nowadays, advertising brings in most of
the revenue.
In-App Purchases
Subscriptions
Donations
Every application is different. Not every business model is a good fit for
an application. If you’re creating a camera application, then offering a
subscription is probably not going to work. Using in-app purchases to
unlock premium filters is a more viable business strategy.
It’s worth spending time considering your options and experimenting
with different business models. It’s fine and possible to make your
application paid up front and switch to freemium down the road.
Experimenting is fine, but make sure you don’t burn the goodwill of
existing customers. If you switch from paid to freemium and force your
loyal customers to unlock premium features they already paid for, then
prepare yourself for a flood of angry complaints.
Always keep your customers in mind. Don’t switch business models with
every major release. Does that mean you can’t make changes to the
business model of your product? Absolutely not. Let me give you an
example.
Let’s assume you release the first version of your application as a paid
application. After a few months, you realize it isn’t doing as well as it
could. You want to make the application free with an in-app purchase to
unlock premium content.
128
https://marco.org/2016/09/09/overcast-ads
5 How to Make a Living as a Mobile Developer 274
You could simply implement the in-app purchase, but this would anger
customers that purchased your application when it was paid up front.
The solution is simple, but it requires some work. The App Store receipt
includes the original purchase date. Your application can inspect the re-
ceipt and only offer the in-app purchase to customers that downloaded
the application after you made the switch from paid to free with an in-
app purchase.
Evolution
The mobile space continues to evolve and that also means that you and
your business need to evolve. This doesn’t need to be scary, but you need
to be vigilant. Keep an eye on the industry. Which trends are emerging?
What’s working for other developers? Talk to your customers? What are
their expectations? You may be surprised by their responses.
Part 8: You
1 Being and Staying Productive
Productivity is a topic that many people have written about and I’m
certainly not a guru when it comes to productivity. Through trial and
error, I’ve learned what works and what doesn’t.
Productivity is a very personal subject. What works for me may not work
for you. For that reason, I won’t be bombarding you with tips and tricks
in this chapter. Instead, I cover a few key elements that directly and
indirectly impact your productivity.
Maintaining Focus
One of the biggest challenges we’re faced with as developers is main-
taining focus throughout the day. The people we work with often expect
us to be available at all times. If you cannot cope with that feeling, it can
add a substantial amount stress to your life.
That’s why it’s vital to set boundaries. This is even more true for free-
lancers and consultants. If you run a business, people seem to expect
you’re working every waking moment. You are the business and you
should always be available.
Don’t make that mistake. Set boundaries for yourself and for the people
you work with. Believe me. People will respect you for it. And those that
don’t may not be the people you should be working with.
Distraction Is Addictive
As if open offices aren’t enough, instant messaging, like Slack, are used in
almost every technology company. They’re incredibly useful and, at the
same time, a major distraction for most developers. The same is true for
instant messaging of all forms and shapes.
Being distracted has become an addiction for some of us. We get a kick
every time we see an email come in, a message on Slack, or a new tweet
on Twitter.
For many of us, it’s a problem, a real one. We’re being distracted and
we’re craving for distraction. I don’t have the perfect cure to battle
distraction, but I have a piece of paper taped to the wall opposite my
desk with three lines of text.
Have Focus
This is a very effective strategy if you stick to it. The first line is simple.
Make sure that you know what you’re doing. Your focus should be
1 Being and Staying Productive 278
I believe I read this in a book by David Allen years ago. It’s a powerful
technique to get unstuck and move on. It works very, very well if you’re
battling a complex programming problem, because, let’s be honest,
even complex problems and solutions can be broken down into simple,
manageable pieces.
If you’re having a rough day, I recommend taking tiny steps. Launch
Xcode. Open the project you’re working on.
Remove Noise
Focus is only possible if you remove anything that can distract you.
Set a timer for 30 to 60 minutes and remove every possible source of
distraction. I’m writing this on a laptop without an internet connection
in a dimmed room on an improvised standing desk. I have notifications
disabled, closed browser windows, and I can only be disturbed by
emergencies.
Is this overkill? I don’t think so. How do you think programmers got
work done twenty or thirty years ago? They weren’t distracted by Slack,
mobile phones, and a constant influx of news, tweets, and messages.
We haven’t evolved since those days, which means we are not immune
to the distractions of today’s world.
I have one pro tip for you. If you’re working on an iOS application, make
sure you use a test device, not your personal device. It makes it easier to
block out messages, phone calls, and other distractions that your phone
receives.
1 Being and Staying Productive 279
Set Boundaries
An Example
To resolve the issue, Florian didn’t go looking for the silver bullet in the
Core Data programming guide because there is no silver bullet. There
are best practices and guidelines, but not every problem can be solved
with a clear-cut recipe.
important to stop looking for the silver bullet that you may think you can
find somewhere.
Instead, profile your application, investigate the results, and try to im-
prove performance problems or fix that hard to find memory leak. That’s
how you grow as a developer. Being afraid of exploring uncharted waters
is understandable, but that doesn’t mean you shouldn’t give it a try.
3 You Are Not an Imposter
Have you ever heard of imposter syndrome134 ? Like Pauline Rose Clance135 ,
I prefer imposter experience as it better describes the problem.
A surprising number of people suffer from imposter experience. And
developers are no exception. What is imposter experience? And why am
I writing about it in this book?
What Is It
Honesty
It Automatically Disappears
Talk About It
I’ve been wanting to write this post for quite a while. What inspired
me to take action was a recent episode of the Tropical MBA138 podcast,
TMBA384: Are You an Imposter?139 . One of the key takeaways from the
episode is simple, surround yourself with like-minded people and talk
about it.
138
http://www.tropicalmba.com
139
http://www.tropicalmba.com/Imposter/#comments
3 You Are Not an Imposter 286
Dan interviews several people that openly talk about imposter expe-
rience. Luis Miguel Gil opens up about how he experienced imposter
experience. He also zooms in on what causes imposter experience and
how to defuse it. This is what Luis has to say about feeling like an
imposter.
When I compare myself with Luis from three years ago I see
huge growth, huge success. Amazing. I’m very happy and
very proud of what I’ve accomplished. But when I compare
myself with people like you guys (Dan and Ian, the hosts of the
podcast) or other entrepreneurs that have had many amazing
successes, I feel I’m far away from reaching that. I’m so far
away. — Luis Miguel Gil
It’s Common
Imposter experience isn’t uncommon. Many people suffer from im-
poster experience, including people that are considered top performers
in their field. Tom Hanks, one of my favorite actors, made a surprising
comment several years ago.
This may seem odd for someone who’s won two academy awards. It
shows that it isn’t uncommon. It makes him human and approachable.
Information Overload
But, with the introduction of the iPhone in 2007 and the release of
the official SDK in 2008, that number increased substantially. There are
many books available from traditional publishers, such as Apress and
O’Reilly, but many developers, including yours truly, have chosen the
path of self-publishing, bypassing traditional publishers.
1 Choose Your Teacher Wisely 292
It has never been easier to publish a book or course. Books and courses
are available at any price point, including free. Unfortunately, this has
made it more challenging for developers to decide which path to choose
to learn the topic they’re interested in. Each day new tutorials, videos,
and courses are published. It’s challenging. That’s for sure.
The blessing of having so much free information at your fingertips is
more often than not a curse for developers that want to learn Cocoa and
Swift development. Not only is the amount of information overwhelm-
ing, there doesn’t seem to be a clear path to follow. It’s difficult to see
the forest for the trees. Don’t stop here, though. There’s hope.
Who to Trust
Every developer that writes about Cocoa and Swift development does
this with the best of intentions. They want to help people learn some-
thing new or solve a problem they’re having. It’s fantastic to see how
many of us take the time to write a tutorial or produce a video to help
others. It’s one of the key ingredients of the thriving Cocoa and Swift
communities.
Despite the author’s good intentions, though, what they’re teaching may
be incorrect or ignore good practices. If you’re new to a subject, then you
may not be able to spot these mistakes. The title of this chapter is very
telling. It’s become more important than ever to choose your teacher
wisely. While I don’t believe that people are intentionally putting out bad
content or incorrect information, it’s up to you, the student, to filter the
good from the bad.
A few weeks ago, I was looking for a solution to customize the color
of the clear button of a UITextField instance. It turns out that the tint
color of a UITextField doesn’t affect the clear button. Bummer. I was
having an issue where the clear button was nearly invisible against a
dark background.
During my search for an answer, I stumbled on several Stack Overflow
entries that recommended digging into the view hierarchy of the text
1 Choose Your Teacher Wisely 293
field, looking for the clear button, and modifying its tint color. As I
mention elsewhere in this book, this is a bad practice. If the API doesn’t
allow for this type of customization, you file a bug with Apple and
implement a custom solution. That’s the only correct solution. Your
clever workaround will inevitably break when Apple makes changes to
the internals of the UITextField class. Respect the SDK. Always.
The answers that suggested digging into the view hierarchy of the text
field were upvoted because, at that time, it solved the problem. Unfor-
tunately, this creates a bigger problem. Every inexperienced developer
that reads one of these answers is made to believe that this is a viable
solution, that this is fine. Instead of spotting the risk of the solution, they
wrongly believe that they’ve picked up a good practice they can adopt in
other, similar situations.
If I need to pick up a new framework or API, I rely on the people I
have come to trust over time. These are very often people that have
built up authority in the community over several years or people like
Aaron Hillegass146 , Marcus Zarra147 , and Jeff LaMarche148 that have been
around since the very early days of the platform.
important in today’s busy world that having the skill to focus obsessively
is a skill every developer should learn to master.
I don’t believe in the concept of a genius. It’s true that some people are
more gifted than others, but, in the end, developers that excel in what
they do are those who can focus and commit to something. You don’t
master Swift by reading a few chapters in Apple’s language guide. That’s
a good start, but it’s a process that continues and never stops. That’s the
beauty of it. No? Didn’t you become a developer because the sky’s the
limit?
That’s also why I often ask developers what goals they have for the
coming months or years. What I’m actually asking them is what their
focus is. What are they trying to accomplish? Ambitious people have a
clear focus, very often a singular one. Let me ask you then, “What is your
focus?”
The mobile space is still very young, relatively speaking, and it evolves
at an incredible pace. With Apple and Google heavily investing in their
platforms, the speed with which mobile platforms evolve requires de-
velopers to focus and learn non-stop.
In 2015, Apple introduced no less than two new platforms, tvOS and
watchOS. While developers familiar with iOS won’t have a hard time
getting up to speed with Apple’s brand new SDKs, there are many, many
APIs and paradigms to become familiar with. It’s understandable if you
feel a little overwhelmed as a mobile developer. That’s fine and it’s fine
to admit that.
If you decide to become a developer, regardless of the platform you
write software for, you need to accept and become comfortable with
the fact that learning on a daily basis is part of the job.
For the past few years, Apple has released a new version of its operating
systems every year, introducing new technologies we need to become
1 Choose Your Teacher Wisely 295
familiar with. The Swift project continues to evolve at a fast pace. At the
time of writing, Swift 4 is just around the corner and with it come new
features, bug fixes, and numerous improvements.
Are you ready to dive in head first? If Apple announces a slew of new
APIs next year, will that scare you or will it excite you? Do you have the
motivation to not only continue learning but also push the envelope.
Using an API is one thing, pushing it to its boundaries and beyond is
where it’s at.
If you like programming, but prefer to stick with what you know, then
mobile development may not be the best choice. If learning is in your
blood and the mere thought of WWDC or Google I/O gives you goose-
bumps, then being a mobile developer is the best job in the world.
2 Taking a Shortcut
What I like about programming and software development is that every-
one is treated the same. This means that there are no shortcuts you can
take. This is something I bring up several times in this book because I
strongly believe that you need to put in the work if you want to evolve
into a proficient Swift developer.
If your goal is to become one of the world’s top violinists, then you
simply need to put in the hours. The same applies to programming and
software development. Why would it be any different?
Even though there are no shortcuts, there are several paths you can
take to speed up your career. The shortcuts I mention in this chapter
are legitimate recipes to accelerate your growth as a developer.
Internship
The life of a freelancer may seem like the perfect life to many developers.
It’s true that it comes with several perks. You can start work whenever
you like and you can choose your workplace. But it’s a tough life at times,
especially if you’re just starting out.
For that exact reason, however, freelancing can be a shortcut in your
career. You’re forced to learn a lot of stuff and figure things out on your
own. You need to take care of a million things to keep your business
afloat. You need to develop skills you didn’t know you ever needed, such
as writing proposals, talking to clients, and working with subcontractors.
This isn’t for everyone, but if this sounds like a challenge to you, then
freelancing can significantly speed up your career.
Subcontracting is similar to freelancing. The difference is that you usually
work at your client’s company. It can sometimes feel as if you’re an
employee if you’re subcontracting. The reason I consider subcontracting
a shortcut is for exactly that reason.
As a subcontractor, you usually become a member of the team at the
company you work for. You learn about the company’s culture, the tools
they use, their workflow, and their automation. The result is that you
learn a lot in a short amount of time. You see what works and what
doesn’t.
I worked as a subcontractor for several years and it has taught me a lot
about the various aspects of running a business, project management,
programing, automation, and testing. The bigger the company, the more
effective this shortcut is.
As a subcontractor, you switch companies from time to time and that
only increases the amount you learn. Every company does things differ-
ently and that’s what you’re looking for. You can pick and choose what
works and apply that. It’s one thing reading about something, but it’s
something completely different to be immersed in it.
If you’re a freelancer and freedom is important to you, then subcontract-
2 Taking a Shortcut 298
ing may not be what you’re looking for. Keep that in mind when you’re
given this opportunity.
If you’re lucky, then you work at a company that gives you the freedom
to learn new things on the job. While this may seem like a generous
gesture, your employer knows and understands that they need to invest
in their employees and their education. The technology industry is a
competitive arena and what worked yesterday may no longer work
today or tomorrow.
Choose Wisely
I started this book with a strong focus on your foundation and I want
to briefly revisit this topic. It’s tempting to focus on the shiny stuff
companies like Apple and Google spoil us with. But remember that you
make a living building applications that are powered by technologies
that have been around for decades. Make sure you don’t neglect your
foundation.
With a solid foundation it’s easier to pick up new technologies. Once
you understand how the puzzle fits together, it’s easier to pick up
new languages, frameworks, and libraries. Investing in your foundation
should always be your main concern. It helps you build confidence and
it ensures that you can make a living doing what you love doing, building
software.
3 Some Things Are Hard
Before the iPhone was introduced in 2007, Cocoa Programming for Mac
OS X149 by Aaron Hillegass150 was the book if you were interested in
Cocoa development. It was Aaron’s book that introduced me to Cocoa
programming.
One of the most important lessons Aaron taught me had nothing to do
with programming. In the first chapter of his book, Aaron writes about
Rock, a former boss he had worked with.
Some things are hard. Unfortunately, admitting that some things are
hard is some sort of taboo among programmers. You lose credibility
as a programmer if you admit that you’re struggling understanding
something.
149
https://www.amazon.com/Cocoa-Programming-Mac-OS-4th/dp/0321774086
150
https://twitter.com/AaronHillegass
151
https://www.amazon.com/Cocoa-Programming-Mac-OS-4th/dp/0321774086
3 Some Things Are Hard 301
It’s not that I’m so smart, it’s just that I stay with problems
longer. — Albert Einstein
Examples
Views are supposed be dumb. A view should only know how to present
the data it’s given. This is a rule you shouldn’t break. But I don’t agree
with that. Once you understand why this rule is important, it’s fine to
break it as long as you understand what the consequences are.
I sometimes break this rule when I create a complex table or collection
view. If you notice that you’re making it very hard on yourself to keep the
view dumb and ignorant, then it may be better to look for an alternative.
In such a scenario, I promote the table or collection view cell to a
controller. I see each table or collection view cell as a view controller
and its content view as the view controller’s view. This can often reduce
the complexity in the view controller that drives the table or collection
view.
I know that I’m breaking a rule and I understand the impact of that deci-
sion. That understanding gives me the confidence I need to implement
a solution I know works better.
4 Learn the Rules, Then Break Them 303
Growing as a Developer
There’s a subtle but important difference between violating a rule and
breaking a rule. Breaking a rule implies that you know about the rule
and you should know about the consequences. That said, break rules
sparingly. There’s a reason why design patterns and best practices exist.
It can sometimes help to play by the rules to understand how to break
them.
are. Junior developers do this frequently without realizing it. And that’s
fine. You always learn something if you make a mistake. Just make sure
you don’t make the same mistake twice.