SlideShare a Scribd company logo
Better Brewing with…
Sam Meadley
@sammeadley
Overview
• Macros
• NS_DESIGNATED_INITIALIZER	
  
• NS_UNAVAILABLE	
  
• NS_ASSUME_NONNULL_BEGIN/END	
  
• Behaviour changes between Xcode 6 vs Xcode 7
The real overview
• We’re going to start a brewery. Right here, tonight. 















Any brewers in the
house?
Brewing beer; a primer
• 4 fundamental ingredients (experimentation encouraged)
• Water (let’s make this easier)
• Hops
• Malt
• Yeast
Let’s start a brewery
@interface CBCBrewComponents : NSObject
@property (copy, nonatomic) NSString *identifier;
@property (copy, nonatomic) NSString *hopVariety;
@property (copy, nonatomic) NSString *maltVariety;
@property (copy, nonatomic) NSString *yeastStrain;
- (instancetype)initWithIdentifier:(NSString *)identifier
hopVariety:(NSString *)hopVariety
maltVariety:(NSString *)maltVariety
yeastStrain:(NSString *)yeastStrain NS_DESIGNATED_INITIALIZER;
@end
NS_DESIGNATED_INITIALIZER
• Formalises object initialisation
- (instancetype)initWithIdentifier:(NSString *)identifier
hopVariety:(NSString *)hopVariety
maltVariety:(NSString *)maltVariety
yeastStrain:(NSString *)yeastStrain
{
self = [super init];
if (self) {
_identifier = [identifier copy];
_hopVariety = [hopVariety copy];
_maltVariety = [maltVariety copy];
_yeastStrain = [yeastStrain copy];
}
return self;
}
NS_DESIGNATED_INITIALIZER
• Formalises object initialisation
- (instancetype)initWithIdentifier:(NSString *)identifier
hopVariety:(NSString *)hopVariety
maltVariety:(NSString *)maltVariety
yeastStrain:(NSString *)yeastStrain
{
self = [super init];
if (self) {
_identifier = [identifier copy];
_hopVariety = [hopVariety copy];
_maltVariety = [maltVariety copy];
_yeastStrain = [yeastStrain copy];
}
return self;
}
- (instancetype)initWithHopVariety:(NSString *)hopVariety
maltVariety:(NSString *)maltVariety
yeastStrain:(NSString *)yeastStrain
{
NSUUID *UUID = [NSUUID UUID];
return [self initWithIdentifier:UUID.UUIDString
hopVariety:hopVariety
maltVariety:maltVariety
yeastStrain:yeastStrain];
}
NS_DESIGNATED_INITIALIZER
• Formalises object initialisation
• Generates warnings if convenience initialisers do
not call the designated initialiser
• Communicates intent to other developers
• Even more warnings if you don’t override the
designated initialiser inherited from superclass
(more on that later)
Well that was easy…
• Let’s down tools, it’s brew time.
@interface CBCBrewDay : NSObject
- (instancetype)initWithDate:(NSDate *)date NS_DESIGNATED_INITIALIZER;
- (CBCBrew *)brewFromComponents:(CBCBrewComponents *)brewComponents;
@end
Let’s start with a Pale Ale
CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]];
CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] init];
brewComponents.identifier = @"Pale Ale";
brewComponents.hopVariety = @"Fuggles";
brewComponents.maltVariety = @"Maris Otter";
brewComponents.yeastStrain = @“WLP002";
CBCBrew *brew = [brewDay brewFromComponents:brewComponents];
Nailed it… Cheers! 🍻
Second time around…
• First batch won’t make it past the brewery gates,
better brew a second batch.
CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]];
CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] init];
CBCBrew *brew = [brewDay brewFromComponents:brewComponents];
Erm, something is wrong here
Second time around…
CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]];
CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] init];
brewComponents.identifier = @"Pale Ale";
brewComponents.hopVariety = @"Fuggles";
brewComponents.maltVariety = @"Maris Otter";
brewComponents.yeastStrain = @“WLP002";
CBCBrew *brew = [brewDay brewFromComponents:brewComponents];
Hell no, H20
What went wrong?
CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]];
CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] init];
brewComponents.identifier = @"Pale Ale";
brewComponents.hopVariety = @"Fuggles";
brewComponents.maltVariety = @"Maris Otter";
brewComponents.yeastStrain = @“WLP002";
CBCBrew *brew = [brewDay brewFromComponents:brewComponents];
• No error checking code in the brewFromComponents:
method to ensure that all the required components are set
• Callers can initialise CBCBrewComponents using the
default init inherited from NSObject

