Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Code Generators In Swift (Part 2)

Paul Taykalo
November 19, 2016

Code Generators In Swift (Part 2)

Talk about code generators in general, and what code generators we can and should use when we're working with ios projects

Paul Taykalo

November 19, 2016
Tweet

More Decks by Paul Taykalo

Other Decks in Programming

Transcript

  1. 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
  2. When should we write one? ✅ Structure is well defined

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

    ✅ Number of special cases is low ✅ Uniform structure Code Generators in Swift, #Cocoaheads, Minsk 15
  4. 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
  5. 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
  6. Flow time is limited. Simple operations should take small amount

    of time Code Generators in Swift, #Cocoaheads, Minsk 22
  7. But before that What so special in code generators for

    Swift? Code Generators in Swift, #Cocoaheads, Minsk 28
  8. 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
  9. Swagger • Source Language: DSL in YAML / JSON •

    Written In: Java • Generates: Everything http://swagger.io/ Code Generators in Swift, #Cocoaheads, Minsk 36
  10. Cuckoo • Source Language: Swift Code • Written in: Swift

    • Generates: Swift (Mocks) https://github.com/SwiftKit/ Cuckoo Code Generators in Swift, #Cocoaheads, Minsk 37
  11. 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
  12. 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
  13. 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
  14. 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
  15. SwiftGen Source: Xcode Files Written in : Swift Generates: Enums

    for resources https://github.com/AliSoftware/SwiftGen Code Generators in Swift, #Cocoaheads, Minsk 42
  16. 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
  17. 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
  18. 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
  19. 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
  20. 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
  21. Simple is better than easy • Simple is easier to

    support and understand Code Generators in Swift, #Cocoaheads, Minsk 55
  22. 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
  23. 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
  24. Check reality • Ask if this tool is really needed?

    • Ask other people too Code Generators in Swift, #Cocoaheads, Minsk 59
  25. For the future generations • Document • Open Source Code

    Generators in Swift, #Cocoaheads, Minsk 60
  26. 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
  27. Source type "dayOfWeek" spec { constraints("string") { enumeration 'sun', 'mon',

    'tue', 'wed', 'thu', 'fri', 'sat' } } Code Generators in Swift, #Cocoaheads, Minsk 63
  28. 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
  29. 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
  30. 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
  31. 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
  32. Random structures generation extension Shop: Random { static func random()

    -> Shop { return restrictedRandom() } } Code Generators in Swift, #Cocoaheads, Minsk 68
  33. 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
  34. Structures updates extension Shop { func updated( shopId: Optional<String> =

    nil, image: Optional<String> = nil, name: Optional<String> = nil ... ) -> Shop { return Shop( shopId:shopId ?? self.shopId, image:image ?? self.image, name:name ?? self.name ... ) } } Code Generators in Swift, #Cocoaheads, Minsk 70
  35. 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
  36. 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
  37. Sum up • There're always things to automate • Code

    generation is one of the multiple options Code Generators in Swift, #Cocoaheads, Minsk 75
  38. 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
  39. Code Generators in Swift by Paul Taykalo, Stanfy @TT_Kilew Code

    Generators in Swift, #Cocoaheads, Minsk 78