SlideShare a Scribd company logo
1 of 53
Download to read offline
CocoaHeads
@v_pradeilles | Medium | LinkedIn
From async to Rx, with little to
no work
Swift
Swift
Quick recap on how functions are typed:
// a function that takes an Int and returns Void
let f: (Int) -> Void
// a function that takes an Int and returns a function that takes a String
and returns Void
let g: (Int) -> (String) -> Void
g(2)("Foo")
// and so on…
let h: (T) -> (U) -> (V) -> W
Async Programming
Completion Handlers
Completion handlers are an easy way to pass data asynchronously
// a function that takes a completion handler
func request(arg1: String, arg2: Int, completionHandler: @escaping (String) -> Void)
// and how it is actually called
request(arg1: "Foo", arg2: 0, completionHandler: { result in
// do something with result
})
Completion Handlers
This pattern is great, until you need to chain calls.
When you do, it leads to nested callbacks, which are hard to read and
reason about.
This situation is often known as « callback hell ».
Rx
Rx
Rx is a library that allows to write asynchronous code through the use
of Observables.
// same function, written using RxSwift
func request(arg1: String, arg2: Int) -> Observable<String>
// and you use it like this
request("Foo", 42).subscribe(onNext: { result in
// do something with result
})
Rx makes it easier to work with asynchronous code, so what about
converting legacy or vendor API that uses completion handlers to new
API that return Observables?
We can try doing it by hand:
func observableRequest(arg1: String, arg2: Int) -> Observable<String> {
return Observable.create { (observer) -> Disposable in
request(arg1: arg1, arg2: arg2, completionHandler: { result in
observer.onNext(result)
observer.onCompleted()
})
return Disposables.create()
}
}
Requires a lot of boiler plate & duplicated code 😞
Functional programming
Functional programming
Currying is a fundamental primitive of functional programming.
It allows us to mangle with a function signature.
// this is how you call a standard function
add(arg1: 2, arg2: 3) // returns 5
// this is how you call a curried function
let curriedAdd = curry(add(arg1:arg2:))
curriedAdd(2)(3) // returns 5
How to implement curry
Easier than it seems:
func curry<A, B, C>(_ function: @escaping (A, B) -> C) -> (A) -> (B) -> C {
return { (a: A) -> (B) -> C in { (b: B) -> C in function(a, b) } }
}
Basically, we wrap the function in a succession of lambdas that will
each receive one of the argument before finally calling the wrapped
function.
Putting the pieces together
Base case
func fromAsync(_ asyncRequest: @escaping ((Element) -> Void) -> Void) -> Observable<Element> {
return Observable.create({ (o) -> Disposable in
asyncRequest({ (result) in
o.onNext(result)
o.onCompleted()
})
return Disposables.create()
})
}
Recursion
func fromAsync<T>(_ asyncRequest: @escaping (T, (Element) -> Void) -> Void) -> (T) ->
Observable<Element> {
return { (a: T) in Observable.fromAsync(curry(asyncRequest)(a)) }
}
func fromAsync<T, U>(_ asyncRequest: @escaping (T, U, (Element) -> Void) -> Void) ->
(T, U) -> Observable<Element> {
return { (a: T, b: U) in Observable.fromAsync(curry(asyncRequest)(a)(b)) }
}
How to use it
// let’s bridge this function
func request(arg1: String, arg2: Int, completionHandler: @escaping (String) -> Void)
fromAsync(request(arg1:arg2:completionHandler:))("Foo", 3)
.subscribe(onNext: { (result) in
// do something with result
})
Performances
Nothing comes for free and this technique comes at some performance costs.
Still, there’s nothing we can’t manage.
• Currying function that takes many parameters (> 6) can take sometime to
compile, due to generics and type inference.
=> The bridging code can be placed in a compiled dependency
• Recursive approaches can reduce performances when applied to resource-
demanding code.
=> Profile execution to identify what is running slow, and do the bridging
manually (via boiler plate code) if needed.
It’s even easier in JS!
Currying in JS
JavaScript exposes primitives that allow to manipulate more directly
the arguments list, thus allowing for a real curry function.
function curry( fn ) {
var arity = fn.length;
return (function resolver() {
var memory = Array.prototype.slice.call( arguments );
return function() {
var local = memory.slice(), next;
Array.prototype.push.apply( local, arguments );
next = local.length >= arity ? fn : resolver;
return next.apply( null, local );
};
}());
}
Bonus
Bonus #1
Async functions (regardless of pattern) are great for UI-based code…
…but they’re a pain when it comes to units testing
func async(_ completionHandler: @escaping (String) -> Void) {
sleep(2)
completionHandler("Foo")
}
assert(/* ??? */ == "Foo")
Bonus #1
Good news is, Foundation has all the primitives required to convert
async to sync:
func sync() -> String {
let dispatchGroup = DispatchGroup()
var result: String? = nil
dispatchGroup.enter()
async {
result = $0
dispatchGroup.leave()
}
dispatchGroup.wait()
return result!
}
assert(sync() == "Foo") // 🎉
Bonus #1
By factoring out the boiler plate code, we create a new base case for
bridging:
func toSync<E>(_ async: @escaping ( @escaping (E) -> Void) -> Void) -> () -> E {
return {
let dispatchGroup = DispatchGroup()
var result: E? = nil
dispatchGroup.enter()
async {
result = $0
dispatchGroup.leave()
}
dispatchGroup.wait()
return result!
}
}
Bonus #2
struct MaximumValidator {
private let max: Int
private let strict: Bool
init(max: Int, strict: Bool) {
self.max = max
self.strict = strict
}
func validate(_ value: Int) -> Bool {
if strict {
return value < max
} else {
return value <= max
}
}
}
Bonus #2
By leveraging currying, we can store a much more relevant artifact to
perform the validation:
struct MaximumValidator {
let validate: (_ max: Int) -> Bool
init(max: Int, strict: Bool) {
self.validate = strict ? { $0 < max } : { $0 <= max }
}
}
Recap
What can currying bring to your code ?
• Bridge functions by operating on their signature
• Build alternate version of a function more appropriate to a given
context
• Specialize functions by binding some parameters to constant
values
Questions? 🤔
Thanks!
• Detailed explanation: https://medium.com/@vin.pradeilles/from-
async-api-to-rx-api-with-little-to-no-work-ba725b53a1e0 👏
• Use it in production: https://github.com/RxSwiftCommunity/
RxSwiftExt#fromasync
💪
A pattern to easily enforce
external data validation in Swift
Real world situation
let accountNumber: String = getAccountNumberFromUser()
// .... some code
if !isValidAccountNumber(accountNumber) { return }
// .... some more code
performBusinessLogic(with: accountNumber)
Real world situation
The validation is indeed performed… for now ⏳
But it is lost in a possibly big chunk of code, so:
- It’s easy to break 🚨
- Hard to enforce in review 🤔
➜ We need to figure out a tighter system
Model-driven security
Model-driven security
Wrap data in business objects:
struct AccountNumber {
let number: String
init?(untrustedAccountNumber: String) {
guard isValidAccountNumber(untrustedAccountNumber) else { return nil }
self.number = untrustedAccountNumber
}
}
Model-driven security
And allow business services to only read data from such objects:
func performBusinessLogic(with accountNumber: AccountNumber) {
// ...
}
That’s better, but not enough
struct Transfer {
let creditAccount: String
let debitAccount: String
let amount: Int
init?(untrustedCreditAccount: String,
untrustedDebitAccount: String,
untrustedAmount: Int) {
guard isValidAccountNumber(untrustedCreditAccount),
isValidAccountNumber(untrustedCreditAccount),
isValidAmount(untrustedAmount) else { return nil }
self.creditAccount = untrustedCreditAccount
self.debitAccount = untrustedDebitAccount
self.amount = untrustedAmount
}
}
That’s better, but not enough
struct Transfer {
let creditAccount: String
let debitAccount: String
let amount: Int
init?(untrustedCreditAccount: String,
untrustedDebitAccount: String,
untrustedAmount: Int) {
guard isValidAccountNumber(untrustedCreditAccount),
isValidAccountNumber(untrustedCreditAccount),
isValidAmount(untrustedAmount) else { return nil }
self.creditAccount = untrustedCreditAccount
self.debitAccount = untrustedDebitAccount
self.amount = untrustedAmount
}
}
That’s better, but not enough
The untrusted value can still be accessed without passing the
validation.
That gives a lot of room for nasty bugs, especially in places where
copy/paste tends to be heavily relied on.
The Validator pattern
The Validator pattern
public struct Untrusted<T> {
fileprivate let value: T
public init(_ value: T) {
self.value = value
}
}
The Validator pattern
public struct Untrusted<T> {
fileprivate let value: T
public init(_ value: T) {
self.value = value
}
}
public protocol Validator {
associatedtype T
static func validation(value: T) -> Bool
}
The Validator pattern
extension Validator {
public static func validate(untrusted: Untrusted<T>) -> T? {
if self.validation(value: untrusted.value) {
return untrusted.value
} else {
return nil
}
}
}
We’re still in the
same file!
Let’s see it in action
Let’s see it in action
struct AccountNumberValidator: Validator {
static func validation(value: String) -> Bool {
return isValidAccountNumber(value)
}
}
Let’s see it in action
struct AccountNumberValidator: Validator {
static func validation(value: String) -> Bool {
return isValidAccountNumber(value)
}
}
struct AccountNumber {
let number: String
init?(untrustedAccountNumber: Untrusted<String>) {
guard let validAccountNumber = AccountNumberValidator.validate(untrusted: untrustedAccountNumber)
else {
return nil
}
self.number = validAccountNumber
}
}
Finally, some coding
guidelines
Finally, some coding guidelines
Whenever external data is retrieved, it must be immediately stored in
an Untrusted container => easy to enforce in code review ✅
Initializer of business objects can take as arguments either other
business objects or Untrusted containers, never primitive types =>
easy to enforce in code review ✅
Business logic can only operate with business objects, never with
primitive types => easy to enforce in code review ✅
Questions? 🤔
Thanks, again!
• Detailed explanation: https://medium.com/@vin.pradeilles/a-pattern-
to-easily-enforce-external-data-validation-in-swift-8bc1d5917bfd 👏
• For some more content about secure coding : https://
www.youtube.com/watch?v=oqd9bxy5Hvc (2016 GOTO
conference)
🍞🥤