Better Brewing with
NS_UNAVAILABLE;
@interface CBCBrewComponents : NSObject
@property (copy, nonatomic) NSString *identifier;
@property (copy, nonatomic) NSString *hopVariety;
@property (copy, nonatomic) NSString *maltVariety;
@property (copy, nonatomic) NSString *yeastStrain;
- (instancetype)initWithIdentifier:(NSString *)identifier
hopVariety:(NSString *)hopVariety
maltVariety:(NSString *)maltVariety
yeastStrain:(NSString *)yeastStrain NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
Better Brewing with
NS_UNAVAILABLE;
CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]];
CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] initWithIdentifier:@"Pale Ale"
hopVariety:@"Fuggles"
maltVariety:@"Maris Otter"
yeastStrain:@"WLP002"];
CBCBrew *brew = [brewDay brewFromComponents:brewComponents];
• Communicate minimum valid object
• Compile time checking
• Earlier resolution, more beer for everyone
The dining philosophers
forgetful brewer problem
@interface CBCBrewComponents : NSObject
- (instancetype)initWithIdentifier:(NSString *)identifier
hopVariety:(NSString *)hopVariety
maltVariety:(NSString *)maltVariety
yeastStrain:(NSString *)yeastStrain NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]];
CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] initWithIdentifier:@"Pale Ale"
hopVariety:nil
maltVariety:@"Maris Otter"
yeastStrain:@"WLP002"];
CBCBrew *brew = [brewDay brewFromComponents:brewComponents];
😭
Better Brewing with
nonnull
• Nullability type specifiers introduced in Xcode 6.3
• Properties
• Parameters
• Method return values
• and more…
• nonnull and nullable	
  
• NS_ASSUME_NONNULL_BEGIN/NS_ASSUME_NONNULL_END
Better Brewing with
nonnull
@interface CBCBrewComponents : NSObject
@property (copy, nonatomic, nonnull) NSString *identifier;
@property (copy, nonatomic, nonnull) NSString *hopVariety;
@property (copy, nonatomic, nonnull) NSString *maltVariety;
@property (copy, nonatomic, nonnull) NSString *yeastStrain;
- (instancetype)initWithIdentifier:(nonnull NSString *)identifier
hopVariety:(nonnull NSString *)hopVariety
maltVariety:(nonnull NSString *)maltVariety
yeastStrain:(nonnull NSString *)yeastStrain NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
Better Brewing with
nonnull
@interface CBCBrewComponents : NSObject
@property (copy, nonatomic, nonnull) NSString *identifier;
@property (copy, nonatomic, nonnull) NSString *hopVariety;
@property (copy, nonatomic, nonnull) NSString *maltVariety;
@property (copy, nonatomic, nonnull) NSString *yeastStrain;
- (instancetype)initWithIdentifier:(nonnull NSString *)identifier
hopVariety:(nonnull NSString *)hopVariety
maltVariety:(nonnull NSString *)maltVariety
yeastStrain:(nonnull NSString *)yeastStrain NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
Better Brewing with
nonnull
• Nullability type specifiers should not be applied partially.
• Along with properties and parameters, they can also
applied to method return types.
• Xcode helps with this.
Forgetful Brewer revisited
@interface CBCBrewComponents : NSObject
@property (copy, nonatomic, nonnull) NSString *identifier;
@property (copy, nonatomic, nonnull) NSString *hopVariety;
@property (copy, nonatomic, nonnull) NSString *maltVariety;
@property (copy, nonatomic, nonnull) NSString *yeastStrain;
- (nonnull instancetype)initWithIdentifier:(nonnull NSString *)identifier
hopVariety:(nonnull NSString *)hopVariety
maltVariety:(nonnull NSString *)maltVariety
yeastStrain:(nonnull NSString *)yeastStrain NS_DESIGNATED_INITIALIZER;
- (nonnull instancetype)init NS_UNAVAILABLE;
@end
Whaddayasay Xcode?
Audited Regions
• That’s a whole lot of nonnull
• Audited Regions can help
• NS_ASSUME_NONNULL_BEGIN	
  
