KEMBAR78
Best Practice in Swift | PDF | Swift (Programming Language) | String (Computer Science)
0% found this document useful (0 votes)
131 views98 pages

Best Practice in Swift

This document discusses emerging best practices in Swift programming. It covers several topics: 1. Learning from history and not repeating mistakes of the past. New syntax and features should enable new ideas rather than just being adopted for their own sake. 2. Examples of best practices that emerged from Swift features like object literals and blocks. Dependency injection and limiting coupling between objects also help enable testing. 3. The importance of incremental change and never throwing away code or ideas prematurely. Both code and ideas have merit, and refactoring is preferable to rewriting from scratch.

Uploaded by

thejay
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
131 views98 pages

Best Practice in Swift

This document discusses emerging best practices in Swift programming. It covers several topics: 1. Learning from history and not repeating mistakes of the past. New syntax and features should enable new ideas rather than just being adopted for their own sake. 2. Examples of best practices that emerged from Swift features like object literals and blocks. Dependency injection and limiting coupling between objects also help enable testing. 3. The importance of incremental change and never throwing away code or ideas prematurely. Both code and ideas have merit, and refactoring is preferable to rewriting from scratch.

Uploaded by

thejay
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 98

Emerging

Best Practices
in Swift
Ash Furrow
Afraid
I was
Everything turned out

Fine
Best Practices in Swift
What do they look like?

Also, how do we find new ones?


Agenda

Weve been here before

Learning is forever, deal with it

Never throw ideas away

How to force yourself to think

Always be abstracting
Lets go!
This looks strangely familiar
Those who dont study history
are doomed to repeat it.
Lots of people, for hundreds of years
Wow, thats depressing.
Those who dont understand the past
cant make informed decisions about the present.
Me, today
iOS 5 or earlier?
Before Object Literals
NSArray *array = [NSArray arrayWithObjects:
@"This",
@"is",
@"so",
@"tedious", nil];

NSDictionary *dictionary = [NSDictionary


dictionaryWithObjectsAndKeys:
@"Who would do this?", @"Not me", nil];

NSNumber *number = [NSNumber numberWithInt:401];


Before Object Literals and ARC
NSArray *array = [[NSArray arrayWithObjects:
@"This",
@"is",
@"so",
@"tedious", nil] alloc];

NSDictionary *dictionary = [[NSDictionary


dictionaryWithObjectsAndKeys:
@"Who would do this?", @"Not me", nil] alloc];

NSNumber *number = [[NSNumber numberWithInt:401] alloc];


After Object Literals

NSArray *array =
@[ @"This", @"is", @"much", @"better" ];

NSDictionary *dictionary =
@{ @"Who likes this?": @"Me!" };

NSNumber *number = @(401);


Object Literals

Clearly way better

Adopted by everyone almost immediately

Became a best practice


