UNDER THE GREAT PATRONAGE OF HIS MAJESTY THE KING MOHAMMED VI
SWIFT COOKING COURSE
MAKING A CAKE ... PATTERN
D. PLAINDOUX | DEVOXX MOROCCO
1
DEPENDENCY INJECTION WITH SWIFT
Calling a constructor and/or a setter
Container with registration capabilities
Classical and "agnostic" approach ...
2
DEPENDENCY INJECTION ALTERNATIVE?
Speci c design pattern applied
using the Swift language expressivness
3
 
type MySelf = Freelance & ComputerScientist
@dplaindoux
4
THE INGREDIENTS
5
QUICK LANGUAGE OVERVIEW
6
OBJET-ORIENTED PROGRAMMING LANGUAGE
Class
OO programming
Structure
OO & Immutability
Enumeration
OO & Patterns
Protocol
Speci cation
7
PROTOCOL
Speci cation: methods, values ...
Extensions
8
PROTOCOL SPECIFICATION
protocol User {
var name : String { get } // Variable Specification
}
protocol UserRepository {
func users() -> [User] // Methods specification
func search(byName name:String) -> User? // Returns an optional !
}
9
PROTOCOL EXTENSION
Looks like "default" methods in Java 8+ interfaces
extension UserRepository {
func search(byName name:String) -> User? {
return self.users().filter{ $0.name == name }.first // self ≡ Java this
}
}
10
PROTOCOL AND INHERITANCE
A priori ...
protocol Contact {
func send(message: String);
}
protocol User : Contact {
var name: String { get }
}
extension User {
func send(message: String) { ... }
}
11
PROTOCOL EXTENSION AND ... INHERITANCE ?
protocol Contact {
func send(message: String);
}
extension User : Contact {
func send(message: String) { ... }
}
Extension of protocol User cannot have an inheritance clause
12
EXTENSION AND INHERITANCE
Only available for Class, Struct and Enum
13
THE SELF TYPE
"Bounded Polymorphism for Extensible Objects"
14
self : Self
class Counter {
var value:Int
init(_ value:Int = 0) {
self.value = value
}
func increment() -> Self {
self.value += 1
return self // Mutable
}
}
Self is the type of the current instance i.e. self ...
15
A NEW ... Self
class Counter {
let value:Int
func increment() -> Self {
return type(of:self).init(self.value + 1) // Immutable
}
required init(_ value:Int = 0) {
self.value = value
}
}
  Looks like Perl 5+ object creation