• NS_ASSUME_NONNULL_END
Audited Regions
@interface CBCBrewComponents : NSObject
@property (copy, nonatomic, nonnull) NSString *identifier;
@property (copy, nonatomic, nonnull) NSString *hopVariety;
@property (copy, nonatomic, nonnull) NSString *maltVariety;
@property (copy, nonatomic, nonnull) NSString *yeastStrain;
- (nonnull instancetype)initWithIdentifier:(nonnull NSString *)identifier
hopVariety:(nonnull NSString *)hopVariety
maltVariety:(nonnull NSString *)maltVariety
yeastStrain:(nonnull NSString *)yeastStrain NS_DESIGNATED_INITIALIZER;
- (nonnull instancetype)init NS_UNAVAILABLE;
@end
Is equivalent to;
NS_ASSUME_NONNULL_BEGIN
@interface CBCBrewComponents : NSObject
@property (copy, nonatomic) NSString *identifier;
@property (copy, nonatomic) NSString *hopVariety;
@property (copy, nonatomic) NSString *maltVariety;
@property (copy, nonatomic) NSString *yeastStrain;
- (instancetype)initWithIdentifier:(NSString *)identifier
hopVariety:(NSString *)hopVariety
maltVariety:(NSString *)maltVariety
yeastStrain:(NSString *)yeastStrain NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END
Audited Regions
• You can mix and match nullability type specifier
within an audited region.
NS_ASSUME_NONNULL_BEGIN
@interface CBCBrewComponents : NSObject
@property (copy, nonatomic) NSString *identifier;
@property (copy, nonatomic, nullable) NSString *hopVariety;
@property (copy, nonatomic) NSString *maltVariety;
@property (copy, nonatomic) NSString *yeastStrain;
- (instancetype)initWithIdentifier:(NSString *)identifier
hopVariety:(NSString *)hopVariety
maltVariety:(NSString *)maltVariety
yeastStrain:(NSString *)yeastStrain NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END
Audited Regions
• Even with all this help. Be sure to still implement
error checking. The compiler doesn’t catch it all.
• Be sure to check your inputs are valid.
CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]];
NSString *hopVariety = nil;
CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] initWithIdentifier:@"Pale Ale"
hopVariety:hopVariety
maltVariety:@"Maris Otter"
yeastStrain:@"WLP002"];
CBCBrew *brew = [brewDay brewFromComponents:brewComponents];
Better Brewing with
nonnull
• Communicate correct usage of your class
• More awesome compile-time help
• Less bugs! (you’d hope, right?)
Changes in Xcode 7
(beta)
Adopting
NS_DESIGNATED_INITIALIZER
• Xcode 6.x
• add macro to designated initialiser
• Xcode 7 beta
• add macro to designated initialiser
• explicitly override superclass designated
initialiser(s)
• … even if marked unavailable
Adopting
NS_DESIGNATED_INITIALIZER
• Override inherited initialiser with some sensible
defaults (not like these…)
- (instancetype)init
{
return [self initWithIdentifier:[NSString string]
hopVariety:[NSString string]
maltVariety:[NSString string]
yeastStrain:[NSString string]];
}
Adopting
NS_DESIGNATED_INITIALIZER
• Even if superclass initialiser is marked
NS_UNAVAILABLE, Xcode still issues warning
• https://openradar.appspot.com/21302875
• Call doesNotRecognizeSelector and return nil
- (instancetype)init
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
Summary
• Use NS_DESIGNATED_INITIALIZER to formalise
object initialisation
• Use NS_UNAVAILABLE to hide inherited members
not relevant to your subclass
• Guard against nil inputs and communicate intent
with NS_ASSUME_NONNULL_BEGIN/END
Summary
• https://openradar.appspot.com/21302875
• https://developer.apple.com/library/mac/
documentation/General/Conceptual/
CocoaEncyclopedia/Initialization/Initialization.html
• craftbeercraftcode.com
• https://github.com/sammeadley/brewery
Cheers! 🍻