More Related Content

What's hot

Operator Overloading & Type Conversions
Operator Overloading & Type ConversionsOperator Overloading & Type Conversions
Operator Overloading & Type ConversionsRokonuzzaman Rony
 
Introduction to reactive programming & ReactiveCocoa
Introduction to reactive programming & ReactiveCocoaIntroduction to reactive programming & ReactiveCocoa
Introduction to reactive programming & ReactiveCocoaFlorent Pillet
 
Bca 2nd sem u-4 operator overloading
Bca 2nd sem u-4 operator overloadingBca 2nd sem u-4 operator overloading
Bca 2nd sem u-4 operator overloadingRai University
 
Operator overloading
Operator overloadingOperator overloading
Operator overloadingabhay singh
 
operator overloading & type conversion in cpp over view || c++
operator overloading & type conversion in cpp over view || c++operator overloading & type conversion in cpp over view || c++
operator overloading & type conversion in cpp over view || c++gourav kottawar
 
C++ and OOPS Crash Course by ACM DBIT | Grejo Joby
C++ and OOPS Crash Course by ACM DBIT | Grejo JobyC++ and OOPS Crash Course by ACM DBIT | Grejo Joby
C++ and OOPS Crash Course by ACM DBIT | Grejo JobyGrejoJoby1
 