^{
Blocks & GCD

Introduced in iOS 4

Adopted slowly, but surely

Required new ways of thinking

Did using blocks became a best practice?

Sort of
Blocks

Enable
other best practices
Contextual Code Execution

^{
Functional Reactive Programming

Futures
Inline Network Operations

Generic Datasource Objects


Callbacks

Deferred Customization Promises


Collections Operations
Change
Embrace
Swift 2
Swift 2

Lots of new syntax

New syntax lets us do new things

However! Syntax is only a tool

Like blocks, Swift 2 syntax is most useful when it enables new ideas
Swift 2

guard

defer

throws

etc
Should I use guard?
What can I do with guard?
Examples
Pyramid of Doom

if let thing = optionalThing {


if thing.shouldDoThing {
if let otherThing = thing.otherThing {
doStuffWithThing(otherThing)
}
}
}
Clause Applause

if let thing = optionalThing,


let otherThing = thing.otherThing
where thing.shoudDoThing {
doStuffWithThing(otherThing)
}
Avoid Mutability
func strings(
parameter: [String],
startingWith prefix: String) -> [String] {

var mutableArray = [String]()


for string in parameter {
if string.hasPrefix(prefix) {
mutableArray.append(string)
}

_
}

return mutableArray
}
Avoid Mutability

func strings(
parameter: [String],
startingWith prefix: String) -> [String] {

return parameter.filter { $0.hasPrefix(prefix) }


}
Currying

One of those weird words you avoid because people who say it are sometimes jerks

Its actually a pretty straightforward concept

Currying is a function that returns another function

Useful for sharing code thats mostly the same


Before Currying

func containsAtSign(string: String) -> Bool {


return string.characters.contains("@")
}

...

input.filter(containsAtSign)
Currying

func contains(substring: String) -> (String -> Bool) {


return { string -> Bool in
return string.characters.contains(substring)
}
}

...

input.filter(contains("@"))
Currying

func contains(substring: String)(string: String) -> Bool {


return string.characters.contains(substring)
}

...

input.filter(contains("@"))
Extract Associated Values

Use Swift enums

Attach associated values

Extract using a case


Extract Associated Values
enum Result {
case Success
case Failure(reason: String)
}

switch doThing() {
case .Success:
print("")
case .Failure(let reason):
print("Oops: \(reason)")
}
Extract Associated Values

enum Result {
case Success
case Failure(reason: String)
}

if case .Failure(let reason) = doThing() {


print(" \(reason)")
}
Thats all just
Syntax
What matters are

Ideas
Protocol-Oriented
Programming
just go watch the WWDC video.
Others
Lets ask
Syntax vs Idea

How to tell if something is universally a good idea, or just enables other ideas?

You cant

Its a false dichotomy

I lied to you

Im so sorry
Youve just got to
Try stuff
Never throw away

Ideas
Never Throw Away Ideas

Swift was released

We treated Swift like object literals instead of like blocks

Some of us thought Swift was universally better

My fault, oops
Merit
Older ideas have
iOS developers throw things away

A lot
Why?
Beginner learns thing

Is bad at thing

Blames thing

Thing must be bad


Beginner gets more experience

New thing comes out

Learning new thing is easier than old thing

New thing must be good


New ideas are
Appealing
iOS is constantly changing

Always a fresh supply of old APIs


for us to blame
Refactoring
Lets talk about
What is Not Refactor?

Refactoring does not add new functionality

Refactoring does not change a types interface

Refactoring does not change a types behaviour


Changing a unit test?

No Yes

Refactoring Rewriting
Rewrites are

Bad
Favour incremental change
Code isnt necessarily valuable

But throwing it away is dangerous


&
Things to never throw away:

Code
Ideas
Change
Unit tests will help
Unit Testing & Thinking

So, uhh, unit testing

Controversial in iOS

Not so much everywhere else

Why?

Well get to that


Benefits of Testing

(Lets presume that unit testing is a good idea)

I really dont care that much about the tests

I care more about how writing tests makes me think about what Im writing
Benefits of Testing

Limited object scope is good

High cohesion, low coupling

How to limit scope?

Controlling public interface and dependencies



Dependency injection?
Dependency Injection

5 word for a 5 idea

Your things shouldnt create the things they need


Example
Without Dependency Injection
class ViewController: UIViewController {
let networkController = NetworkController()

func viewDidLoad() {
super.viewDidLoad()
networkController.fetchStuff {
self.showStuff()
}
}
}
With Dependency Injection
class ViewController: UIViewController {
var networkController: NetworkController?

func viewDidLoad() {
super.viewDidLoad()
networkController?.fetchStuff {
self.showStuff()
}
}
}
Dependency Injection

Rely on someone else to configure your instance

Could be another part of your app (eg: prepareForSegue)

Could be a unit test

Protocols work really well for this


Dependency Injection
protocol NetworkController {
func fetchStuff(completion: () -> ())
}

...

class APINetworkController: NetworkController {


func fetchStuff(completion: () -> ()) {
// TODO: fetch stuff and call completion()
}
}
Dependency Injection
protocol NetworkController {
func fetchStuff(completion: () -> ())
}

...

class TestNetworkController: NetworkController {


func fetchStuff(completion: () -> ()) {
// TODO: stub fetched stuff
completion()
}
}
Dependency Injection

Use of protocols limits coupling between types

Adding a method to a protocol becomes a decision you have to make

Dependency injection can also be used for shared state, like singletons
Without Dependency Injection

func loadAppSetup() {
let defaults =
NSUserDefaults.standardUserDefaults()

if defaults.boolForKey("launchBefore") == false {
runFirstLaunch()
}
}
How would you even test that?
With Dependency Injection

func loadAppSetup(defaults: NSUserDefaults) {


if defaults.boolForKey("launchBefore") == false {
runFirstLaunch()
}
}
Dont be an ideologue
Cheat with Dependency Injection

func loadAppSetup(
defaults: NSUserDefaults = .standardUserDefaults()){

if defaults.boolForKey("launchBefore") == false {
runFirstLaunch()
}
}
Cheat with Dependency Injection

loadAppSetup() // In your app

loadAppSetup(stubbedUserDefaults) // In your tests


Cheat with Dependency Injection
class ViewController: UIViewController {
lazy var networkController: NetworkController =
APINetworkController()

func viewDidLoad() {
super.viewDidLoad()
networkController.fetchStuff {
self.showStuff()
}
}
}
TDD if necessary, but not necessarily TDD.

Mackenzie King (Canadas Winston Churchill)


Unit Testing
Dont test private functions

Also, start marking functions as private

Remember, we want to avoid rewriting

Dont test the implementation

Dont use partial mocks

See @searls post on partial mocks


Unit Testing

So why dont iOS developers do unit testing?

Its unfamiliar and no one forces us to do it


Better
Testing code makes me a

Developer
Abstract
Everything
Two or more lines of repeated code?

Find a better way


(
Look for Abstractions

Youre already learning new syntax

Look for new abstractions along the way

Not all ideas will work out

But you should still do it

Experiment!
No such thing
as a

Failed experiment
Learn
Always opportunities to
Wrap Up

We have a history of being awesome, lets keep it up

Learning isnt just for when Xcode is in beta

Ideas are more valuable than code, but throwing away either is dangerous

Effective unit tests make it easy to change code

Operate at the highest level of abstraction you can at any given time
Make
Better Mistakes
Tomorrow

You might also like