Slide 1

Slide 1 text

Code Generators in Swift by Paul Taykalo, Stanfy Code Generators in Swift, #Cocoaheads, Minsk 1

Slide 2

Slide 2 text

Code generation Code Generators in Swift, #Cocoaheads, Minsk 2

Slide 3

Slide 3 text

Code generation or Automatic Programming In computer science, the term automatic programming identifies a type of computer programming in which some mechanism generates a computer program to allow human programmers to write the code at a higher abstraction level — Wikipedia Code Generators in Swift, #Cocoaheads, Minsk 3

Slide 4

Slide 4 text

Generators in general Code Generators in Swift, #Cocoaheads, Minsk 4

Slide 5

Slide 5 text

Our main interest today * Code Generators in Swift, #Cocoaheads, Minsk 5

Slide 6

Slide 6 text

Our goals Code Generators in Swift, #Cocoaheads, Minsk 6

Slide 7

Slide 7 text

Write less code Code Generators in Swift, #Cocoaheads, Minsk 7

Slide 8

Slide 8 text

Automate Repetitive Operations Code Generators in Swift, #Cocoaheads, Minsk 8

Slide 9

Slide 9 text

Save time Make everyone happy Code Generators in Swift, #Cocoaheads, Minsk 9

Slide 10

Slide 10 text

Uniform structure Code Generators in Swift, #Cocoaheads, Minsk 10

Slide 11

Slide 11 text

Error Scalability Code Generators in Swift, #Cocoaheads, Minsk 11

Slide 12

Slide 12 text

Platform Scalability Code Generators in Swift, #Cocoaheads, Minsk 12

Slide 13

Slide 13 text

When should we write one? Code Generators in Swift, #Cocoaheads, Minsk 13

Slide 14

Slide 14 text

When should we write one? ✅ Structure is well defined Code Generators in Swift, #Cocoaheads, Minsk 14

Slide 15

Slide 15 text

When should we write one? ✅ Structure is well defined ✅ Number of special cases is low ✅ Uniform structure Code Generators in Swift, #Cocoaheads, Minsk 15

Slide 16

Slide 16 text

When should we write one? ✅ Structure is well defined ✅ Number of special cases is low ✅ Uniform structure ✅ One Layer of Abstraction Code Generators in Swift, #Cocoaheads, Minsk 16

Slide 17

Slide 17 text

When should we write one? ✅ Structure is well defined ✅ Number of special cases is low ✅ Uniform structure ✅ One Layer of Abstraction ✅ It's time efficient Code Generators in Swift, #Cocoaheads, Minsk 17

Slide 18

Slide 18 text

Time efficiency rule Code Generators in Swift, #Cocoaheads, Minsk 18

Slide 19

Slide 19 text

Time efficiency rule Code Generators in Swift, #Cocoaheads, Minsk 19

Slide 20

Slide 20 text

Time efficiency rule examples Code Generators in Swift, #Cocoaheads, Minsk 20

Slide 21

Slide 21 text

Time efficiency rule examples Code Generators in Swift, #Cocoaheads, Minsk 21

Slide 22

Slide 22 text

Flow time is limited. Simple operations should take small amount of time Code Generators in Swift, #Cocoaheads, Minsk 22

Slide 23

Slide 23 text

Code Generators in Swift, #Cocoaheads, Minsk 23

Slide 24

Slide 24 text

Source Code Generators in Swift, #Cocoaheads, Minsk 24

Slide 25

Slide 25 text

Generator Source DSL Code Generators in Swift, #Cocoaheads, Minsk 25

Slide 26

Slide 26 text

Generator Source Swift Code Code Generators in Swift, #Cocoaheads, Minsk 26

Slide 27

Slide 27 text

Let's back to swift Code Generators in Swift, #Cocoaheads, Minsk 27

Slide 28

Slide 28 text

But before that What so special in code generators for Swift? Code Generators in Swift, #Cocoaheads, Minsk 28

Slide 29

Slide 29 text

What so special in code generators for Swift? • No Runtime • Static Typing • No simple way to get types in runtime* • Hard to get metainformation at runtime* Code Generators in Swift, #Cocoaheads, Minsk 29

Slide 30

Slide 30 text

Examples Code Generators in Swift, #Cocoaheads, Minsk 30

Slide 31

Slide 31 text

Code Snippets Code Generators in Swift, #Cocoaheads, Minsk 31

Slide 32

Slide 32 text

Code Generators in Swift, #Cocoaheads, Minsk 32

Slide 33

Slide 33 text

Xcode File Templates Code Generators in Swift, #Cocoaheads, Minsk 33

Slide 34

Slide 34 text

Project Templates Code Generators in Swift, #Cocoaheads, Minsk 34

Slide 35

Slide 35 text

Bit more complex examples Code Generators in Swift, #Cocoaheads, Minsk 35

Slide 36

Slide 36 text

Swagger • Source Language: DSL in YAML / JSON • Written In: Java • Generates: Everything http://swagger.io/ Code Generators in Swift, #Cocoaheads, Minsk 36

Slide 37

Slide 37 text