ReactiveCocoa in Practice
ReactiveCocoa in PracticeReactiveCocoa in Practice
ReactiveCocoa in PracticeOutware Mobile
 
ReactiveCocoa Goodness - Part I of II
ReactiveCocoa Goodness - Part I of IIReactiveCocoa Goodness - Part I of II
ReactiveCocoa Goodness - Part I of IImanuelmaly
 
Presentation on overloading
Presentation on overloading Presentation on overloading
Presentation on overloading Charndeep Sekhon
 
Swift Sequences & Collections
Swift Sequences & CollectionsSwift Sequences & Collections
Swift Sequences & CollectionsCocoaHeads France
 
Découvrir dtrace en ligne de commande.
Découvrir dtrace en ligne de commande.Découvrir dtrace en ligne de commande.
Découvrir dtrace en ligne de commande.CocoaHeads France
 
Functional programming in Javascript
Functional programming in JavascriptFunctional programming in Javascript
Functional programming in JavascriptKnoldus Inc.
 
operator overloading
operator overloadingoperator overloading
operator overloadingNishant Joshi
 
Learn You a ReactiveCocoa for Great Good
Learn You a ReactiveCocoa for Great GoodLearn You a ReactiveCocoa for Great Good
Learn You a ReactiveCocoa for Great GoodJason Larsen
 
