Thinking in Swift: Lessons
Learned from Converting a
Legacy Robotics
Project To Swift
Janie Clayton
About Me
• Software Engineer at
SonoPlot
• Cohost of NSBrief
• Coauthor of “iOS 8 SDK
Development”
• @RedQueenCoder
• http://redqueencoder.com
Thinking In Swift
Microplotter II
Thinking In Swift
Most Common Issues
Silent nil messaging failures
“Faith-based casting”
Unexpected object coupling
Error handling problems
Nil: The Silent Killer
The $10,000 Bug
Silent Failure: Feature or
Bug?
Dereferencing null pointers causes crashes in C and C++.
Null pointers also cause random behavior and memory
corruption.
Rather than crash if there is nothing at the pointer,
Objective-C sends messages to nil, which effectively does
nothing
Does not warn or alert you that the message isn’t being
received by anything.
Nil Messages!!
-[NSAlert alertWithError:] called with nil NSError.
A generic error message will be displayed,
but the user deserves better.
Nil-Messaging Accessors
Inheriting from NSObject: nil
Int: 0
Float: 0.0
Double: 0.0
Thinking In Swift
Why Required Values are a
Good Thing
In Objective-C, optional values are the default rather
than something you choose to opt into.
Compiler enforced rules force you to ensure your
values are compliant or else it won’t let you build.
These compiler enforced rules catch bugs before they
are released out into the field.
Compile-time prevention > unit test catches > crashes
in QA testing > bugs in the field
Type Safety in Swift
Prevents “faith-based casting”
What does an NSArray take in and give out?
NSNotifications?
Compiler-defined interfaces
Like putting together pieces in a puzzle
Example: fixed-length arrays using tuples
Property List Serialization
NSUserDefaults
Serialize data to make it easily storable
Cocoa way: Use NSCoder to convert types
to NSData to be stored and extracted later.
Issues with NSCoding
Weak type safety, with potential security and stability
issues
Only works on descendants of NSObject, which does
not include Swift structs or enums
NSData is essentially “Grey Goo” in that it is a blob of
data that is not human readable.
Thinking In Swift
struct Coordinate {
let x:Double
let y:Double
let z:Double
init(_ x: Double, _ y:Double, _ z:Double)
{
self.x = x
self.y = y
self.z = z
}
}
protocol PropertyListReadable
{
func propertyListRepresentation() -> NSDictionary
init?(propertyListRepresentation:NSDictionary?)
}
extension Coordinate:PropertyListReadable {
func propertyListRepresentation() -> NSDictionary
{
let representation:[String:AnyObject] =
[“x”:self.x, “y”:self.y, “z”:self.z]
return representation
}
init?(propertyListRepresentation:NSDictionary?) {
guard let values = propertyListRepresentation
else return {nil}
if let xCoordinate = values[“x”] as? Double,
yCoordinate = values[“y”] as? Double,
zCoordinate = values[“z”] as? Double {
self.x = xCoordinate
self.y = yCoordinate
self.z = zCoordinate
} else {
return nil
}
}
1.1
2.0
1.2
func
saveValuesToDefault<T:PropertyListReadable>
(newValues:[T], key:String)
{
let encodedValues = newValues
.map{$0.propertyListRepresentation()}
NSUserDefaults.standardUserDefaults()
.setObject(encodedValues, forKey:key)
}
[“savedPositions”:
[[firstCoordinateNSDictionary],
[secondCoordinateNSDictionary],
[thirdCoordinateNSDictionary]]
]
func
extractValuesFromPropertyListArray<PropertyListReadable>
(propertyListArray:[AnyObject]?) -> [T]
{
guard let encodedArray = propertyListArray as?
[NSDictionary] else {return []}
return encodedArray
.map{T(propertyListRepresentation:$0)}
.filter{ $0 != nil }
.map{ $0! }
}
encodedArray
.map{T(propertyListRepresentation:$0)}
.filter{ $0 != nil }
.map{ $0! }
encodedArray
.flatMap{T(propertyListRepresentation:$0)}
guard let encodedArray = propertyListArray as?
[NSDictionary] else {return []}
guard let encodedArray = propertyListArray
else {return []}
func
extractValuesFromPropertyListArray<PropertyListReadable>
(propertyListArray:[AnyObject]?) -> [T]
{
guard let encodedArray = propertyListArray else
{return []}
return encodedArray.map{$0 as? NSDictionary}
.flatMap{T(propertyListRepresentation:$0)}
}
Reducing Mutability
Thinking In Swift
Why Reducing Mutability is
Good
If a lot of objects look at and can write to the same
object, one can change it underneath another one
Our robotics might expect a value to be one thing, but
another piece of code might change it and confuse the
robotics, which can cause physical damage that is $$$
Creates code coupling, aka Spaghetti Code. Huzzah!
Untestable Code
Code coupling made our code untestable because no
one piece could be isolated from any other piece
The code base became unstable and bugs took longer
and longer to find and to fix
It also became more difficult to add new features to the
code because the code would break
Taking the lessons learned from maintaining a 7-year-
old project allowed us to re-architect the software in a
more stable manner
Values Types vs
Reference Types
Objects and Objective-C
Objects were the only way to encapsulate data and the
code that acted on the data in Objective-C
The Cocoa Frameworks were designed around the
idea that everything would be an object
All Objective-C objects were passed by reference
Swift Structs and Enums
Allowed other ways of encapsulating data besides just
classes.
Far more powerful and feature rich than C structs and
enums
Allows you to differentiate between passing values and
passing references.
When to use a class?
Use a class when you want shared references
Use a class if you need traditional inheritance
Use and enum if you need to represent distinct
options
Use a struct for all other structured values
Error Handling
Thinking In Swift
Where is it most important to make
sure you have error handling?
Interacting with the file system
Interacting with hardware
Communication over a network
Why Error Handling is
Important
You do have complete control over your application.
You don’t have complete control over the outside
world.
You have to deal with error handling when you are
interacting with the outside world and it can fail in weird
ways.
Problems with Objective-C
Error Handling
A method / function can only return one value
✨ Magic constants ✨
Error scribbling and code crashes
http://edgecasesshow.com/007-if-you-look-at-the-
error-you-will-crash.html
Verbose and easy to forget to handle all the failure
states
- (Coordinate *)moveToCoordinate:(Coordinate *)targetCoordinate error:(NSError **)error
{
if (targetCoordinate == nil){
if (error != nil){
*error = [self errorForRoboticsErrorCode:BADCOORDINATE];
}
return nil;
}
if(![self moveUp error:error]){
return nil;
}
if(![self moveOverCoordinate:targetCoordinate error:error]){
return nil;
}
Coordinate *newPosition = [self readCurrentCoordinate:error];
if(newPosition == nil){
return nil;
}
if(!newPosition.isEqualTo(targetCoordinate)){
if (error != NULL){
*error = [self errorForRoboticsErrorCode:MISMATCHEDPOSITIONS]
}
return nil;
}
return newPosition;
}
Swift 1.0 and Result Type
Uses generics and enums with associated values to create a
reusable return type
Two cases: Success(value) and Failure(error)
Forces you to handle the errors if you want the success value
No need for magic constants or inputs as outputs
Allows us use error types other than NSError, like custom
Swift enums
public enum Result<T, U>{
case Success<T>
case Failure<U>
func then<V>(nextOperation:T -> Result<V, U>)
-> Result<V, U> {
switch self {
case let .Failure(error):
return .Failure(error)
case let .Success(value):
return nextOperation(value)
}
}
}
enum RoboticsError {
case MismatchedPosition
case HitObstruction
case NotConnected
}
func moveToCoordinate(targetCoordinate:Coordinate) ->
Result<Coordinate, RoboticsError>
{
return self.moveUp()
.then{self.moveOverCoordinate(targetCoordinate)}
.then{self.moveDownCoordinate(targetCoordinate)}
.then{self.readCurrentCoordinate()}
.then{coordinate -> Result<Coordinate,
RoboticsError> in
if (coordinate != targetCoordinate) {
return .Failure(.MismatchedPosition)
} else {
return .Success(coordinate)
}
}
}
Advantages of Result Error
Handling
Compiler-enforced error handling for return values
Uses less code (go from 38 lines of code to 12)
Inputs are inputs, outputs are outputs
More human readable by removing boilerplate code
Issues with Result Error
Handling
Odd code flow with return statement at top
Really long chained statements can choke the compiler
Have to enclose non-Result-returning functions in
awkward closures
Easy to ignore errors from functions that don’t return
values
Thinking In Swift
Swift 2.0 Error Handling
Introduced a try/catch error handling model
At a glance, very different from Result<T,U>, but in
practice very similar
Not at all NSException
Compiler forces you to handle or rethrow every error,
ensuring proper error handling
Do, Try, Catch, Throw, and
Throws
If you have a method that can provide an error, you
specify that it “throws” in the signature
To call an error throwing function, you must call it with
“try”
First “try” line that fails kicks out of the function / method
To catch the error, you use a “do/catch” block
To bubble the error up, “throw” the error
func moveToCoordinate(targetCoordinate: Coordinate)
throws -> Coordinate
{
try self.moveUp()
try self.moveOverCoordinate(targetCoordinate)
try self.moveDownToCoordinate(targetCoordinate)
let coordinate = try self.readCurrentCoordinate()
if(coordinate != targetCoordinate) {
throw .MismatchedPosition
}
return coordinate
}
Advantages over Result<T,U>
Even fewer lines of code (9 vs. 12)
More natural execution flow (return at end)
Fewer braces, no more artificial closures
Compiler-enforced handling of errors, even for
functions with no return values
Swift Wins
Our current code base is 75% smaller than the legacy
code base
Removed whole classes of bugs so that they can’t
even happen
Identified subtle bugs that would have taken weeks to
track down and have caused thousands of dollars in
damages
We can now implement new features that weren’t
possible before because the code was too fragile
Swift Wins
We now have unit tests that we could not implement in
the old code because of mutability and code coupling.
We are able to do sophisticated unit testing using fake
robots and serial ports in code that don’t require us to
connect to hardware.
Links and Questions
http://www.sunsetlakesoftware.com/2014/12/02/why-
were-rewriting-our-robotics-software-swift
http://www.sunsetlakesoftware.com/2015/06/12/
swift-2-error-handling-practice
https://github.com/LlamaKit/LlamaKit
http://edgecasesshow.com/007-if-you-look-at-the-
error-you-will-crash.html

More Related Content

PDF
Robots in Swift
PDF
Object-oriented Basics
PDF
Design patterns in java script, jquery, angularjs
PPTX
Solid principles
PDF
JavaScript Programming
PDF
Sony C#/.NET component set analysis
PDF
Writing clean code
PDF
Lsl scripts
Robots in Swift
Object-oriented Basics
Design patterns in java script, jquery, angularjs
Solid principles
JavaScript Programming
Sony C#/.NET component set analysis
Writing clean code
Lsl scripts

What's hot (20)

PDF
Design patterns illustrated 010PHP
PDF
Design patterns illustrated-2015-03
PPTX
Oop objects_classes
PPT
The JavaScript Programming Language
PDF
iOS 101 - Xcode, Objective-C, iOS APIs
PDF
How to really obfuscate your pdf malware
PPTX
Oop2010 Scala Presentation Stal
PPT
Constructor and destructor in C++
PPTX
2. Design patterns. part #2
PDF
Java ppt Gandhi Ravi ([email protected])
PDF
One Careful Owner
PDF
Java Script Best Practices
PPTX
Python Programming Essentials - M20 - Classes and Objects
PDF
Java Persistence API
PDF
ReactJS for Programmers
PPT
Objective-C for iOS Application Development
PDF
Google Dart
PPTX
PPTX
Constructors and destructors
PPTX
Applying Compiler Techniques to Iterate At Blazing Speed
Design patterns illustrated 010PHP
Design patterns illustrated-2015-03
Oop objects_classes
The JavaScript Programming Language
iOS 101 - Xcode, Objective-C, iOS APIs
How to really obfuscate your pdf malware
Oop2010 Scala Presentation Stal
Constructor and destructor in C++
2. Design patterns. part #2
Java ppt Gandhi Ravi ([email protected])
One Careful Owner
Java Script Best Practices
Python Programming Essentials - M20 - Classes and Objects
Java Persistence API
ReactJS for Programmers
Objective-C for iOS Application Development
Google Dart
Constructors and destructors
Applying Compiler Techniques to Iterate At Blazing Speed
Ad

Viewers also liked (13)

PPTX
Acs 2013 indianapolis_cvsp
PDF
In-silico study of ToxCast GPCR assays by quantitative structure-activity rel...
PDF
John Madayese Research- Barriers to Prosperity in Africa Unchaining the Eco...
PPTX
Open classroom health policy - session 10.16 - iselin and young
PDF
PROCESO DE COMPRA
PPTX
The State of Search: 2016 Edition
PDF
The Importance of Proper Windshield Replacement
PPT
A pérola, de John Steinbeck
PPTX
Meeting of Company
PPT
ppt on meeting and resolution
PDF
Top Fears of Lawyers [Infographic]
PDF
Complete Guide to Seo Footprints
PDF
Guided Reading: Making the Most of It
Acs 2013 indianapolis_cvsp
In-silico study of ToxCast GPCR assays by quantitative structure-activity rel...
John Madayese Research- Barriers to Prosperity in Africa Unchaining the Eco...
Open classroom health policy - session 10.16 - iselin and young
PROCESO DE COMPRA
The State of Search: 2016 Edition
The Importance of Proper Windshield Replacement
A pérola, de John Steinbeck
Meeting of Company
ppt on meeting and resolution
Top Fears of Lawyers [Infographic]
Complete Guide to Seo Footprints
Guided Reading: Making the Most of It
Ad

Similar to Thinking In Swift (20)

PDF
Migrating from Objective-C to Swift
PDF
Никита Корчагин - Programming Apple iOS with Objective-C
PDF
Objective-C to Swift - Swift Cloud Workshop 3
PDF
Swift Tutorial Part 2. The complete guide for Swift programming language
PDF
Swift, swiftly
PPTX
Swift vs Objective-C
PDF
SV-ios-objc-to-swift
PDF
01 objective-c session 1
PDF
Advanced Swift Updated For Swift 5 Chris Eidhof
PDF
Programming with Objective-C
PDF
Custom view
PPTX
Intro to iOS: Object Oriented Programming and Objective-C
PPTX
Ios fundamentals with ObjectiveC
PPTX
Swift LA Meetup at eHarmony- Swift and Enterprise and eHarmony with Heena Ras...
PDF
Objective-C
PDF
Working with Cocoa and Objective-C
PDF
From android/java to swift (3)
PDF
Intro to Objective C
KEY
Debugging: Or How I Learned To Stop Worrying and Love EXC_BAD_ACCESS
Migrating from Objective-C to Swift
Никита Корчагин - Programming Apple iOS with Objective-C
Objective-C to Swift - Swift Cloud Workshop 3
Swift Tutorial Part 2. The complete guide for Swift programming language
Swift, swiftly
Swift vs Objective-C
SV-ios-objc-to-swift
01 objective-c session 1
Advanced Swift Updated For Swift 5 Chris Eidhof
Programming with Objective-C
Custom view
Intro to iOS: Object Oriented Programming and Objective-C
Ios fundamentals with ObjectiveC
Swift LA Meetup at eHarmony- Swift and Enterprise and eHarmony with Heena Ras...
Objective-C
Working with Cocoa and Objective-C
From android/java to swift (3)
Intro to Objective C
Debugging: Or How I Learned To Stop Worrying and Love EXC_BAD_ACCESS

More from Janie Clayton (10)

PDF
Beyond White: Embracing the iOS Design Aesthetic
PDF
3D Math Primer: CocoaConf Chicago
PDF
GPU Programming: Chicago CocoaConf 2015
PDF
3D Math Primer: CocoaConf Atlanta
PDF
GPU Programming: CocoaConf Atlanta
PDF
3D Math Without Presenter Notes
PDF
The Day You Finally Use Algebra: A 3D Math Primer
PDF
GPU Programming 360iDev
PDF
Bug Hunting Safari
PDF
Gpu Programming With GPUImage and Metal
Beyond White: Embracing the iOS Design Aesthetic
3D Math Primer: CocoaConf Chicago
GPU Programming: Chicago CocoaConf 2015
3D Math Primer: CocoaConf Atlanta
GPU Programming: CocoaConf Atlanta
3D Math Without Presenter Notes
The Day You Finally Use Algebra: A 3D Math Primer
GPU Programming 360iDev
Bug Hunting Safari
Gpu Programming With GPUImage and Metal

Recently uploaded (20)

PDF
Revolutionizing recommendations a survey: a comprehensive exploration of mode...
PDF
Domain-specific knowledge and context in large language models: challenges, c...
PDF
Peak of Data & AI Encore: Scalable Design & Infrastructure
PDF
FASHION-DRIVEN TEXTILES AS A CRYSTAL OF A NEW STREAM FOR STAKEHOLDER CAPITALI...
PDF
Human Computer Interaction Miterm Lesson
PDF
TicketRoot: Event Tech Solutions Deck 2025
PDF
【AI論文解説】高速・高品質な生成を実現するFlow Map Models(Part 1~3)
PDF
Optimizing bioinformatics applications: a novel approach with human protein d...
PPTX
maintenance powerrpoint for adaprive and preventive
PDF
Secure Java Applications against Quantum Threats
PPTX
From Curiosity to ROI — Cost-Benefit Analysis of Agentic Automation [3/6]
PPTX
Blending method and technology for hydrogen.pptx
PDF
Introduction to c language from lecture slides
PDF
The Basics of Artificial Intelligence - Understanding the Key Concepts and Te...
PDF
1_Keynote_Breaking Barriers_한계를 넘어서_Charith Mendis.pdf
PPT
Overviiew on Intellectual property right
PPTX
Presentation - Principles of Instructional Design.pptx
PDF
Decision Optimization - From Theory to Practice
PDF
NewMind AI Journal Monthly Chronicles - August 2025
PPTX
From XAI to XEE through Influence and Provenance.Controlling model fairness o...
Revolutionizing recommendations a survey: a comprehensive exploration of mode...
Domain-specific knowledge and context in large language models: challenges, c...
Peak of Data & AI Encore: Scalable Design & Infrastructure
FASHION-DRIVEN TEXTILES AS A CRYSTAL OF A NEW STREAM FOR STAKEHOLDER CAPITALI...
Human Computer Interaction Miterm Lesson
TicketRoot: Event Tech Solutions Deck 2025
【AI論文解説】高速・高品質な生成を実現するFlow Map Models(Part 1~3)
Optimizing bioinformatics applications: a novel approach with human protein d...
maintenance powerrpoint for adaprive and preventive
Secure Java Applications against Quantum Threats
From Curiosity to ROI — Cost-Benefit Analysis of Agentic Automation [3/6]
Blending method and technology for hydrogen.pptx
Introduction to c language from lecture slides
The Basics of Artificial Intelligence - Understanding the Key Concepts and Te...
1_Keynote_Breaking Barriers_한계를 넘어서_Charith Mendis.pdf
Overviiew on Intellectual property right
Presentation - Principles of Instructional Design.pptx
Decision Optimization - From Theory to Practice
NewMind AI Journal Monthly Chronicles - August 2025
From XAI to XEE through Influence and Provenance.Controlling model fairness o...

Thinking In Swift