16
PROTOCOL STRIKES BACK
Capability to constraint Self type
Inheritance vs. Composition
17
PROTOCOL IMPLEMENTATION AND SELF CONSTRAINTS
protocol Contact {
func send(message: String);
}
extension User where Self:Contact {
func send(message: String) {
print("Say (message) to (name)")
}
}
send de ned for a User when composed with a Contact
18
PROTOCOL USAGE AND SELF CONSTRAINTS
protocol Contact {
func send(message: String);
}
extension Contact where Self:User {
func send(message: String) {
print("Say (message) to (name)")
}
}
send de ned for a Contact when composed with a User
19
PROTOCOL AND MUTUAL COMPOSITION
Mutual Self constraints is allowed
when mutual inheritance is not possible!
20
⚗
THE CHEMISTRY
21
"SCALABLE COMPONENT ABSTRACTIONS"
Martin Odersky & Matthias Zenger
22
PRINCIPLE #1: ABSTRACT TYPE MEMBER
"Abstract type members provide a exible way to
abstract over concrete types of components."
23
NOTIONS OF ABSTRACTION
PARAMETERIZATION ABSTRACT MEMBERS
Method
Variable
Type
Constructor
24
PRINCIPLE #2: EXPLICIT SELF TYPE
"Self type annotations allow one to attach a
programmer-de ned type to self"
25
PRINCIPLE #3: MODULAR MIXIN COMPOSITION
"Modular mixin composition provides a exible way to
compose components and component types"
26
SCALABLE COMPONENT ABSTRACTIONS & SWIFT
USER REPOSITORY DESIGN ILLUSTRATED
27
SPECIFIC PROTOCOL
struct User : Equatable {
let name: String
static func == (lhs:User, rhs:User) -> Bool { return lhs.name == rhs.name }
}
protocol UserRepository {
func create(_ user: User) -> Self
func delete(_ user: User) -> Self
}
28
ABSTRACT TYPE MEMBER & SELF TYPE
protocol InMemoryRepository {
associatedtype Element
var elements : [Element] { get }
func create(_ e: Element) -> Self
func delete(_ e: Element) -> Self
init(_ elements:[Element]) // Constructor specification in Protocols
}
29
ABSTRACT TYPE MEMBER & UPPER BOUND
extension InMemoryRepository {
func create(_ e: Element) -> Self {
return type(of:self).init(self.elements + [e])
}
}
extension InMemoryRepository where Element:Equatable {
func delete(_ e: Element) -> Self {
return type(of:self).init(self.elements.filter{ $0 != e })
}
}
30
ABSTRACT TYPE MEMBER & UPPER BOUND
extension InMemoryRepository {
func create(_ e: Element) -> Self {
return ...
}
}
extension InMemoryRepository when Element:Equatable {
func delete(_ e: Element) -> Self {
return ...
}
}
31
SPECIFIC PROTOCOL & SELF TYPE CONSTRAINT
extension UserRepository
where Self:InMemoryRepository
{
typealias Element = User
}
32
STRUCTURE & MODULAR MIXIN COMPOSITION
struct ConcreteUserRepository : UserRepository, InMemoryRepository {
let elements : [User]
init(_ elements:[User]) { self.elements = elements }
}
let r = ConcreteUserRepository([]).create(User(name:"Alice"))
.delete(User(name:"Alice"))
33
THE CAKE PATTERN
Alternative to Dependency Injection?
Not only!
34
THE CAKE PATTERN
Design Pattern based on
Abstrat Type Member
Modular Mixin Composition
Explicit Self Type
35
THE CAKE PATTERN ANATOMY
Service
Component
Application
Domains, API and SPI
Services wrapper
Components Assembly
"Standardized" boilerplate for application design
36
THE CAKE PATTERN PHYSIOLOGY
SERVICES DEFINITION AND IMPLEMENTATION
37
SERVICES DEFINITION
struct User {
let name: String
let password: String
}
protocol UserRepository {
func find(name: String) -> User?
}
protocol UserService {
func authenticate(name: String, password: String) -> Bool
}
38
A STATIC REPOSITORY SERVICE IMPLEMENTATION
struct StaticUserRepository : UserRepository {
let users = [ User(name:"Alice", password:"Wonderland") ]
func find(name: String) -> User? {
return self.users.filter{ $0.name == name }.first
}
}
39
A DEFAULT USER SERVICE IMPLEMENTATION
struct DefaultUserService : UserService {
let userRepository : UserRepository
func authenticate(name: String, password: String) -> Bool {
return self.userRepository.find(name: name)
.map{ $0.password == password } ?? false
}
}
40
QUICK SERVICE OVERVIEW
41
THE CAKE PATTERN PHYSIOLOGY
COMPONENTS DEFINITION
42
USER REPOSITORY COMPONENT
protocol UserRepositoryComponent {
static var userRepository : UserRepository { get }
static func createUserRepository() -> UserRepository
}
extension UserRepositoryComponent {
static var userRepository : UserRepository {
return self.createUserRepository()
}
}
Simple service wrapper with abstract creator
43
USER SERVICE COMPONENT
protocol UserServiceComponent {
static var userService : UserService { get }
static func createUserService() -> UserService
}
extension UserServiceComponent {
static var userService : UserService {
return self.createUserService()
}
}
Same wrapper ! Not real DRY
44
QUICK BASIC COMPONENTS OVERVIEW
45
STATIC REPOSITORY COMPONENT
protocol StaticUserRepositoryComponent : UserRepositoryComponent {}
extension StaticUserRepositoryComponent {
static func createUserRepository() -> UserRepository {
return StaticUserRepository()
}
}
46
DEFAULT USER SERVICE COMPONENT
protocol DefaultUserServiceComponent : UserServiceComponent {}
extension DefaultUserServiceComponent where Self:UserRepositoryComponent {
static func createUserService() -> UserService {
return DefaultUserService(userRepository: self.userRepository)
}
}
Self constraint used to retrieve the user repository
47
QUICK COMPONENTS OVERVIEW
48
QUICK COMPONENTS OVERVIEW
49
THE CAKE PATTERN PHYSIOLOGY
APPLICATION DEFINITION
50
MIXING COMPONENTS
struct Application: StaticUserRepositoryComponent,DefaultUserServiceComponent {
// Static variables userRepository and userService
// implicitely setup via variables initialization
}
Application.userService.authenticate(name:"Alice", password:"Wonderland")
51
REVISITING THE RECIPE
52
PROTOCOL SELF CONSTRAINT
The Twilight Zone
53
BASIC PROTOCOL DEFINITION
protocol A { func a() -> String }
extension A { func a() -> String { return "a" } }
protocol B { func b() -> String }
extension B { func b() -> String { return "b" } }
protocol C { func c() -> String }
extension C { func c() -> String { return "c" } }
54
SELF CONSTRAINED EXTENSIONS
extension C where Self:A {
func c() -> String { return "c with (a())" }
}
extension C where Self:B {
func c() -> String { return "c with (b())" }
}
extension C where Self:A&B {
func c() -> String { return "c with (a()) and (b())" }
}
55
CONSTRAINT BASED COMPOSITIONS
class DefaultC : C { func display() { print(c()) } }
DefaultC().display() // prints "c"
class DefaultAC : A, C { func display() { print(c()) } }
DefaultAC().display() // prints "c with a"
class DefaultBC : B, C { func display() { print(c()) } }
DefaultBC().display() // prints "c with b"
class DefaultABC : A, B, C { func display() { print(c()) } }
DefaultABC().display() // prints "c with a and b"
56
SELF CONSTRAINT AND PROTOCOL
Constraint based programming style i.e.
behaviors aggregation driven by types composition
57
REVISITING THE CAKE PATTERN
MIMIC SPRING "AUTOWIRED" ANNOTATION
58
USER REPOSITORY COMPONENT
protocol Autowired {}
extension UserRepositoryComponent where Self:Autowired {
static var userRepository : UserRepository {
return self.createUserRepository()
}
}
extension UserServiceComponent where Self:Autowired {
static var userService : UserService {
return self.createUserService()
}
}
59
MIXING COMPONENTS
struct Application: StaticUserRepositoryComponent,DefaultUserServiceComponent {
static let userRepository = Application.createUserRepository()
static let userService = Application.createUserService()
}
struct Application: StaticUserRepositoryComponent,DefaultUserServiceComponent,
Autowired {
// Static variables implicitly linked
}
60
PROTOCOL ORIENTED PROGRAMMING
Programming style
Protocol Based Design
Modular Mixin Composition
61
PROTOCOL ORIENTED PROGRAMMING PHILOSOPHY
"Replace a class hierarchy with
a protocol-oriented solution"
62
REVISITING THE CAKE PATTERN
PROTOCOL ORIENTED PROGRAMMING APPLIED
63
A STATIC REPOSITORY SERVICE PROTOTYPE
protocol StaticUserRepository : UserRepository {}
extension StaticUserRepository {
var users : [User] {
return [ User(name: "Alice", password: "Wonderland") ]
}
func find(name: String ) -> User? {
return self.users.filter{ $0.name == name }.first
}
}
64
A DEFAULT USER SERVICE PROTOCOL
protocol DefaultUserService : UserService {
var userRepository : UserRepository { get }
}
extension DefaultUserService {
func authenticate(name: String, password: String) -> Bool {
return userRepository.find(name:name)
.map{ $0.password == password }
?? false
}
}
65
STATIC REPOSITORY COMPONENT
struct StaticUserRepositoryStruct : StaticUserRepository {}
protocol StaticUserRepositoryComponent : UserRepositoryComponent {}
extension StaticUserRepositoryComponent {
static func createUserRepository() -> UserRepository {
return StaticUserRepositoryStruct()
}
}
66
DEFAULT USER SERVICE COMPONENT
struct DefaultUserServiceStruct : DefaultUserService {
let userRepository : UserRepository
}
protocol DefaultUserServiceComponent : UserServiceComponent {}
extension DefaultUserServiceComponent where Self:UserRepositoryComponent {
static func createUserService() -> UserService {
return DefaultUserServiceStruct(userRepository: self.userRepository)
}
}
67
ABSTRACTION FIRST PROGRAMMING STYLE
"Cake Pattern: The Bakery from the Black Lagoon"
Daniel Spiewak
68
SOME REFERENCES
Odersky & Zenger - Scalable component abstractions
Jonas Boner - Cake Pattern blog post
D. Spiewak - Cake Pattern conference talk
Protocol Oriented Programming and
Cake pattern by raywenderlich.com
69
QUESTIONS ?
70