Cuckoo • Source Language: Swift Code • Written in: Swift • Generates: Swift (Mocks) https://github.com/SwiftKit/ Cuckoo Code Generators in Swift, #Cocoaheads, Minsk 37

Slide 38

Slide 38 text

Cuckoo let mock = MockGreeter() stub(mock) { stub in when(stub.greetWithMessage("Hello world")).then { message in print(message) } } Code Generators in Swift, #Cocoaheads, Minsk 38

Slide 39

Slide 39 text

VIPER Module Generator • Source Language: String • Written in: Ruby • Generates: Swift, Objective-C https://github.com/teambox/ viper-module-generator Code Generators in Swift, #Cocoaheads, Minsk 39

Slide 40

Slide 40 text

Generamba • Source Language: Ruby (DSL) • Written in: Ruby • Generates: Swift, Objective-C, Xcode Project https://github.com/rambler-digital-solutions/ Generamba Code Generators in Swift, #Cocoaheads, Minsk 40

Slide 41

Slide 41 text

Protobuf Source: Protocol Buffers Language Written in: * Generates: Swift, Any Supported Language https://github.com/alexeyxo/protobuf-swift https://github.com/google/protobuf Code Generators in Swift, #Cocoaheads, Minsk 41

Slide 42

Slide 42 text

SwiftGen Source: Xcode Files Written in : Swift Generates: Enums for resources https://github.com/AliSoftware/SwiftGen Code Generators in Swift, #Cocoaheads, Minsk 42

Slide 43

Slide 43 text

SwiftGen // The Image type below is typealias'ed to UIImage on iOS and NSImage on OSX enum Asset: String { case Green_Apple = "Green-Apple" case Red_Apple = "Red apple" case _2_Pears = "2-pears" var image: Image { return Image(asset: self) } } extension Image { convenience init!(asset: Asset) { self.init(named: asset.rawValue) } } Code Generators in Swift, #Cocoaheads, Minsk 43

Slide 44

Slide 44 text

R Source: Xcode Project Files Written in : Swift Generates: Enums for resources https://github.com/mac-cain13/R.swift Code Generators in Swift, #Cocoaheads, Minsk 44

Slide 45

Slide 45 text

R Code Generators in Swift, #Cocoaheads, Minsk 45

Slide 46

Slide 46 text

Helium Source : DSL in Groovy Written in : JVM Languages Java/Kotlin/Groovy Generates: Java Library, API Client, Swift, Objective-C https://github.com/stanfy/ helium Code Generators in Swift, #Cocoaheads, Minsk 46

Slide 47

Slide 47 text

If you decided to create on Code Generators in Swift, #Cocoaheads, Minsk 47

Slide 48

Slide 48 text

Templates, DSL Code Generators in Swift, #Cocoaheads, Minsk 48

Slide 49

Slide 49 text

SourceKitten Code Generators in Swift, #Cocoaheads, Minsk 49

Slide 50

Slide 50 text