More Related Content

What's hot

Introduction to Nodejs
Introduction to NodejsIntroduction to Nodejs
Introduction to Nodejs
Gabriele Lana
 
Rubish- A Quixotic Shell
Rubish- A Quixotic ShellRubish- A Quixotic Shell
Rubish- A Quixotic Shell
guest3464d2
 
Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8
Wilson Su
 
Всеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.jsВсеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.js
Yandex
 
JRubyによるエンタープライズweb開発
JRubyによるエンタープライズweb開発JRubyによるエンタープライズweb開発
JRubyによるエンタープライズweb開発
Naoto Takai
 
Security Challenges in Node.js
Security Challenges in Node.jsSecurity Challenges in Node.js
Security Challenges in Node.js
Websecurify
 
nodecalgary1
nodecalgary1nodecalgary1
nodecalgary1
Eric Kryski
 
NodeJS in Windows Azure
NodeJS in Windows AzureNodeJS in Windows Azure
NodeJS in Windows Azure
Jesus Rodriguez
 
JRuby on Rails and Thread Safety
JRuby on Rails and Thread SafetyJRuby on Rails and Thread Safety
JRuby on Rails and Thread Safety
Naoto Takai
 
Alloy Tips & Tricks #TiLon
Alloy Tips & Tricks #TiLonAlloy Tips & Tricks #TiLon
Alloy Tips & Tricks #TiLon
Fokke Zandbergen
 
Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8
Wilson Su
 
The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)
Domenic Denicola
 
How to Write Node.js Module
How to Write Node.js ModuleHow to Write Node.js Module
How to Write Node.js Module
Fred Chien
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
Rubyc Slides
 
JS everywhere 2011
JS everywhere 2011JS everywhere 2011
JS everywhere 2011
Oleg Podsechin
 
7주 JavaScript 실습
7주 JavaScript 실습7주 JavaScript 실습
7주 JavaScript 실습
지수 윤
 
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
Jeongkyu Shin
 
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the ForgePuppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet
 
2010 04-24-cerealize
2010 04-24-cerealize2010 04-24-cerealize
2010 04-24-cerealize
Lin Jen-Shin
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
Visual Engineering
 

What's hot (20)

Introduction to Nodejs
Introduction to NodejsIntroduction to Nodejs
Introduction to Nodejs
 
Rubish- A Quixotic Shell
Rubish- A Quixotic ShellRubish- A Quixotic Shell
Rubish- A Quixotic Shell
 
Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8
 
Всеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.jsВсеволод Струкчинский: Node.js
Всеволод Струкчинский: Node.js
 
JRubyによるエンタープライズweb開発
JRubyによるエンタープライズweb開発JRubyによるエンタープライズweb開発
JRubyによるエンタープライズweb開発
 
Security Challenges in Node.js
Security Challenges in Node.jsSecurity Challenges in Node.js
Security Challenges in Node.js
 
nodecalgary1
nodecalgary1nodecalgary1
nodecalgary1
 
NodeJS in Windows Azure
NodeJS in Windows AzureNodeJS in Windows Azure
NodeJS in Windows Azure
 
JRuby on Rails and Thread Safety
JRuby on Rails and Thread SafetyJRuby on Rails and Thread Safety
JRuby on Rails and Thread Safety
 