Operator Overloading
Operator OverloadingOperator Overloading
Operator OverloadingNilesh Dalvi
 

What's hot (20)

Operator Overloading & Type Conversions
Operator Overloading & Type ConversionsOperator Overloading & Type Conversions
Operator Overloading & Type Conversions
 
Map kit light
Map kit lightMap kit light
Map kit light
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Introduction to reactive programming & ReactiveCocoa
Introduction to reactive programming & ReactiveCocoaIntroduction to reactive programming & ReactiveCocoa
Introduction to reactive programming & ReactiveCocoa
 
JavaScript Core
JavaScript CoreJavaScript Core
JavaScript Core
 
Bca 2nd sem u-4 operator overloading
Bca 2nd sem u-4 operator overloadingBca 2nd sem u-4 operator overloading
Bca 2nd sem u-4 operator overloading
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Overloading
OverloadingOverloading
Overloading
 
expression in cpp
expression in cppexpression in cpp
expression in cpp
 
operator overloading & type conversion in cpp over view || c++
operator overloading & type conversion in cpp over view || c++operator overloading & type conversion in cpp over view || c++
operator overloading & type conversion in cpp over view || c++
 
C++ and OOPS Crash Course by ACM DBIT | Grejo Joby
C++ and OOPS Crash Course by ACM DBIT | Grejo JobyC++ and OOPS Crash Course by ACM DBIT | Grejo Joby
C++ and OOPS Crash Course by ACM DBIT | Grejo Joby
 
ReactiveCocoa in Practice
ReactiveCocoa in PracticeReactiveCocoa in Practice
ReactiveCocoa in Practice
 
ReactiveCocoa Goodness - Part I of II
ReactiveCocoa Goodness - Part I of IIReactiveCocoa Goodness - Part I of II
ReactiveCocoa Goodness - Part I of II
 
Presentation on overloading
Presentation on overloading Presentation on overloading
Presentation on overloading
 
Swift Sequences & Collections
Swift Sequences & CollectionsSwift Sequences & Collections
Swift Sequences & Collections
 
Découvrir dtrace en ligne de commande.
Découvrir dtrace en ligne de commande.Découvrir dtrace en ligne de commande.
Découvrir dtrace en ligne de commande.
 
Functional programming in Javascript
Functional programming in JavascriptFunctional programming in Javascript
Functional programming in Javascript
 
operator overloading
operator overloadingoperator overloading
operator overloading
 
Learn You a ReactiveCocoa for Great Good
Learn You a ReactiveCocoa for Great GoodLearn You a ReactiveCocoa for Great Good
Learn You a ReactiveCocoa for Great Good
 
Operator Overloading
Operator OverloadingOperator Overloading
Operator Overloading
 

Viewers also liked

L'intégration continue avec Bitrise
L'intégration continue avec BitriseL'intégration continue avec Bitrise
L'intégration continue avec BitriseCocoaHeads France
 
Tout savoir pour devenir Freelance
Tout savoir pour devenir FreelanceTout savoir pour devenir Freelance
Tout savoir pour devenir FreelanceFlorent Douine
 
CONTINUOUS DELIVERY WITH FASTLANE
CONTINUOUS DELIVERY WITH FASTLANECONTINUOUS DELIVERY WITH FASTLANE
CONTINUOUS DELIVERY WITH FASTLANECocoaHeads France
 
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017Carol Smith
 

Viewers also liked (10)

Handle the error
Handle the errorHandle the error
Handle the error
 
L'intégration continue avec Bitrise
L'intégration continue avec BitriseL'intégration continue avec Bitrise
L'intégration continue avec Bitrise
 
Make Acccessibility Great Again
Make Acccessibility Great AgainMake Acccessibility Great Again
Make Acccessibility Great Again
 
Super combinators
Super combinatorsSuper combinators
Super combinators
 
Tout savoir pour devenir Freelance
Tout savoir pour devenir FreelanceTout savoir pour devenir Freelance
Tout savoir pour devenir Freelance
 
Design like a developer
Design like a developerDesign like a developer
Design like a developer
 
Cocoaheads
CocoaheadsCocoaheads
Cocoaheads
 