Swift cooking course making a cake ... pattern

  • 1.
    UNDER THE GREATPATRONAGE OF HIS MAJESTY THE KING MOHAMMED VI SWIFT COOKING COURSE MAKING A CAKE ... PATTERN D. PLAINDOUX | DEVOXX MOROCCO 1
  • 2.
    DEPENDENCY INJECTION WITHSWIFT Calling a constructor and/or a setter Container with registration capabilities Classical and "agnostic" approach ... 2
  • 3.
    DEPENDENCY INJECTION ALTERNATIVE? Specic design pattern applied using the Swift language expressivness 3
  • 4.
      type MySelf =Freelance & ComputerScientist @dplaindoux 4
  • 5.
  • 6.
  • 7.
    OBJET-ORIENTED PROGRAMMING LANGUAGE Class OOprogramming Structure OO & Immutability Enumeration OO & Patterns Protocol Speci cation 7
  • 8.
    PROTOCOL Speci cation: methods,values ... Extensions 8
  • 9.
    PROTOCOL SPECIFICATION protocol User{ var name : String { get } // Variable Specification } protocol UserRepository { func users() -> [User] // Methods specification func search(byName name:String) -> User? // Returns an optional ! } 9
  • 10.
    PROTOCOL EXTENSION Looks like"default" methods in Java 8+ interfaces extension UserRepository { func search(byName name:String) -> User? { return self.users().filter{ $0.name == name }.first // self ≡ Java this } } 10
  • 11.
    PROTOCOL AND INHERITANCE Apriori ... protocol Contact { func send(message: String); } protocol User : Contact { var name: String { get } } extension User { func send(message: String) { ... } } 11
  • 12.
    PROTOCOL EXTENSION AND... INHERITANCE ? protocol Contact { func send(message: String); } extension User : Contact { func send(message: String) { ... } } Extension of protocol User cannot have an inheritance clause 12
  • 13.
    EXTENSION AND INHERITANCE Onlyavailable for Class, Struct and Enum 13
  • 14.
    THE SELF TYPE "BoundedPolymorphism for Extensible Objects" 14
  • 15.
    self : Self classCounter { var value:Int init(_ value:Int = 0) { self.value = value } func increment() -> Self { self.value += 1 return self // Mutable } } Self is the type of the current instance i.e. self ... 15
  • 16.
    A NEW ...Self class Counter { let value:Int func increment() -> Self { return type(of:self).init(self.value + 1) // Immutable } required init(_ value:Int = 0) { self.value = value } }   Looks like Perl 5+ object creation 16
  • 17.
    PROTOCOL STRIKES BACK Capabilityto constraint Self type Inheritance vs. Composition 17
  • 18.
    PROTOCOL IMPLEMENTATION ANDSELF CONSTRAINTS protocol Contact { func send(message: String); } extension User where Self:Contact { func send(message: String) { print("Say (message) to (name)") } } send de ned for a User when composed with a Contact 18
  • 19.
    PROTOCOL USAGE ANDSELF CONSTRAINTS protocol Contact { func send(message: String); } extension Contact where Self:User { func send(message: String) { print("Say (message) to (name)") } } send de ned for a Contact when composed with a User 19
  • 20.
    PROTOCOL AND MUTUALCOMPOSITION Mutual Self constraints is allowed when mutual inheritance is not possible! 20
  • 21.
  • 22.
    "SCALABLE COMPONENT ABSTRACTIONS" MartinOdersky & Matthias Zenger 22
  • 23.
    PRINCIPLE #1: ABSTRACTTYPE MEMBER "Abstract type members provide a exible way to abstract over concrete types of components." 23
  • 24.
    NOTIONS OF ABSTRACTION PARAMETERIZATIONABSTRACT MEMBERS Method Variable Type Constructor 24
  • 25.
    PRINCIPLE #2: EXPLICITSELF TYPE "Self type annotations allow one to attach a programmer-de ned type to self" 25
  • 26.
    PRINCIPLE #3: MODULARMIXIN COMPOSITION "Modular mixin composition provides a exible way to compose components and component types" 26
  • 27.
    SCALABLE COMPONENT ABSTRACTIONS& SWIFT USER REPOSITORY DESIGN ILLUSTRATED 27
  • 28.
    SPECIFIC PROTOCOL struct User: Equatable { let name: String static func == (lhs:User, rhs:User) -> Bool { return lhs.name == rhs.name } } protocol UserRepository { func create(_ user: User) -> Self func delete(_ user: User) -> Self } 28
  • 29.
    ABSTRACT TYPE MEMBER& SELF TYPE protocol InMemoryRepository { associatedtype Element var elements : [Element] { get } func create(_ e: Element) -> Self func delete(_ e: Element) -> Self init(_ elements:[Element]) // Constructor specification in Protocols } 29
  • 30.
    ABSTRACT TYPE MEMBER& UPPER BOUND extension InMemoryRepository { func create(_ e: Element) -> Self { return type(of:self).init(self.elements + [e]) } } extension InMemoryRepository where Element:Equatable { func delete(_ e: Element) -> Self { return type(of:self).init(self.elements.filter{ $0 != e }) } } 30
  • 31.
    ABSTRACT TYPE MEMBER& UPPER BOUND extension InMemoryRepository { func create(_ e: Element) -> Self { return ... } } extension InMemoryRepository when Element:Equatable { func delete(_ e: Element) -> Self { return ... } } 31
  • 32.
    SPECIFIC PROTOCOL &SELF TYPE CONSTRAINT extension UserRepository where Self:InMemoryRepository { typealias Element = User } 32
  • 33.
    STRUCTURE & MODULARMIXIN COMPOSITION struct ConcreteUserRepository : UserRepository, InMemoryRepository { let elements : [User] init(_ elements:[User]) { self.elements = elements } } let r = ConcreteUserRepository([]).create(User(name:"Alice")) .delete(User(name:"Alice")) 33
  • 34.
    THE CAKE PATTERN Alternativeto Dependency Injection? Not only! 34
  • 35.
    THE CAKE PATTERN DesignPattern based on Abstrat Type Member Modular Mixin Composition Explicit Self Type 35
  • 36.
    THE CAKE PATTERNANATOMY Service Component Application Domains, API and SPI Services wrapper Components Assembly "Standardized" boilerplate for application design 36
  • 37.
    THE CAKE PATTERNPHYSIOLOGY SERVICES DEFINITION AND IMPLEMENTATION 37
  • 38.
    SERVICES DEFINITION struct User{ let name: String let password: String } protocol UserRepository { func find(name: String) -> User? } protocol UserService { func authenticate(name: String, password: String) -> Bool } 38
  • 39.
    A STATIC REPOSITORYSERVICE IMPLEMENTATION struct StaticUserRepository : UserRepository { let users = [ User(name:"Alice", password:"Wonderland") ] func find(name: String) -> User? { return self.users.filter{ $0.name == name }.first } } 39
  • 40.
    A DEFAULT USERSERVICE IMPLEMENTATION struct DefaultUserService : UserService { let userRepository : UserRepository func authenticate(name: String, password: String) -> Bool { return self.userRepository.find(name: name) .map{ $0.password == password } ?? false } } 40
  • 41.
  • 42.
    THE CAKE PATTERNPHYSIOLOGY COMPONENTS DEFINITION 42
  • 43.
    USER REPOSITORY COMPONENT protocolUserRepositoryComponent { static var userRepository : UserRepository { get } static func createUserRepository() -> UserRepository } extension UserRepositoryComponent { static var userRepository : UserRepository { return self.createUserRepository() } } Simple service wrapper with abstract creator 43
  • 44.
    USER SERVICE COMPONENT protocolUserServiceComponent { static var userService : UserService { get } static func createUserService() -> UserService } extension UserServiceComponent { static var userService : UserService { return self.createUserService() } } Same wrapper ! Not real DRY 44
  • 45.
  • 46.
    STATIC REPOSITORY COMPONENT protocolStaticUserRepositoryComponent : UserRepositoryComponent {} extension StaticUserRepositoryComponent { static func createUserRepository() -> UserRepository { return StaticUserRepository() } } 46
  • 47.
    DEFAULT USER SERVICECOMPONENT protocol DefaultUserServiceComponent : UserServiceComponent {} extension DefaultUserServiceComponent where Self:UserRepositoryComponent { static func createUserService() -> UserService { return DefaultUserService(userRepository: self.userRepository) } } Self constraint used to retrieve the user repository 47
  • 48.
  • 49.
  • 50.
    THE CAKE PATTERNPHYSIOLOGY APPLICATION DEFINITION 50
  • 51.
    MIXING COMPONENTS struct Application:StaticUserRepositoryComponent,DefaultUserServiceComponent { // Static variables userRepository and userService // implicitely setup via variables initialization } Application.userService.authenticate(name:"Alice", password:"Wonderland") 51
  • 52.
  • 53.
  • 54.
    BASIC PROTOCOL DEFINITION protocolA { func a() -> String } extension A { func a() -> String { return "a" } } protocol B { func b() -> String } extension B { func b() -> String { return "b" } } protocol C { func c() -> String } extension C { func c() -> String { return "c" } } 54
  • 55.
    SELF CONSTRAINED EXTENSIONS extensionC where Self:A { func c() -> String { return "c with (a())" } } extension C where Self:B { func c() -> String { return "c with (b())" } } extension C where Self:A&B { func c() -> String { return "c with (a()) and (b())" } } 55
  • 56.
    CONSTRAINT BASED COMPOSITIONS classDefaultC : C { func display() { print(c()) } } DefaultC().display() // prints "c" class DefaultAC : A, C { func display() { print(c()) } } DefaultAC().display() // prints "c with a" class DefaultBC : B, C { func display() { print(c()) } } DefaultBC().display() // prints "c with b" class DefaultABC : A, B, C { func display() { print(c()) } } DefaultABC().display() // prints "c with a and b" 56
  • 57.
    SELF CONSTRAINT ANDPROTOCOL Constraint based programming style i.e. behaviors aggregation driven by types composition 57
  • 58.
    REVISITING THE CAKEPATTERN MIMIC SPRING "AUTOWIRED" ANNOTATION 58
  • 59.
    USER REPOSITORY COMPONENT protocolAutowired {} extension UserRepositoryComponent where Self:Autowired { static var userRepository : UserRepository { return self.createUserRepository() } } extension UserServiceComponent where Self:Autowired { static var userService : UserService { return self.createUserService() } } 59
  • 60.
    MIXING COMPONENTS struct Application:StaticUserRepositoryComponent,DefaultUserServiceComponent { static let userRepository = Application.createUserRepository() static let userService = Application.createUserService() } struct Application: StaticUserRepositoryComponent,DefaultUserServiceComponent, Autowired { // Static variables implicitly linked } 60
  • 61.
    PROTOCOL ORIENTED PROGRAMMING Programmingstyle Protocol Based Design Modular Mixin Composition 61
  • 62.
    PROTOCOL ORIENTED PROGRAMMINGPHILOSOPHY "Replace a class hierarchy with a protocol-oriented solution" 62
  • 63.
    REVISITING THE CAKEPATTERN PROTOCOL ORIENTED PROGRAMMING APPLIED 63
  • 64.
    A STATIC REPOSITORYSERVICE PROTOTYPE protocol StaticUserRepository : UserRepository {} extension StaticUserRepository { var users : [User] { return [ User(name: "Alice", password: "Wonderland") ] } func find(name: String ) -> User? { return self.users.filter{ $0.name == name }.first } } 64
  • 65.
    A DEFAULT USERSERVICE PROTOCOL protocol DefaultUserService : UserService { var userRepository : UserRepository { get } } extension DefaultUserService { func authenticate(name: String, password: String) -> Bool { return userRepository.find(name:name) .map{ $0.password == password } ?? false } } 65
  • 66.
    STATIC REPOSITORY COMPONENT structStaticUserRepositoryStruct : StaticUserRepository {} protocol StaticUserRepositoryComponent : UserRepositoryComponent {} extension StaticUserRepositoryComponent { static func createUserRepository() -> UserRepository { return StaticUserRepositoryStruct() } } 66
  • 67.
    DEFAULT USER SERVICECOMPONENT struct DefaultUserServiceStruct : DefaultUserService { let userRepository : UserRepository } protocol DefaultUserServiceComponent : UserServiceComponent {} extension DefaultUserServiceComponent where Self:UserRepositoryComponent { static func createUserService() -> UserService { return DefaultUserServiceStruct(userRepository: self.userRepository) } } 67
  • 68.
    ABSTRACTION FIRST PROGRAMMINGSTYLE "Cake Pattern: The Bakery from the Black Lagoon" Daniel Spiewak 68
  • 69.
    SOME REFERENCES Odersky &Zenger - Scalable component abstractions Jonas Boner - Cake Pattern blog post D. Spiewak - Cake Pattern conference talk Protocol Oriented Programming and Cake pattern by raywenderlich.com 69
  • 70.