Alloy Tips & Tricks #TiLon
Alloy Tips & Tricks #TiLonAlloy Tips & Tricks #TiLon
Alloy Tips & Tricks #TiLon
 
Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8
 
The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)
 
How to Write Node.js Module
How to Write Node.js ModuleHow to Write Node.js Module
How to Write Node.js Module
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
 
JS everywhere 2011
JS everywhere 2011JS everywhere 2011
JS everywhere 2011
 
7주 JavaScript 실습
7주 JavaScript 실습7주 JavaScript 실습
7주 JavaScript 실습
 
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
 
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the ForgePuppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the Forge
 
2010 04-24-cerealize
2010 04-24-cerealize2010 04-24-cerealize
2010 04-24-cerealize
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
 

Recently uploaded

一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
kgyxske
 
Modelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - AmsterdamModelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - Amsterdam
Alberto Brandolini
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
OnePlan Solutions
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
Maitrey Patel
 
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdfThe Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
kalichargn70th171
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
dakas1
 
Assure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyesAssure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !
Marcin Chrost
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...
Paul Brebner
 
Boost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management AppsBoost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management Apps
Jhone kinadey
 
Manyata Tech Park Bangalore_ Infrastructure, Facilities and More
Manyata Tech Park Bangalore_ Infrastructure, Facilities and MoreManyata Tech Park Bangalore_ Infrastructure, Facilities and More
Manyata Tech Park Bangalore_ Infrastructure, Facilities and More
narinav14
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Paul Brebner
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid
 
ppt on the brain chip neuralink.pptx
ppt  on   the brain  chip neuralink.pptxppt  on   the brain  chip neuralink.pptx
ppt on the brain chip neuralink.pptx
Reetu63
 
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
campbellclarkson
 
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
The Third Creative Media
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
gapen1
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
ToXSL Technologies
 

Recently uploaded (20)

一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
 
Modelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - AmsterdamModelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - Amsterdam
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...Transforming Product Development using OnePlan To Boost Efficiency and Innova...
Transforming Product Development using OnePlan To Boost Efficiency and Innova...
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
 
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdfThe Comprehensive Guide to Validating Audio-Visual Performances.pdf
The Comprehensive Guide to Validating Audio-Visual Performances.pdf
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
 
Assure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyesAssure Contact Center Experiences for Your Customers With ThousandEyes
Assure Contact Center Experiences for Your Customers With ThousandEyes
 
Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...Superpower Your Apache Kafka Applications Development with Complementary Open...
Superpower Your Apache Kafka Applications Development with Complementary Open...
 
Boost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management AppsBoost Your Savings with These Money Management Apps
Boost Your Savings with These Money Management Apps
 
Manyata Tech Park Bangalore_ Infrastructure, Facilities and More
Manyata Tech Park Bangalore_ Infrastructure, Facilities and MoreManyata Tech Park Bangalore_ Infrastructure, Facilities and More
Manyata Tech Park Bangalore_ Infrastructure, Facilities and More
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
 
ppt on the brain chip neuralink.pptx
ppt  on   the brain  chip neuralink.pptxppt  on   the brain  chip neuralink.pptx
ppt on the brain chip neuralink.pptx
 
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
🏎️Tech Transformation: DevOps Insights from the Experts 👩‍💻
 
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
 