  • 1. Thinking in Swift: Lessons Learned from Converting a Legacy Robotics Project To Swift Janie Clayton
  • 2. About Me • Software Engineer at SonoPlot • Cohost of NSBrief • Coauthor of “iOS 8 SDK Development” • @RedQueenCoder • http://redqueencoder.com
  • 6. Most Common Issues Silent nil messaging failures “Faith-based casting” Unexpected object coupling Error handling problems
  • 7. Nil: The Silent Killer The $10,000 Bug
  • 8. Silent Failure: Feature or Bug? Dereferencing null pointers causes crashes in C and C++. Null pointers also cause random behavior and memory corruption. Rather than crash if there is nothing at the pointer, Objective-C sends messages to nil, which effectively does nothing Does not warn or alert you that the message isn’t being received by anything.
  • 10. -[NSAlert alertWithError:] called with nil NSError. A generic error message will be displayed, but the user deserves better.
  • 11. Nil-Messaging Accessors Inheriting from NSObject: nil Int: 0 Float: 0.0 Double: 0.0
  • 13. Why Required Values are a Good Thing In Objective-C, optional values are the default rather than something you choose to opt into. Compiler enforced rules force you to ensure your values are compliant or else it won’t let you build. These compiler enforced rules catch bugs before they are released out into the field. Compile-time prevention > unit test catches > crashes in QA testing > bugs in the field
  • 14. Type Safety in Swift Prevents “faith-based casting” What does an NSArray take in and give out? NSNotifications? Compiler-defined interfaces Like putting together pieces in a puzzle Example: fixed-length arrays using tuples
  • 15. Property List Serialization NSUserDefaults Serialize data to make it easily storable Cocoa way: Use NSCoder to convert types to NSData to be stored and extracted later.
  • 16. Issues with NSCoding Weak type safety, with potential security and stability issues Only works on descendants of NSObject, which does not include Swift structs or enums NSData is essentially “Grey Goo” in that it is a blob of data that is not human readable.
  • 18. struct Coordinate { let x:Double let y:Double let z:Double init(_ x: Double, _ y:Double, _ z:Double) { self.x = x self.y = y self.z = z } }
  • 19. protocol PropertyListReadable { func propertyListRepresentation() -> NSDictionary init?(propertyListRepresentation:NSDictionary?) }
  • 20. extension Coordinate:PropertyListReadable { func propertyListRepresentation() -> NSDictionary { let representation:[String:AnyObject] = [“x”:self.x, “y”:self.y, “z”:self.z] return representation } init?(propertyListRepresentation:NSDictionary?) { guard let values = propertyListRepresentation else return {nil} if let xCoordinate = values[“x”] as? Double, yCoordinate = values[“y”] as? Double, zCoordinate = values[“z”] as? Double { self.x = xCoordinate self.y = yCoordinate self.z = zCoordinate } else { return nil } } 1.1 2.0 1.2
  • 21. func saveValuesToDefault<T:PropertyListReadable> (newValues:[T], key:String) { let encodedValues = newValues .map{$0.propertyListRepresentation()} NSUserDefaults.standardUserDefaults() .setObject(encodedValues, forKey:key) }
  • 23. func extractValuesFromPropertyListArray<PropertyListReadable> (propertyListArray:[AnyObject]?) -> [T] { guard let encodedArray = propertyListArray as? [NSDictionary] else {return []} return encodedArray .map{T(propertyListRepresentation:$0)} .filter{ $0 != nil } .map{ $0! } }
  • 26. guard let encodedArray = propertyListArray as? [NSDictionary] else {return []}
  • 27. guard let encodedArray = propertyListArray else {return []}
  • 28. func extractValuesFromPropertyListArray<PropertyListReadable> (propertyListArray:[AnyObject]?) -> [T] { guard let encodedArray = propertyListArray else {return []} return encodedArray.map{$0 as? NSDictionary} .flatMap{T(propertyListRepresentation:$0)} }
  • 31. Why Reducing Mutability is Good If a lot of objects look at and can write to the same object, one can change it underneath another one Our robotics might expect a value to be one thing, but another piece of code might change it and confuse the robotics, which can cause physical damage that is $$$ Creates code coupling, aka Spaghetti Code. Huzzah!
  • 32. Untestable Code Code coupling made our code untestable because no one piece could be isolated from any other piece The code base became unstable and bugs took longer and longer to find and to fix It also became more difficult to add new features to the code because the code would break Taking the lessons learned from maintaining a 7-year- old project allowed us to re-architect the software in a more stable manner
  • 34. Objects and Objective-C Objects were the only way to encapsulate data and the code that acted on the data in Objective-C The Cocoa Frameworks were designed around the idea that everything would be an object All Objective-C objects were passed by reference
  • 35. Swift Structs and Enums Allowed other ways of encapsulating data besides just classes. Far more powerful and feature rich than C structs and enums Allows you to differentiate between passing values and passing references.
  • 36. When to use a class? Use a class when you want shared references Use a class if you need traditional inheritance Use and enum if you need to represent distinct options Use a struct for all other structured values
  • 39. Where is it most important to make sure you have error handling? Interacting with the file system Interacting with hardware Communication over a network
  • 40. Why Error Handling is Important You do have complete control over your application. You don’t have complete control over the outside world. You have to deal with error handling when you are interacting with the outside world and it can fail in weird ways.
  • 41. Problems with Objective-C Error Handling A method / function can only return one value ✨ Magic constants ✨ Error scribbling and code crashes http://edgecasesshow.com/007-if-you-look-at-the- error-you-will-crash.html Verbose and easy to forget to handle all the failure states
  • 42. - (Coordinate *)moveToCoordinate:(Coordinate *)targetCoordinate error:(NSError **)error { if (targetCoordinate == nil){ if (error != nil){ *error = [self errorForRoboticsErrorCode:BADCOORDINATE]; } return nil; } if(![self moveUp error:error]){ return nil; } if(![self moveOverCoordinate:targetCoordinate error:error]){ return nil; } Coordinate *newPosition = [self readCurrentCoordinate:error]; if(newPosition == nil){ return nil; } if(!newPosition.isEqualTo(targetCoordinate)){ if (error != NULL){ *error = [self errorForRoboticsErrorCode:MISMATCHEDPOSITIONS] } return nil; } return newPosition; }
  • 43. Swift 1.0 and Result Type Uses generics and enums with associated values to create a reusable return type Two cases: Success(value) and Failure(error) Forces you to handle the errors if you want the success value No need for magic constants or inputs as outputs Allows us use error types other than NSError, like custom Swift enums
  • 44. public enum Result<T, U>{ case Success<T> case Failure<U> func then<V>(nextOperation:T -> Result<V, U>) -> Result<V, U> { switch self { case let .Failure(error): return .Failure(error) case let .Success(value): return nextOperation(value) } } }
  • 45. enum RoboticsError { case MismatchedPosition case HitObstruction case NotConnected }
  • 46. func moveToCoordinate(targetCoordinate:Coordinate) -> Result<Coordinate, RoboticsError> { return self.moveUp() .then{self.moveOverCoordinate(targetCoordinate)} .then{self.moveDownCoordinate(targetCoordinate)} .then{self.readCurrentCoordinate()} .then{coordinate -> Result<Coordinate, RoboticsError> in if (coordinate != targetCoordinate) { return .Failure(.MismatchedPosition) } else { return .Success(coordinate) } } }
  • 47. Advantages of Result Error Handling Compiler-enforced error handling for return values Uses less code (go from 38 lines of code to 12) Inputs are inputs, outputs are outputs More human readable by removing boilerplate code
  • 48. Issues with Result Error Handling Odd code flow with return statement at top Really long chained statements can choke the compiler Have to enclose non-Result-returning functions in awkward closures Easy to ignore errors from functions that don’t return values
  • 50. Swift 2.0 Error Handling Introduced a try/catch error handling model At a glance, very different from Result<T,U>, but in practice very similar Not at all NSException Compiler forces you to handle or rethrow every error, ensuring proper error handling
  • 51. Do, Try, Catch, Throw, and Throws If you have a method that can provide an error, you specify that it “throws” in the signature To call an error throwing function, you must call it with “try” First “try” line that fails kicks out of the function / method To catch the error, you use a “do/catch” block To bubble the error up, “throw” the error
  • 52. func moveToCoordinate(targetCoordinate: Coordinate) throws -> Coordinate { try self.moveUp() try self.moveOverCoordinate(targetCoordinate) try self.moveDownToCoordinate(targetCoordinate) let coordinate = try self.readCurrentCoordinate() if(coordinate != targetCoordinate) { throw .MismatchedPosition } return coordinate }
  • 53. Advantages over Result<T,U> Even fewer lines of code (9 vs. 12) More natural execution flow (return at end) Fewer braces, no more artificial closures Compiler-enforced handling of errors, even for functions with no return values
  • 54. Swift Wins Our current code base is 75% smaller than the legacy code base Removed whole classes of bugs so that they can’t even happen Identified subtle bugs that would have taken weeks to track down and have caused thousands of dollars in damages We can now implement new features that weren’t possible before because the code was too fragile
  • 55. Swift Wins We now have unit tests that we could not implement in the old code because of mutability and code coupling. We are able to do sophisticated unit testing using fake robots and serial ports in code that don’t require us to connect to hardware.