Share
Embed
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
Transcript
67 slides
-
CODE GENERATORS IN SWIFT BY PAUL TAYKALO, STANFY 1 —
Code Generators in Swift, #se2016 -
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 -
SO DIFFERENT CODE GENERATORS > Snippets > GUI Tools >
Wizards 4 — Code Generators in Swift, #se2016 -
BUT BEFORE THAT WHY DO WE NEED CODE GENERATORS IN
SWIFT? 7 — Code Generators in Swift, #se2016 -
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 -
What are our main goals when whe use Code Generators?
OUR GOALS 9 — Code Generators in Swift, #se2016 -
SAVE TIME MAKE EVERYONE HAPPY 12 — Code Generators in
Swift, #se2016 -
Human error rate Update is just regeneration Good copy-pasting machine
ERROR SCALABILITY 13 — Code Generators in Swift, #se2016 -
WHEN SHOULD WE WRITE ONE? 14 — Code Generators in
Swift, #se2016 -
WHEN SHOULD WE WRITE ONE? ✅ Structure is well defined
15 — Code Generators in Swift, #se2016 -
WHEN SHOULD WE WRITE ONE? ✅ Structure is well defined
✅ Number of special cases is low ✅ Uniform structure 16 — Code Generators in Swift, #se2016 -
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 -
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 -
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 -
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 -
It can be tranformed by Regex Regex SourceKitten GENERATOR SOURCE
SWIFT CODE 24 — Code Generators in Swift, #se2016 -
LET'S START FROM EASY ONES... 26 — Code Generators in
Swift, #se2016 -
SWAGGER > Source Language: DSL in YAML / JSON >
Written In: Java > Generates: Everything http://swagger.io/ 32 — Code Generators in Swift, #se2016 -
CUCKOO > Source Language: Swift Code > Written in: Swift
> Generates: Swift (Mocks) https://github.com/SwiftKit/ Cuckoo 33 — Code Generators in Swift, #se2016 -
CUCKOO let mock = MockGreeter() stub(mock) { stub in when(stub.greetWithMessage("Hello
world")).then { message in print(message) } } 34 — Code Generators in Swift, #se2016 -
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 -
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 -
SWIFTGEN Source: Xcode Files Written in : Swift Generates: Enums
for resources https://github.com/AliSoftware/SwiftGen 37 — Code Generators in Swift, #se2016 -
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 -
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 -
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 -
IF YOU DECIDED TO CREATE ON 42 — Code Generators
in Swift, #se2016 -
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 -
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 -
TIPS AND TRICKS > Don't go too deep > Use
template > Don't overdo > Check reality > Document > Open Source 48 — Code Generators in Swift, #se2016 -
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 -
SOURCE type "dayOfWeek" spec { constraints("string") { enumeration 'sun', 'mon',
'tue', 'wed', 'thu', 'fri', 'sat' } } 51 — Code Generators in Swift, #se2016 -
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 -
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 -
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 -
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 -
RANDOM STRUCTURES GENERATION extension Shop: Random { static func random()
-> Shop { return restrictedRandom() } } 56 — Code Generators in Swift, #se2016 -
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 -
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 -
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 -
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 -
SUMMARIZE > Code generators are here 61 — Code Generators
in Swift, #se2016 -
SUMMARIZE > Engineering approach > Art 62 — Code Generators
in Swift, #se2016 -
SUMMARIZE > There're always things to automate > Code generation
is one of the multiple options 63 — Code Generators in Swift, #se2016 -
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 -
CODE GENERATORS IN SWIFT BY PAUL TAYKALO, STANFY @TT_KILEW 66
— Code Generators in Swift, #se2016 -
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