Better Brewing with...

  • 1. Better Brewing with… Sam Meadley @sammeadley
  • 2. Overview • Macros • NS_DESIGNATED_INITIALIZER   • NS_UNAVAILABLE   • NS_ASSUME_NONNULL_BEGIN/END   • Behaviour changes between Xcode 6 vs Xcode 7
  • 3. The real overview • We’re going to start a brewery. Right here, tonight. 
 
 
 
 
 
 
 

  • 4. Any brewers in the house?
  • 5. Brewing beer; a primer • 4 fundamental ingredients (experimentation encouraged) • Water (let’s make this easier) • Hops • Malt • Yeast
  • 6. Let’s start a brewery @interface CBCBrewComponents : NSObject @property (copy, nonatomic) NSString *identifier; @property (copy, nonatomic) NSString *hopVariety; @property (copy, nonatomic) NSString *maltVariety; @property (copy, nonatomic) NSString *yeastStrain; - (instancetype)initWithIdentifier:(NSString *)identifier hopVariety:(NSString *)hopVariety maltVariety:(NSString *)maltVariety yeastStrain:(NSString *)yeastStrain NS_DESIGNATED_INITIALIZER; @end
  • 7. NS_DESIGNATED_INITIALIZER • Formalises object initialisation - (instancetype)initWithIdentifier:(NSString *)identifier hopVariety:(NSString *)hopVariety maltVariety:(NSString *)maltVariety yeastStrain:(NSString *)yeastStrain { self = [super init]; if (self) { _identifier = [identifier copy]; _hopVariety = [hopVariety copy]; _maltVariety = [maltVariety copy]; _yeastStrain = [yeastStrain copy]; } return self; }
  • 8. NS_DESIGNATED_INITIALIZER • Formalises object initialisation - (instancetype)initWithIdentifier:(NSString *)identifier hopVariety:(NSString *)hopVariety maltVariety:(NSString *)maltVariety yeastStrain:(NSString *)yeastStrain { self = [super init]; if (self) { _identifier = [identifier copy]; _hopVariety = [hopVariety copy]; _maltVariety = [maltVariety copy]; _yeastStrain = [yeastStrain copy]; } return self; } - (instancetype)initWithHopVariety:(NSString *)hopVariety maltVariety:(NSString *)maltVariety yeastStrain:(NSString *)yeastStrain { NSUUID *UUID = [NSUUID UUID]; return [self initWithIdentifier:UUID.UUIDString hopVariety:hopVariety maltVariety:maltVariety yeastStrain:yeastStrain]; }
  • 9. NS_DESIGNATED_INITIALIZER • Formalises object initialisation • Generates warnings if convenience initialisers do not call the designated initialiser • Communicates intent to other developers • Even more warnings if you don’t override the designated initialiser inherited from superclass (more on that later)
  • 10. Well that was easy… • Let’s down tools, it’s brew time. @interface CBCBrewDay : NSObject - (instancetype)initWithDate:(NSDate *)date NS_DESIGNATED_INITIALIZER; - (CBCBrew *)brewFromComponents:(CBCBrewComponents *)brewComponents; @end
  • 11. Let’s start with a Pale Ale CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]]; CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] init]; brewComponents.identifier = @"Pale Ale"; brewComponents.hopVariety = @"Fuggles"; brewComponents.maltVariety = @"Maris Otter"; brewComponents.yeastStrain = @“WLP002"; CBCBrew *brew = [brewDay brewFromComponents:brewComponents]; Nailed it… Cheers! 🍻
  • 12. Second time around… • First batch won’t make it past the brewery gates, better brew a second batch. CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]]; CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] init]; CBCBrew *brew = [brewDay brewFromComponents:brewComponents]; Erm, something is wrong here
  • 13. Second time around… CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]]; CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] init]; brewComponents.identifier = @"Pale Ale"; brewComponents.hopVariety = @"Fuggles"; brewComponents.maltVariety = @"Maris Otter"; brewComponents.yeastStrain = @“WLP002"; CBCBrew *brew = [brewDay brewFromComponents:brewComponents]; Hell no, H20
  • 14. What went wrong? CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]]; CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] init]; brewComponents.identifier = @"Pale Ale"; brewComponents.hopVariety = @"Fuggles"; brewComponents.maltVariety = @"Maris Otter"; brewComponents.yeastStrain = @“WLP002"; CBCBrew *brew = [brewDay brewFromComponents:brewComponents]; • No error checking code in the brewFromComponents: method to ensure that all the required components are set • Callers can initialise CBCBrewComponents using the default init inherited from NSObject

  • 15. Better Brewing with NS_UNAVAILABLE; @interface CBCBrewComponents : NSObject @property (copy, nonatomic) NSString *identifier; @property (copy, nonatomic) NSString *hopVariety; @property (copy, nonatomic) NSString *maltVariety; @property (copy, nonatomic) NSString *yeastStrain; - (instancetype)initWithIdentifier:(NSString *)identifier hopVariety:(NSString *)hopVariety maltVariety:(NSString *)maltVariety yeastStrain:(NSString *)yeastStrain NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @end
  • 16. Better Brewing with NS_UNAVAILABLE; CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]]; CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] initWithIdentifier:@"Pale Ale" hopVariety:@"Fuggles" maltVariety:@"Maris Otter" yeastStrain:@"WLP002"]; CBCBrew *brew = [brewDay brewFromComponents:brewComponents]; • Communicate minimum valid object • Compile time checking • Earlier resolution, more beer for everyone
  • 17. The dining philosophers forgetful brewer problem @interface CBCBrewComponents : NSObject - (instancetype)initWithIdentifier:(NSString *)identifier hopVariety:(NSString *)hopVariety maltVariety:(NSString *)maltVariety yeastStrain:(NSString *)yeastStrain NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @end CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]]; CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] initWithIdentifier:@"Pale Ale" hopVariety:nil maltVariety:@"Maris Otter" yeastStrain:@"WLP002"]; CBCBrew *brew = [brewDay brewFromComponents:brewComponents]; 😭
  • 18. Better Brewing with nonnull • Nullability type specifiers introduced in Xcode 6.3 • Properties • Parameters • Method return values • and more… • nonnull and nullable   • NS_ASSUME_NONNULL_BEGIN/NS_ASSUME_NONNULL_END
  • 19. Better Brewing with nonnull @interface CBCBrewComponents : NSObject @property (copy, nonatomic, nonnull) NSString *identifier; @property (copy, nonatomic, nonnull) NSString *hopVariety; @property (copy, nonatomic, nonnull) NSString *maltVariety; @property (copy, nonatomic, nonnull) NSString *yeastStrain; - (instancetype)initWithIdentifier:(nonnull NSString *)identifier hopVariety:(nonnull NSString *)hopVariety maltVariety:(nonnull NSString *)maltVariety yeastStrain:(nonnull NSString *)yeastStrain NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @end
  • 20. Better Brewing with nonnull @interface CBCBrewComponents : NSObject @property (copy, nonatomic, nonnull) NSString *identifier; @property (copy, nonatomic, nonnull) NSString *hopVariety; @property (copy, nonatomic, nonnull) NSString *maltVariety; @property (copy, nonatomic, nonnull) NSString *yeastStrain; - (instancetype)initWithIdentifier:(nonnull NSString *)identifier hopVariety:(nonnull NSString *)hopVariety maltVariety:(nonnull NSString *)maltVariety yeastStrain:(nonnull NSString *)yeastStrain NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @end
  • 21. Better Brewing with nonnull • Nullability type specifiers should not be applied partially. • Along with properties and parameters, they can also applied to method return types. • Xcode helps with this.
  • 22. Forgetful Brewer revisited @interface CBCBrewComponents : NSObject @property (copy, nonatomic, nonnull) NSString *identifier; @property (copy, nonatomic, nonnull) NSString *hopVariety; @property (copy, nonatomic, nonnull) NSString *maltVariety; @property (copy, nonatomic, nonnull) NSString *yeastStrain; - (nonnull instancetype)initWithIdentifier:(nonnull NSString *)identifier hopVariety:(nonnull NSString *)hopVariety maltVariety:(nonnull NSString *)maltVariety yeastStrain:(nonnull NSString *)yeastStrain NS_DESIGNATED_INITIALIZER; - (nonnull instancetype)init NS_UNAVAILABLE; @end Whaddayasay Xcode?
  • 23. Audited Regions • That’s a whole lot of nonnull • Audited Regions can help • NS_ASSUME_NONNULL_BEGIN   • NS_ASSUME_NONNULL_END
  • 24. Audited Regions @interface CBCBrewComponents : NSObject @property (copy, nonatomic, nonnull) NSString *identifier; @property (copy, nonatomic, nonnull) NSString *hopVariety; @property (copy, nonatomic, nonnull) NSString *maltVariety; @property (copy, nonatomic, nonnull) NSString *yeastStrain; - (nonnull instancetype)initWithIdentifier:(nonnull NSString *)identifier hopVariety:(nonnull NSString *)hopVariety maltVariety:(nonnull NSString *)maltVariety yeastStrain:(nonnull NSString *)yeastStrain NS_DESIGNATED_INITIALIZER; - (nonnull instancetype)init NS_UNAVAILABLE; @end Is equivalent to; NS_ASSUME_NONNULL_BEGIN @interface CBCBrewComponents : NSObject @property (copy, nonatomic) NSString *identifier; @property (copy, nonatomic) NSString *hopVariety; @property (copy, nonatomic) NSString *maltVariety; @property (copy, nonatomic) NSString *yeastStrain; - (instancetype)initWithIdentifier:(NSString *)identifier hopVariety:(NSString *)hopVariety maltVariety:(NSString *)maltVariety yeastStrain:(NSString *)yeastStrain NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @end NS_ASSUME_NONNULL_END
  • 25. Audited Regions • You can mix and match nullability type specifier within an audited region. NS_ASSUME_NONNULL_BEGIN @interface CBCBrewComponents : NSObject @property (copy, nonatomic) NSString *identifier; @property (copy, nonatomic, nullable) NSString *hopVariety; @property (copy, nonatomic) NSString *maltVariety; @property (copy, nonatomic) NSString *yeastStrain; - (instancetype)initWithIdentifier:(NSString *)identifier hopVariety:(NSString *)hopVariety maltVariety:(NSString *)maltVariety yeastStrain:(NSString *)yeastStrain NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @end NS_ASSUME_NONNULL_END
  • 26. Audited Regions • Even with all this help. Be sure to still implement error checking. The compiler doesn’t catch it all. • Be sure to check your inputs are valid. CBCBrewDay *brewDay = [[CBCBrewDay alloc] initWithDate:[NSDate date]]; NSString *hopVariety = nil; CBCBrewComponents *brewComponents = [[CBCBrewComponents alloc] initWithIdentifier:@"Pale Ale" hopVariety:hopVariety maltVariety:@"Maris Otter" yeastStrain:@"WLP002"]; CBCBrew *brew = [brewDay brewFromComponents:brewComponents];
  • 27. Better Brewing with nonnull • Communicate correct usage of your class • More awesome compile-time help • Less bugs! (you’d hope, right?)
  • 28. Changes in Xcode 7 (beta)
  • 29. Adopting NS_DESIGNATED_INITIALIZER • Xcode 6.x • add macro to designated initialiser • Xcode 7 beta • add macro to designated initialiser • explicitly override superclass designated initialiser(s) • … even if marked unavailable
  • 30. Adopting NS_DESIGNATED_INITIALIZER • Override inherited initialiser with some sensible defaults (not like these…) - (instancetype)init { return [self initWithIdentifier:[NSString string] hopVariety:[NSString string] maltVariety:[NSString string] yeastStrain:[NSString string]]; }
  • 31. Adopting NS_DESIGNATED_INITIALIZER • Even if superclass initialiser is marked NS_UNAVAILABLE, Xcode still issues warning • https://openradar.appspot.com/21302875 • Call doesNotRecognizeSelector and return nil - (instancetype)init { [self doesNotRecognizeSelector:_cmd]; return nil; }
  • 32. Summary • Use NS_DESIGNATED_INITIALIZER to formalise object initialisation • Use NS_UNAVAILABLE to hide inherited members not relevant to your subclass • Guard against nil inputs and communicate intent with NS_ASSUME_NONNULL_BEGIN/END