SourceKitten [{ "descriptionKey" : "advancedBy(n: Distance)", "associatedUSRs" : "s:FSi10advancedByFSiFSiSi ", "kind" : "source.lang.swift.decl.function.method.instance", "sourcetext" : "advancedBy(<#T##n: Distance##Distance#>)", "context" : "source.codecompletion.context.thisclass", "typeName" : "Int", "moduleName" : "Swift", "name" : "advancedBy(n: Distance)" }, Code Generators in Swift, #Cocoaheads, Minsk 50

Slide 51

Slide 51 text

SourceKitten sourcekitten structure --text "struct A { func b() {} } { "key.substructure" : [ { "key.kind" : "source.lang.swift.decl.struct", "key.offset" : 0, "key.nameoffset" : 7, "key.namelength" : 1, "key.bodyoffset" : 10, "key.bodylength" : 13, "key.length" : 24, "key.substructure" : [ ... } ], "key.offset" : 0, "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse", "key.length" : 24 } Code Generators in Swift, #Cocoaheads, Minsk 51

Slide 52

Slide 52 text

Tips and Tricks Code Generators in Swift, #Cocoaheads, Minsk 52

Slide 53

Slide 53 text

Don't go too deep Code Generators in Swift, #Cocoaheads, Minsk 53

Slide 54

Slide 54 text

Simple is better than easy Code Generators in Swift, #Cocoaheads, Minsk 54

Slide 55

Slide 55 text

Simple is better than easy • Simple is easier to support and understand Code Generators in Swift, #Cocoaheads, Minsk 55

Slide 56

Slide 56 text

Simple is better than easy • Simple is easier to support and understand • Easy one can be complex but easy to use Code Generators in Swift, #Cocoaheads, Minsk 56

Slide 57

Slide 57 text

Simple is better than easy • Simple is easier to support and understand • Easy one can be complex but easy to use • Use templates Code Generators in Swift, #Cocoaheads, Minsk 57

Slide 58

Slide 58 text

Check reality Code Generators in Swift, #Cocoaheads, Minsk 58

Slide 59

Slide 59 text

Check reality • Ask if this tool is really needed? • Ask other people too Code Generators in Swift, #Cocoaheads, Minsk 59

Slide 60

Slide 60 text

For the future generations • Document • Open Source Code Generators in Swift, #Cocoaheads, Minsk 60

Slide 61

Slide 61 text

Our results Code Generators in Swift, #Cocoaheads, Minsk 61

Slide 62

Slide 62 text

Source type 'Shop' message { shop_id 'string' image 'string' name 'string' description 'string' currency 'string' optional service_charge 'AdditionalCharges' optional payment_methods(type:'PaymentMethod') { sequence true required false } } Code Generators in Swift, #Cocoaheads, Minsk 62

Slide 63

Slide 63 text

Source type "dayOfWeek" spec { constraints("string") { enumeration 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' } } Code Generators in Swift, #Cocoaheads, Minsk 63

Slide 64

Slide 64 text

Entities generation public enum DayOfWeek: String { case Sun = "sun" case Mon = "mon" case Tue = "tue" case Wed = "wed" case Thu = "thu" case Fri = "fri" case Sat = "sat" } Code Generators in Swift, #Cocoaheads, Minsk 64

Slide 65

Slide 65 text

Entities generation public struct Shop { public let shopId: String public let image: String public let name: String public let description: String public let currency: String? public let serviceCharge: AdditionalCharges? public let paymentMethods: [PaymentMethod]? } Code Generators in Swift, #Cocoaheads, Minsk 65

Slide 66

Slide 66 text

Equatable // MARK: - Shop Equatable public func == (lhs: Shop, rhs: Shop) -> Bool { return lhs.shopId == rhs.shopId && lhs.image == rhs.image && lhs.name == rhs.name && lhs.description == rhs.description && lhs.currency == rhs.currency && lhs.serviceCharge == rhs.serviceCharge && lhs.paymentMethods == rhs.paymentMethods } Code Generators in Swift, #Cocoaheads, Minsk 66

Slide 67

Slide 67 text

Mappings generation extension DayOfWeek: Decodable {} extension Shop: Decodable { public static func decode(json: AnyObject) throws -> Shop { return try Shop( internalId: json =>? "internal_id" , shopId: json => "shop_id" , image: json => "image" , name: json => "name" , description: json => "description" , currency: json =>? "currency" , deliveryCharge: json =>? "delivery_charge" , paymentMethods: json =>? "payment_methods" ) } } Code Generators in Swift, #Cocoaheads, Minsk 67

Slide 68

Slide 68 text

Random structures generation extension Shop: Random { static func random() -> Shop { return restrictedRandom() } } Code Generators in Swift, #Cocoaheads, Minsk 68

Slide 69

Slide 69 text

Random structures generation extension Shop: Random { static func restrictedRandom( shopId: String = .random(), image: String = .random(), name: String = .random() ... ) -> Shop { return Shop( shopId: shopId, image: image, name: name ... ) } } Code Generators in Swift, #Cocoaheads, Minsk 69

Slide 70

Slide 70 text

Structures updates extension Shop { func updated( shopId: Optional = nil, image: Optional = nil, name: Optional = nil ... ) -> Shop { return Shop( shopId:shopId ?? self.shopId, image:image ?? self.image, name:name ?? self.name ... ) } } Code Generators in Swift, #Cocoaheads, Minsk 70

Slide 71

Slide 71 text

Generated code in action // Only shipId will be set up let validShop = Shop.restrictedRandom( shopId: "SE2016", currency: "UAH" ) // Everything will be copied but 'shopID' property let anotherShop = validShop.updated(shopId:"123") // If we want to set up nil value let notSavedYet = validShop.updated(internalId: Optional(nil)) let notSavedYet2 = validShop.updated(internalId: .Some(nil)) Code Generators in Swift, #Cocoaheads, Minsk 71

Slide 72

Slide 72 text

From one source type 'Shop' message { shop_id 'string' image 'string' name 'string' description 'string' currency 'string' optional service_charge 'AdditionalCharges' optional payment_methods(type:'PaymentMethod') { sequence true required false } } Code Generators in Swift, #Cocoaheads, Minsk 72

Slide 73

Slide 73 text

Sum up • Code generators are here Code Generators in Swift, #Cocoaheads, Minsk 73

Slide 74

Slide 74 text

Sum up • Engineering approach > Art Code Generators in Swift, #Cocoaheads, Minsk 74

Slide 75

Slide 75 text

Sum up • There're always things to automate • Code generation is one of the multiple options Code Generators in Swift, #Cocoaheads, Minsk 75

Slide 76

Slide 76 text

Sum up • Write your own if it worth it • Please don't write another one-time-complex generator • Document well Code Generators in Swift, #Cocoaheads, Minsk 76

Slide 77

Slide 77 text

Thank you Code Generators in Swift, #Cocoaheads, Minsk 77

Slide 78

Slide 78 text

Code Generators in Swift by Paul Taykalo, Stanfy @TT_Kilew Code Generators in Swift, #Cocoaheads, Minsk 78

Slide 79

Slide 79 text

The end Code Generators in Swift, #Cocoaheads, Minsk 79