Quoi de neuf dans iOS 10.3
Quoi de neuf dans iOS 10.3Quoi de neuf dans iOS 10.3
Quoi de neuf dans iOS 10.3
 
CONTINUOUS DELIVERY WITH FASTLANE
CONTINUOUS DELIVERY WITH FASTLANECONTINUOUS DELIVERY WITH FASTLANE
CONTINUOUS DELIVERY WITH FASTLANE
 
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
 

Similar to Cocoa heads 09112017

Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jscacois
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestPavan Chitumalla
 
C++aptitude questions and answers
C++aptitude questions and answersC++aptitude questions and answers
C++aptitude questions and answerssheibansari
 
Object oriented programming system with C++
Object oriented programming system with C++Object oriented programming system with C++
Object oriented programming system with C++msharshitha03s
 
Inline function
Inline functionInline function
Inline functionTech_MX
 
掀起 Swift 的面紗
掀起 Swift 的面紗掀起 Swift 的面紗
掀起 Swift 的面紗Pofat Tseng
 
CPP-overviews notes variable data types notes
CPP-overviews notes variable data types notesCPP-overviews notes variable data types notes
CPP-overviews notes variable data types notesSukhpreetSingh519414
 
Designing REST API automation tests in Kotlin
Designing REST API automation tests in KotlinDesigning REST API automation tests in Kotlin
Designing REST API automation tests in KotlinDmitriy Sobko
 
Our challenge for Bulkload reliability improvement
Our challenge for Bulkload reliability  improvementOur challenge for Bulkload reliability  improvement
Our challenge for Bulkload reliability improvementSatoshi Akama
 
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docxeugeniadean34240
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)jeffz
 
C++ Interview Question And Answer
C++ Interview Question And AnswerC++ Interview Question And Answer
C++ Interview Question And AnswerJagan Mohan Bishoyi
 
C++ questions And Answer
C++ questions And AnswerC++ questions And Answer
C++ questions And Answerlavparmar007
 
cppt-170218053903 (1).pptx
cppt-170218053903 (1).pptxcppt-170218053903 (1).pptx
cppt-170218053903 (1).pptxWatchDog13
 
Currying and Partial Function Application (PFA)
Currying and Partial Function Application (PFA)Currying and Partial Function Application (PFA)
Currying and Partial Function Application (PFA)Dhaval Dalal
 
C optimization notes
C optimization notesC optimization notes
C optimization notesFyaz Ghaffar
 

Similar to Cocoa heads 09112017 (20)

Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.js
 
CGI.ppt
CGI.pptCGI.ppt
CGI.ppt
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
C++aptitude questions and answers
C++aptitude questions and answersC++aptitude questions and answers
C++aptitude questions and answers
 
Object oriented programming system with C++
Object oriented programming system with C++Object oriented programming system with C++
Object oriented programming system with C++
 
Inline function
Inline functionInline function
Inline function
 
Blazing Fast Windows 8 Apps using Visual C++
Blazing Fast Windows 8 Apps using Visual C++Blazing Fast Windows 8 Apps using Visual C++
Blazing Fast Windows 8 Apps using Visual C++
 
Lecture2.ppt
Lecture2.pptLecture2.ppt
Lecture2.ppt
 
掀起 Swift 的面紗
掀起 Swift 的面紗掀起 Swift 的面紗
掀起 Swift 的面紗
 
CPP-overviews notes variable data types notes
CPP-overviews notes variable data types notesCPP-overviews notes variable data types notes
CPP-overviews notes variable data types notes
 
Designing REST API automation tests in Kotlin
Designing REST API automation tests in KotlinDesigning REST API automation tests in Kotlin
Designing REST API automation tests in Kotlin
 
Our challenge for Bulkload reliability improvement
Our challenge for Bulkload reliability  improvementOur challenge for Bulkload reliability  improvement
Our challenge for Bulkload reliability improvement
 
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
 
C++ Interview Question And Answer
C++ Interview Question And AnswerC++ Interview Question And Answer
C++ Interview Question And Answer
 
C++ questions And Answer
C++ questions And AnswerC++ questions And Answer
C++ questions And Answer
 
cppt-170218053903 (1).pptx
cppt-170218053903 (1).pptxcppt-170218053903 (1).pptx
cppt-170218053903 (1).pptx
 
