41
What Code Generation Can Do for You Marc-Antoine Sauvé Hopper

What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

What Code Generation Can Do for You

Marc-Antoine Sauvé Hopper

Page 2: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Hopper Creates Trust from DataWe process 300 billion flight prices each month to build trust and optimize customer interactions.

Page 3: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Repetitive tasks are

Boring Error prone Counterproductive

Page 4: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Sourcery

Code generation No reflection Flexible

Page 5: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

What is it?Standalone application

Page 6: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

What is it?Standalone application

Scan the source code

Page 7: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

What is it?Standalone application

Scan the source code

Uses templates

Page 8: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

What is it?Standalone application

Scan the source code

Uses templates

Generate source code

Page 9: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

What is it?Standalone application

Scan the source code

Uses templates

Generate source code

Can read code and comments

Page 10: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

public class Foo {}

Foo.swift

Page 11: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

{% for type in types.all %}extension {{ type.name }} {{% if type.accessLevel == "public" %}

public var name: String {return "{{ type.name }}"

}{% endif %}}{% endfor %}

AutoClassName.stencil

public class Foo {}

Foo.swift

Page 12: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

{% for type in types.all %}extension {{ type.name }} {{% if type.accessLevel == "public" %}

public var name: String {return "{{ type.name }}"

}{% endif %}}{% endfor %}

AutoClassName.stencil

public class Foo {}

Foo.swift

Page 13: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

{% for type in types.all %}extension {{ type.name }} {{% if type.accessLevel == "public" %}

public var name: String {return "{{ type.name }}"

}{% endif %}}{% endfor %}

AutoClassName.stencil

public class Foo {}

Foo.swift

Page 14: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

{% for type in types.all %}extension {{ type.name }} {{% if type.accessLevel == "public" %}

public var name: String {return "{{ type.name }}"

}{% endif %}}{% endfor %}

AutoClassName.stencil

public class Foo {}

Foo.swift

Page 15: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

{% for type in types.all %}extension {{ type.name }} {{% if type.accessLevel == "public" %}

public var name: String {return "{{ type.name }}"

}{% endif %}}{% endfor %}

AutoClassName.stencil

public class Foo {}

extension Foo {public var name: String {

return "Foo"}

}

Foo.swift

AutoClassName.generated.swift

Page 16: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Sourcery

Before build Watch files Manual

Page 17: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Real Swift problemListing enum

Page 18: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

public enum SuperPower { case HeatVision case SuperSpeed case SuperStrength case XrayVision case SuperIntelligence}

models.swift

Page 19: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

protocol AutoCases { }public enum SuperPower: AutoCases { case HeatVision case SuperSpeed case SuperStrength case XrayVision case SuperIntelligence}

models.swift

Page 20: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

{% for enum in types.implementing.AutoCases|enum %}{{ enum.accessLevel }} extension {{ enum.name }} { static public let count: Int = {{ enum.cases.count }} {% if not enum.hasAssociatedValues %} static public let allCases: [{{ enum.name }}] = [ {% for case in enum.cases %} .{{ case.name }}{% if not forloop.last %},{% endif %} {% endfor %}] {% endif %}}{% endfor %}

AutoCases.stencil

Page 21: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

{% for enum in types.implementing.AutoCases|enum %}{{ enum.accessLevel }} extension {{ enum.name }} { static public let count: Int = {{ enum.cases.count }} {% if not enum.hasAssociatedValues %} static public let allCases: [{{ enum.name }}] = [ {% for case in enum.cases %} .{{ case.name }}{% if not forloop.last %},{% endif %} {% endfor %}] {% endif %}}{% endfor %}

AutoCases.stencil

Page 22: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

{% for enum in types.implementing.AutoCases|enum %}{{ enum.accessLevel }} extension {{ enum.name }} { static public let count: Int = {{ enum.cases.count }} {% if not enum.hasAssociatedValues %} static public let allCases: [{{ enum.name }}] = [ {% for case in enum.cases %} .{{ case.name }}{% if not forloop.last %},{% endif %} {% endfor %}] {% endif %}}{% endfor %}

AutoCases.stencil

Page 23: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

