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

Code generators in Swift

Paul Taykalo
September 04, 2016

Code generators in Swift

Review of existing Code Generators in Swift
Some useful tips of what you need to think of, if you want to create one

Paul Taykalo

September 04, 2016
Tweet

More Decks by Paul Taykalo

Other Decks in Programming

Transcript

  1. CODE GENERATORS IN SWIFT BY PAUL TAYKALO, STANFY 1 —

    Code Generators in Swift, #se2016
  2. 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 3 — Code Generators in Swift, #se2016
  3. SO DIFFERENT CODE GENERATORS > Snippets > GUI Tools >

    Wizards 4 — Code Generators in Swift, #se2016
  4. BUT BEFORE THAT WHY DO WE NEED CODE GENERATORS IN

    SWIFT? 7 — Code Generators in Swift, #se2016
  5. Mostly this is because that we can't get access to

    types or objects structure in runtime There are languages, where still have Runtime, but still want to generate code WHY DO WE NEED CODE GENERATORS IN SWIFT? > No Runtime > Static Typing > No simple way to get types in runtime* > Hard to get metainformation at runtime* 8 — Code Generators in Swift, #se2016
  6. What are our main goals when whe use Code Generators?

    OUR GOALS 9 — Code Generators in Swift, #se2016
  7. Human error rate Update is just regeneration Good copy-pasting machine

    ERROR SCALABILITY 13 — Code Generators in Swift, #se2016
  8. WHEN SHOULD WE WRITE ONE? ✅ Structure is well defined

    15 — Code Generators in Swift, #se2016
  9. WHEN SHOULD WE WRITE ONE? ✅ Structure is well defined

    ✅ Number of special cases is low ✅ Uniform structure 16 — Code Generators in Swift, #se2016
  10. WHEN SHOULD WE WRITE ONE? ✅ Structure is well defined

    ✅ Number of special cases is low ✅ Uniform structure ✅ One Layer of Abstraction 17 — Code Generators in Swift, #se2016
  11. 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 18 — Code Generators in Swift, #se2016
  12. In case if we create one This is actually simplified

    formula It's doesnt count that we get experience TIME EFFICIENCY RULE* 19 — Code Generators in Swift, #se2016
  13. It can be your own DSL in your own language

    Or DSL as valid structures in source language Dynamic languages like Ruby, Python, Groovy GENERATOR SOURCE DSL 23 — Code Generators in Swift, #se2016
  14. It can be tranformed by Regex Regex SourceKitten GENERATOR SOURCE

    SWIFT CODE 24 — Code Generators in Swift, #se2016
  15. SWAGGER > Source Language: DSL in YAML / JSON >

    Written In: Java > Generates: Everything http://swagger.io/ 32 — Code Generators in Swift, #se2016
  16. CUCKOO > Source Language: Swift Code > Written in: Swift

    > Generates: Swift (Mocks) https://github.com/SwiftKit/ Cuckoo 33 — Code Generators in Swift, #se2016
  17. CUCKOO let mock = MockGreeter() stub(mock) { stub in when(stub.greetWithMessage("Hello

    world")).then { message in print(message) } } 34 — Code Generators in Swift, #se2016
  18. VIPER MODULE GENERATOR > Source Language: String > Written in:

    Ruby > Generates: Swift, Objective-C https://github.com/teambox/ viper-module-generator 35 — Code Generators in Swift, #se2016
  19. PROTOBUF Source: Protocol Buffers Language Written in: * Generates: Swift,

    Any Supported Language https://github.com/alexeyxo/protobuf- swift https://github.com/google/protobuf 36 — Code Generators in Swift, #se2016
  20. SWIFTGEN Source: Xcode Files Written in : Swift Generates: Enums

    for resources https://github.com/AliSoftware/SwiftGen 37 — Code Generators in Swift, #se2016
  21. 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) } } 38 — Code Generators in Swift, #se2016
  22. R Source: Xcode Project Files Written in : Swift Generates:

    Enums for resources https://github.com/mac-cain13/R.swift 39 — Code Generators in Swift, #se2016
  23. 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 41 — Code Generators in Swift, #se2016
  24. 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)" }, 45 — Code Generators in Swift, #se2016
  25. 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 } 46 — Code Generators in Swift, #se2016
  26. TIPS AND TRICKS > Don't go too deep > Use

    template > Don't overdo > Check reality > Document > Open Source 48 — Code Generators in Swift, #se2016
  27. 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 } } 50 — Code Generators in Swift, #se2016
  28. SOURCE type "dayOfWeek" spec { constraints("string") { enumeration 'sun', 'mon',

    'tue', 'wed', 'thu', 'fri', 'sat' } } 51 — Code Generators in Swift, #se2016
  29. 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" } 52 — Code Generators in Swift, #se2016
  30. 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]? } 53 — Code Generators in Swift, #se2016
  31. 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 } 54 — Code Generators in Swift, #se2016
  32. 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" ) } } 55 — Code Generators in Swift, #se2016
  33. RANDOM STRUCTURES GENERATION extension Shop: Random { static func random()

    -> Shop { return restrictedRandom() } } 56 — Code Generators in Swift, #se2016
  34. 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 ... ) } } 57 — Code Generators in Swift, #se2016
  35. 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 ... ) } } 58 — Code Generators in Swift, #se2016
  36. 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)) 59 — Code Generators in Swift, #se2016
  37. 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 } } 60 — Code Generators in Swift, #se2016
  38. SUMMARIZE > There're always things to automate > Code generation

    is one of the multiple options 63 — Code Generators in Swift, #se2016
  39. SUMMARIZE > Write your own if it worth it >

    Please don't write another one-time-complex generator > Document well 64 — Code Generators in Swift, #se2016
  40. Which one to create? https://habrahabr.ru/post/141477/ The general idea of what

    will we be talking about here and today Generatros why do we need them Why genertaors? What other options can we have? What we're tryin to achive? How we can do that? Next steps The ide of the all programmers is to not writing code less code - is better But it doesn't mean that this means than you need to write less code in the final language Right? No matter how many real code will be generated - if you have original code - less - is better Reperetive operations We dont' want to perform repetetive opertins. It's really easy for a brain to perform repetetive tasks. Really. But it's also really boring, and really time consuming So in case if we can automate - we should Small task size | Big task size | Fast to automate | Takes long time to automate If it takes less time to automate... What other problems we have here? Repetetive tasks tend to have copy-paste errors. Yep. Let's say, that Programmer will make a stupid mistake once per 1K lines of code (removed and deleted) Few More Facts Generated code is easier to remove Example with tests book Other examples of transformations Code Generation as Transformation -> One Form -> map -> AnotherForm XML + XSLT - ... Xib + Compielr - UI SwiftCode + CLANGCompiler -> ARM instructions A Bit of History - we have an API - mapped to the JAva groovy + APi spec (Java + RetroFit) - then we need to use that api on both Android and Other systems - we also need to have API tests, since most of our subcontractors weren't doing testing right - so we decided to write "Spec" which will describe everything and we'll use it to generate clients - And original Spec was a THE END 67 — Code Generators in Swift, #se2016