Currying and Partial Function Application (PFA)
Currying and Partial Function Application (PFA)Currying and Partial Function Application (PFA)
Currying and Partial Function Application (PFA)
 
C optimization notes
C optimization notesC optimization notes
C optimization notes
 

More from Vincent Pradeilles

The underestimated power of KeyPaths
The underestimated power of KeyPathsThe underestimated power of KeyPaths
The underestimated power of KeyPathsVincent Pradeilles
 
Solving callback hell with good old function composition
Solving callback hell with good old function compositionSolving callback hell with good old function composition
Solving callback hell with good old function compositionVincent Pradeilles
 
Taking the boilerplate out of your tests with Sourcery
Taking the boilerplate out of your tests with SourceryTaking the boilerplate out of your tests with Sourcery
Taking the boilerplate out of your tests with SourceryVincent Pradeilles
 
How to build a debug view almost for free
How to build a debug view almost for freeHow to build a debug view almost for free
How to build a debug view almost for freeVincent Pradeilles
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testingVincent Pradeilles
 
Implementing pseudo-keywords through Functional Programing
Implementing pseudo-keywords through Functional ProgramingImplementing pseudo-keywords through Functional Programing
Implementing pseudo-keywords through Functional ProgramingVincent Pradeilles
 
Property Wrappers or how Swift decided to become Java
Property Wrappers or how Swift decided to become JavaProperty Wrappers or how Swift decided to become Java
Property Wrappers or how Swift decided to become JavaVincent Pradeilles
 

More from Vincent Pradeilles (8)

On-Boarding New Engineers
On-Boarding New EngineersOn-Boarding New Engineers
On-Boarding New Engineers
 
The underestimated power of KeyPaths
The underestimated power of KeyPathsThe underestimated power of KeyPaths
The underestimated power of KeyPaths
 
Solving callback hell with good old function composition
Solving callback hell with good old function compositionSolving callback hell with good old function composition
Solving callback hell with good old function composition
 
Taking the boilerplate out of your tests with Sourcery
Taking the boilerplate out of your tests with SourceryTaking the boilerplate out of your tests with Sourcery
Taking the boilerplate out of your tests with Sourcery
 
How to build a debug view almost for free
How to build a debug view almost for freeHow to build a debug view almost for free
How to build a debug view almost for free
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
 
Implementing pseudo-keywords through Functional Programing
Implementing pseudo-keywords through Functional ProgramingImplementing pseudo-keywords through Functional Programing
Implementing pseudo-keywords through Functional Programing
 
Property Wrappers or how Swift decided to become Java
Property Wrappers or how Swift decided to become JavaProperty Wrappers or how Swift decided to become Java
Property Wrappers or how Swift decided to become Java
 

Recently uploaded

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfryanfarris8
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024Mind IT Systems
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 

Recently uploaded (20)

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 