public extension SuperPower { static let count: Int = 5 static public let allCases: [SuperPower] = [ .HeatVision, .SuperSpeed, .SuperStrength, .XrayVision, .SuperIntelligence ]}

AutoCases.generated.swift

Page 24: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Sourcery

Readable code Debuggable DRY

Page 25: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Equatable

Page 26: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

// swiftlint:disable file_length// [...] Removed some boilerplate to enhance readability{% macro compareVariables variables %} {% for variable in variables where variable.readAccess != "private" and variable.readAccess != "fileprivate" %}{% if not variable.annotations.skipEquality %}guard {% if not variable.isOptional %}{% if not variable.annotations.arrayEquality %}lhs.{{ variable.name }} == rhs.{{ variable.name }}{% else %}compareArrays(lhs: lhs.{{ variable.name }}, rhs: rhs.{{ variable.name }}, compare: ==){% endif %}{% else %}compareOptionals(lhs: lhs.{{ variable.name }}, rhs: rhs.{{ variable.name }}, compare: ==){% endif %} else { return false }{% endif %} {% endfor %}{% endmacro %}

// MARK: - AutoEquatable for classes, protocols, structs{% for type in types.implementing.AutoEquatable|!enum %}

// MARK: - {{ type.name }} AutoEquatable{% if not type.kind == "protocol" and not type.based.NSObject %}extension {{ type.name }}: Equatable {}{% endif %}{% if type.supertype.based.Equatable or type.supertype.implements.AutoEquatable %}THIS WONT COMPILE, WE DONT SUPPORT INHERITANCE for AutoEquatable{% endif %}{{ type.accessLevel }} func == (lhs: {{ type.name }}, rhs: {{ type.name }}) -> Bool { {% if not type.kind == "protocol" %} {% call compareVariables type.storedVariables %} {% else %} {% call compareVariables type.allVariables %} {% endif %} return true}{% endfor %}

// Keeps going for a while adding some code for enums

AutoEquatable.stencil

Page 27: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

// MARK: - SuperHero AutoEquatableextension SuperHero: Equatable {}public func == (lhs: SuperHero, rhs: SuperHero) -> Bool { guard lhs.name == rhs.name else { return false } guard lhs.superPowers == rhs.superPowers else { return false } return true}

AutoEquatable.generated.swift

Page 28: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

// MARK: - SuperPower AutoEquatableextension SuperPower: Equatable {}public func == (lhs: SuperPower, rhs: SuperPower) -> Bool { switch (lhs, rhs) { case (.HeatVision, .HeatVision): return true case (.SuperSpeed(let lhs), .SuperSpeed(let rhs)): if lhs.speed != rhs.speed { return false } if lhs.duration != rhs.duration { return false } return true // [ Skipped some code for readability ] default: return false }}

AutoEquatable.generated.swift

Page 29: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

public class SuperHero: AutoEquatable { public let name: String // sourcery: skipEquality public let sidekick: SuperHero? public let superPowers: [SuperPower]}

Annotations

Page 30: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Sourcery

Test once Avoid human mistakes Low maintenance cost

Page 31: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

ClosureType

DictionaryType

ArrayType TupleElement

TupleType

TypeName

Subscript

MethodParameter

Method

Variable

AssociatedValue

Enum

EnumCase

ClassTypes

Protocol

Struct

GenericType

GenericTypeParameter

Attribute

Page 32: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

What’s bad?Hard to read the template

Page 33: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Hard to read the template

Hard to write the template

What’s bad?

Page 34: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Hard to read the template

Hard to write the template

Poor support in the IDEs

What’s bad?

Page 35: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Hard to read the template

Hard to write the template

Poor support in the IDEs

Can be slow to compile

What’s bad?

Page 36: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Hard to read the template

Hard to write the template

Poor support in the IDEs

Can be slow to compile

Annotations are not type checked

What’s bad?

Page 37: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

AppCode

Page 38: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Visual Studio Code

Page 39: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Still worth it!Saves a lot of time!

Page 40: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

Questions?

Page 41: What Code Generation Can Do for You · 2018-05-31 · // swiftlint:disable file_length // [...] Removed some boilerplate to enhance readability {% macro compareVariables variables

We’re on the Lookout for Talented People

Check out current openings at hopper.com/jobs.

Slides available oncocoaheadsmtl.com.