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

Sorcery with Sourcery

Sorcery with Sourcery

Marcilio Junior

May 03, 2018
Tweet

More Decks by Marcilio Junior

Other Decks in Technology

Transcript

  1. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] WHO AM I? Marcílio

    Júnior ! Mobile Team Leader @ Ignus " Professor @ PUC Minas # Co-Organizer @ CocoaHeads BH
  2. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] Metaprogramação "Metaprogramação é a

    programação de programas que escrevem ou manipulam outros programas (ou a si próprios) assim como seus dados, ou que fazem parte do trabalho em tempo de compilação. Em alguns casos, isso permite que os programadores sejam mais produtivos ao evitar que parte do código seja escrita manualmente.” - Wikipedia
  3. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] Metaprogramação • Normalmente é

    uma característica da linguagem. Ex: Ruby • Aumento de Produtividade • Evitar repetições • Geração de código automaticamente
  4. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] Metaprogramação class Bar def

    self.create_method(method) define_method "my_ #{method}" do puts "Dynamic method called 'my_ #{method}'" end end create_method :foo create_method :bar create_method :baz end Bar.new.my_foo # => "Dynamic method called 'my_foo'" Bar.new.my_bar # => "Dynamic method called 'my_bar'" Bar.new.my_baz # => "Dynamic method called 'my_baz'"
  5. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] Por que? • Quem

    já perdeu bastante tempo escrevendo códigos relacionados a: • Equatable • Hashable • JSON Parsing • Mocks • Stubs
  6. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] Por que? extension Person:

    Equatable { static func ==(lhs: Person, rhs: Person) -> Bool { guard lhs.firstName == rhs.firstName else { return false } guard lhs.lastName == rhs.lastName else { return false } guard lhs.birthDate == rhs.birthDate else { return false } return true } } • E se esse código fosse escrito automaticamente? • E se ao adicionar uma nova propriedade, ele também fosse atualizado automaticamente?
  7. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] Por que? • DRY

    (Don’t Repeat Yourself) • Write Once, Test Once • Less Code, Less Bugs • Evita erros humanos func mapping(map: Map) { name <- ["name"] address <- ["address"] number <- ["numbe"] postalCode <- ["postal_code"] } func mapping(map: Map) { id <- ["id"] name <- ["address"] title <- ["title"] subtitle <- ["subtitle"] comments <- ["comments"] }
  8. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] Sourcery • Gerador de

    código feito usando o SourceKit da Apple • Permite geração de código automático • Usado em mais de 8.000 projetos* • https://github.com/krzysztofzablocki/Sourcery
  9. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] Templates • Javascript import

    JavaScriptCore <%_ for (type of types.implementing.AutoJSExport) { -%> <%_ if (type.kind != "protocol" && !type.annotations.skipJSExport) { -%> @objc protocol <%= type.name %>AutoJSExport: JSExport { <%_ for (variable of type.allVariables) { -%> <%_ if (!variable.annotations.skipJSExport) { -%> var <%= variable.name %>: <%= variable.typeName.name %> { get } <%_ } -%> <%_ } -%> } extension <%= type.name %>: <%= type.name %>AutoJSExport {} <%_ } %> <%_ } %>
  10. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] Templates • Swift <%

    for type in types.classes { -%> <%_ %><%# this is a comment -%> extension <%= type.name %>: Equatable {} <%_ if type.annotations["showComment"] != nil { -%> <% _%> // <%= type.name %> has Annotations <% } -%> func == (lhs: <%= type.name %>, rhs: <%= type.name %>) -> Bool { <%_ for variable in type.variables { -%> if lhs.<%= variable.name %> != rhs.<%= variable.name %> { return false } <%_ } %> return true } <% } -%>
  11. 29º CocoaTalks BH MARCÍLIO JÚNIOR [email protected] Templates • Stencil {%

    for type in types.implementing.AutoEquatable|class %} extension {{ type.name }} { override {{ type.accessLevel }} func isEqual(_ object: Any?) -> Bool { guard let rhs = object as? {{ type.name }} else { return false } {% for variable in type.storedVariables|! annotated:"skipEquality" %}if self.{{ variable.name }} != rhs. {{ variable.name }} { return false } {% endfor %} {% for variable in type.computedVariables| annotated:"forceEquality" %}if self.{{ variable.name }} != rhs. {{ variable.name }} { return false } {% endfor %} {% if type.inheritedTypes.first == "NSObject" %}return true{% else %}return super.isEqual(rhs){% endif %} } } {% endfor %}