Cocoa heads 09112017

  • 2. From async to Rx, with little to no work
  • 4. Swift Quick recap on how functions are typed: // a function that takes an Int and returns Void let f: (Int) -> Void // a function that takes an Int and returns a function that takes a String and returns Void let g: (Int) -> (String) -> Void g(2)("Foo") // and so on… let h: (T) -> (U) -> (V) -> W
  • 6. Completion Handlers Completion handlers are an easy way to pass data asynchronously // a function that takes a completion handler func request(arg1: String, arg2: Int, completionHandler: @escaping (String) -> Void) // and how it is actually called request(arg1: "Foo", arg2: 0, completionHandler: { result in // do something with result })
  • 7. Completion Handlers This pattern is great, until you need to chain calls. When you do, it leads to nested callbacks, which are hard to read and reason about. This situation is often known as « callback hell ».
  • 8. Rx
  • 9. Rx Rx is a library that allows to write asynchronous code through the use of Observables. // same function, written using RxSwift func request(arg1: String, arg2: Int) -> Observable<String> // and you use it like this request("Foo", 42).subscribe(onNext: { result in // do something with result })
  • 10. Rx makes it easier to work with asynchronous code, so what about converting legacy or vendor API that uses completion handlers to new API that return Observables?
  • 11. We can try doing it by hand: func observableRequest(arg1: String, arg2: Int) -> Observable<String> { return Observable.create { (observer) -> Disposable in request(arg1: arg1, arg2: arg2, completionHandler: { result in observer.onNext(result) observer.onCompleted() }) return Disposables.create() } }
  • 12. Requires a lot of boiler plate & duplicated code 😞
  • 14. Functional programming Currying is a fundamental primitive of functional programming. It allows us to mangle with a function signature. // this is how you call a standard function add(arg1: 2, arg2: 3) // returns 5 // this is how you call a curried function let curriedAdd = curry(add(arg1:arg2:)) curriedAdd(2)(3) // returns 5
  • 15. How to implement curry Easier than it seems: func curry<A, B, C>(_ function: @escaping (A, B) -> C) -> (A) -> (B) -> C { return { (a: A) -> (B) -> C in { (b: B) -> C in function(a, b) } } } Basically, we wrap the function in a succession of lambdas that will each receive one of the argument before finally calling the wrapped function.
  • 16. Putting the pieces together
  • 17. Base case func fromAsync(_ asyncRequest: @escaping ((Element) -> Void) -> Void) -> Observable<Element> { return Observable.create({ (o) -> Disposable in asyncRequest({ (result) in o.onNext(result) o.onCompleted() }) return Disposables.create() }) }
  • 18. Recursion func fromAsync<T>(_ asyncRequest: @escaping (T, (Element) -> Void) -> Void) -> (T) -> Observable<Element> { return { (a: T) in Observable.fromAsync(curry(asyncRequest)(a)) } } func fromAsync<T, U>(_ asyncRequest: @escaping (T, U, (Element) -> Void) -> Void) -> (T, U) -> Observable<Element> { return { (a: T, b: U) in Observable.fromAsync(curry(asyncRequest)(a)(b)) } }
  • 19. How to use it // let’s bridge this function func request(arg1: String, arg2: Int, completionHandler: @escaping (String) -> Void) fromAsync(request(arg1:arg2:completionHandler:))("Foo", 3) .subscribe(onNext: { (result) in // do something with result })
  • 20. Performances Nothing comes for free and this technique comes at some performance costs. Still, there’s nothing we can’t manage. • Currying function that takes many parameters (> 6) can take sometime to compile, due to generics and type inference. => The bridging code can be placed in a compiled dependency • Recursive approaches can reduce performances when applied to resource- demanding code. => Profile execution to identify what is running slow, and do the bridging manually (via boiler plate code) if needed.
  • 22. Currying in JS JavaScript exposes primitives that allow to manipulate more directly the arguments list, thus allowing for a real curry function. function curry( fn ) { var arity = fn.length; return (function resolver() { var memory = Array.prototype.slice.call( arguments ); return function() { var local = memory.slice(), next; Array.prototype.push.apply( local, arguments ); next = local.length >= arity ? fn : resolver; return next.apply( null, local ); }; }()); }
  • 23. Bonus
  • 24. Bonus #1 Async functions (regardless of pattern) are great for UI-based code… …but they’re a pain when it comes to units testing func async(_ completionHandler: @escaping (String) -> Void) { sleep(2) completionHandler("Foo") } assert(/* ??? */ == "Foo")
  • 25. Bonus #1 Good news is, Foundation has all the primitives required to convert async to sync: func sync() -> String { let dispatchGroup = DispatchGroup() var result: String? = nil dispatchGroup.enter() async { result = $0 dispatchGroup.leave() } dispatchGroup.wait() return result! } assert(sync() == "Foo") // 🎉
  • 26. Bonus #1 By factoring out the boiler plate code, we create a new base case for bridging: func toSync<E>(_ async: @escaping ( @escaping (E) -> Void) -> Void) -> () -> E { return { let dispatchGroup = DispatchGroup() var result: E? = nil dispatchGroup.enter() async { result = $0 dispatchGroup.leave() } dispatchGroup.wait() return result! } }
  • 27. Bonus #2 struct MaximumValidator { private let max: Int private let strict: Bool init(max: Int, strict: Bool) { self.max = max self.strict = strict } func validate(_ value: Int) -> Bool { if strict { return value < max } else { return value <= max } } }
  • 28. Bonus #2 By leveraging currying, we can store a much more relevant artifact to perform the validation: struct MaximumValidator { let validate: (_ max: Int) -> Bool init(max: Int, strict: Bool) { self.validate = strict ? { $0 < max } : { $0 <= max } } }
  • 29. Recap What can currying bring to your code ? • Bridge functions by operating on their signature • Build alternate version of a function more appropriate to a given context • Specialize functions by binding some parameters to constant values
  • 31. Thanks! • Detailed explanation: https://medium.com/@vin.pradeilles/from- async-api-to-rx-api-with-little-to-no-work-ba725b53a1e0 👏 • Use it in production: https://github.com/RxSwiftCommunity/ RxSwiftExt#fromasync
  • 32. 💪
  • 33. A pattern to easily enforce external data validation in Swift
  • 34. Real world situation let accountNumber: String = getAccountNumberFromUser() // .... some code if !isValidAccountNumber(accountNumber) { return } // .... some more code performBusinessLogic(with: accountNumber)
  • 35. Real world situation The validation is indeed performed… for now ⏳ But it is lost in a possibly big chunk of code, so: - It’s easy to break 🚨 - Hard to enforce in review 🤔 ➜ We need to figure out a tighter system
  • 37. Model-driven security Wrap data in business objects: struct AccountNumber { let number: String init?(untrustedAccountNumber: String) { guard isValidAccountNumber(untrustedAccountNumber) else { return nil } self.number = untrustedAccountNumber } }
  • 38. Model-driven security And allow business services to only read data from such objects: func performBusinessLogic(with accountNumber: AccountNumber) { // ... }
  • 39. That’s better, but not enough struct Transfer { let creditAccount: String let debitAccount: String let amount: Int init?(untrustedCreditAccount: String, untrustedDebitAccount: String, untrustedAmount: Int) { guard isValidAccountNumber(untrustedCreditAccount), isValidAccountNumber(untrustedCreditAccount), isValidAmount(untrustedAmount) else { return nil } self.creditAccount = untrustedCreditAccount self.debitAccount = untrustedDebitAccount self.amount = untrustedAmount } }
  • 40. That’s better, but not enough struct Transfer { let creditAccount: String let debitAccount: String let amount: Int init?(untrustedCreditAccount: String, untrustedDebitAccount: String, untrustedAmount: Int) { guard isValidAccountNumber(untrustedCreditAccount), isValidAccountNumber(untrustedCreditAccount), isValidAmount(untrustedAmount) else { return nil } self.creditAccount = untrustedCreditAccount self.debitAccount = untrustedDebitAccount self.amount = untrustedAmount } }
  • 41. That’s better, but not enough The untrusted value can still be accessed without passing the validation. That gives a lot of room for nasty bugs, especially in places where copy/paste tends to be heavily relied on.
  • 43. The Validator pattern public struct Untrusted<T> { fileprivate let value: T public init(_ value: T) { self.value = value } }
  • 44. The Validator pattern public struct Untrusted<T> { fileprivate let value: T public init(_ value: T) { self.value = value } } public protocol Validator { associatedtype T static func validation(value: T) -> Bool }
  • 45. The Validator pattern extension Validator { public static func validate(untrusted: Untrusted<T>) -> T? { if self.validation(value: untrusted.value) { return untrusted.value } else { return nil } } } We’re still in the same file!
  • 46. Let’s see it in action
  • 47. Let’s see it in action struct AccountNumberValidator: Validator { static func validation(value: String) -> Bool { return isValidAccountNumber(value) } }
  • 48. Let’s see it in action struct AccountNumberValidator: Validator { static func validation(value: String) -> Bool { return isValidAccountNumber(value) } } struct AccountNumber { let number: String init?(untrustedAccountNumber: Untrusted<String>) { guard let validAccountNumber = AccountNumberValidator.validate(untrusted: untrustedAccountNumber) else { return nil } self.number = validAccountNumber } }
  • 50. Finally, some coding guidelines Whenever external data is retrieved, it must be immediately stored in an Untrusted container => easy to enforce in code review ✅ Initializer of business objects can take as arguments either other business objects or Untrusted containers, never primitive types => easy to enforce in code review ✅ Business logic can only operate with business objects, never with primitive types => easy to enforce in code review ✅
  • 52. Thanks, again! • Detailed explanation: https://medium.com/@vin.pradeilles/a-pattern- to-easily-enforce-external-data-validation-in-swift-8bc1d5917bfd 👏 • For some more content about secure coding : https:// www.youtube.com/watch?v=oqd9bxy5Hvc (2016 GOTO conference)