$30 off During Our Annual Pro Sale. View details »

Programação funcional com Ruby, potencialize e simplifique qualquer codebase

Programação funcional com Ruby, potencialize e simplifique qualquer codebase

Pergunta: Quantos problemas você já teve de lidar por conta de abstrações complexas e pouco coesas? Ruby é uma linguagem multiparadigma, ou seja, permite o desenvolvimento de aplicações em uma proposta orientada a objetos e funcional. Nessa talk iremos entender como reduzir a complexidade e potencializar resultados ao fazer uso dos recursos funcionais que o Ruby suporta. Tópicos que serão abordados: Introdução aos princípios funcionais, Functional first development e como refatorar uma aplicação Rails na prática do OOP ao FP.

Rodrigo Serradura

July 21, 2018
Tweet

More Decks by Rodrigo Serradura

Other Decks in Programming

Transcript

  1. programação funcional com Ruby potencialize e simplifique qualquer codebase.

  2. @serradura rodrigo.serradura@gmail.com

  3. Objetivo

  4. Potencializar + simplificar = ?

  5. Potencializar + simplificar = Código expressivo, sequencialmente lógico e modular.

  6. Potencializar + simplificar = Código expressivo, sequencialmente lógico e modular.

    Por que?
  7. Potencializar + simplificar = Código expressivo, sequencialmente lógico e modular.

    Por que? Como?
  8. A simplicidade do paradigma funcional.

  9. A simplicidade do paradigma funcional. O poder do Functional First

    Development.
  10. λ Paradigma funcional

  11. None
  12. O que é uma função?

  13. O que é uma função? É o mapeamento de uma

    entrada para uma saída.
  14. O que é uma função? É o mapeamento de uma

    entrada para uma saída.
  15. O que é uma função? É o mapeamento de uma

    entrada para uma saída. Exemplo: f(x) = x + 1
  16. O que é uma função? É o mapeamento de uma

    entrada para uma saída. Exemplo: f(x) = x + 1 f(2) == 3 f(3) == 4
  17. O que é uma função? É o mapeamento de uma

    entrada para uma saída. Exemplo: f(x) = x + 1 f(2) == 3 f(3) == 4 O output é determinado pelo input!
  18. None
  19. None
  20. None
  21. 1. Testes automatizados visam garantir as regras de negócios. ﹡

    Testes seguem a estrutura de uma função. Ex: (Arrange, Act, Assert) 2. Linters servem de input para um código padronizado. 3. Retrospectivas ágeis avaliam o output para melhorar o próximo input. 4. UX - Discovery > Delivery Princípios funcionais para a vida
  22. "Most of the biggest problems in software are problems of

    misconception. — Rich Hickey (Criador da linguagem Closure)
  23. Programação funcional: Dois fatos históricos

  24. 1. Lambda calculus λ-calculus

  25. Lambda Calculus • Criada em 1930 (88 anos atrás). •

    Representa computações matemáticas através de funções anônimas. • Exemplos de funções: quadrado = (x) ↦ x * x soma_dos_quadrados = (x, y) ↦ x² + y²
  26. 2. Linguagem de programação Lisp

  27. Lisp • Criada em 1958 (60 anos atrás). • Segunda

    linguagem de programação mais antiga. (Fortran - imperativa - é por apenas um ano, há mais antiga. • Sintaxe influenciada pelo λ-calculus. • Exemplos de funções:
  28. Lisp • Criada em 1958 (60 anos atrás). • Segunda

    linguagem de programação mais antiga. (Fortran - imperativa - é por apenas um ano, há mais antiga. • Sintaxe influenciada pelo λ-calculus. • Exemplos de funções:
  29. Lisp - Executando uma função anônima (λ)

  30. Lisp - Executando uma função anônima (λ)

  31. Lisp - Executando uma função anônima (λ)

  32. Lisp - Executando uma função anônima (λ)

  33. Resultado Lisp - Executando uma função anônima (λ)

  34. Lisp - Executando uma função anônima (λ)

  35. Semelhanças entre λ-calculus e LISP

  36. None
  37. Resumo até aqui... 1. Programação funcional tem origem na matemática.

    2. λ-calculus: Representa computações matemáticas através de funções anônimas. 3. LISP (a primeira linguagem funcional) tem influência do λ-calculus.
  38. Bacana, mas o que isso tudo tem haver com Ruby?

  39. https://www.ruby-lang.org/en/about

  40. None
  41. None
  42. Semelhanças entre λ-calculus, LISP e Ruby

  43. None
  44. None
  45. Semelhanças entre λ-calculus, LISP, Ruby e Javascript (Rápida curiosidade)

  46. None
  47. Para quem curtiu a introdução...

  48. None
  49. None
  50. Alerta de Spoiler

  51. Desse ponto em diante, todos os conceitos poderão ser aplicados

    em qualquer linguagem que suporte princípios funcionais. Ex: Javascript, Python, Java (8+), Kotlin, Swift...
  52. Desse ponto em diante, todos os conceitos poderão ser aplicados

    em qualquer linguagem que suporte princípios funcionais. Ex: Javascript, Python, Java (8+), Kotlin, Swift...
  53. Ruby é funcional? λ + = ?%

  54. Talk is cheap. Show me the code. Linus Torvalds

  55. https://en.wikipedia.org/wiki/Functional_programming

  56. https://en.wikipedia.org/wiki/Functional_programming

  57. https://en.wikipedia.org/wiki/Functional_programming

  58. https://en.wikipedia.org/wiki/Functional_programming

  59. https://en.wikipedia.org/wiki/Functional_programming

  60. https://en.wikipedia.org/wiki/Functional_programming

  61. https://en.wikipedia.org/wiki/Functional_programming

  62. https://en.wikipedia.org/wiki/Functional_programming

  63. First-class functions Uma função é um tipo de dado como

    qualquer outro.
  64. First-class functions Função é um tipo de dado

  65. Higher-order functions Funções podem receber e retornar funções

  66. Higher-order functions (1 de 3) Funções podem receber e retornar

    funções
  67. Higher-order functions (2 de 3) Funções podem receber e retornar

    funções
  68. Higher-order functions (3 de 3) Funções podem receber e retornar

    funções
  69. Higher-order functions (3 de 3)

  70. Pure-functions Operações sem side-effects (memória ou I/O)

  71. Pure functions (1 de 4) Operações sem side-effects (memória ou

    I/O)
  72. (... Legenda: Abrindo um rápido parêntese

  73. Pure functions (1 de 4) Operações sem side-effects (memória ou

    I/O) Como a função tem acesso a variável counter?
  74. Pure functions (1 de 4) Operações sem side-effects (memória ou

    I/O) Como a função tem acesso a variável counter? Resposta: closure
  75. Pure functions (1 de 4) Operações sem side-effects (memória ou

    I/O) O que significa closure?
  76. Pure functions (1 de 4) Operações sem side-effects (memória ou

    I/O) O que significa closure? R: Capacidade da função em "lembrar" do escopo em que foi declarada.
  77. …) Legenda: Fechando o parêntese

  78. Pure functions (2 de 4) Operações sem side-effects (memória ou

    I/O)
  79. Pure functions (3 de 4) Operações sem side-effects (memória ou

    I/O)
  80. Pure functions (4 de 4) Operações sem side-effects (memória ou

    I/O)
  81. Pure functions (4 de 4) Operações sem side-effects (memória ou

    I/O)
  82. Recursion

  83. Recursion

  84. Recursion

  85. Strict versus non-strict evaluation Lazy evaluation = computar um resultado

    apenas quando necessário
  86. Strict versus non-strict evaluation Lazy evaluation = computar um resultado

    apenas quando necessário
  87. Strict versus non-strict evaluation Lazy evaluation = computar um resultado

    apenas quando necessário
  88. Type systems

  89. O que é uma função? É o mapeamento de uma

    entrada para uma saída. Exemplo: f(x) = x + 1 f(2) == 3 f(3) == 4 O output é determinado pelo input!
  90. O que é uma função? É o mapeamento de uma

    entrada para uma saída. Exemplo: f(x) = x + 1 f(2) == 3 f(3) == 4 O output é determinado pelo input! Quanto mais garantido o input melhores serão as garantias (corretude) do output.
  91. Type Systems (1 de 2)

  92. Type Systems (2 de 2)

  93. (... Legenda: Abrindo um rápido parêntese

  94. Type Systems (2 de 2) Closures!

  95. Type Systems (2 de 2) Assim como um Hash, lambdas

    podem ser invocadas com colchetes
  96. …) Legenda: Fechando o parêntese

  97. Type Systems (2 de 2)

  98. Imutabilidade Referential transparency

  99. Referential transparency (1 de 4) Imutabilidade

  100. Operações sem side-effects (memória ou I/O) Imutabilidade Referential transparency (2

    de 4)
  101. Operações sem side-effects (memória ou I/O) Referential transparency (3 de

    4) Imutabilidade
  102. Operações sem side-effects (memória ou I/O) Imutabilidade Referential transparency (4

    de 4)
  103. (... Legenda: Abrindo um rápido parêntese

  104. Operações sem side-effects (memória ou I/O) Imutabilidade Referential transparency (4

    de 4)
  105. Operações sem side-effects (memória ou I/O) Imutabilidade Referential transparency (4

    de 4) Em Ruby, podemos invocar qualquer callable com .()
  106. Operações sem side-effects (memória ou I/O) Imutabilidade Referential transparency (4

    de 4) Em Ruby, podemos invocar qualquer callable com .() sum.call(1, 1) sum.(1, 1)
  107. …) Legenda: Fechando o parêntese

  108. Referential transparency Imutabilidade

  109. Ruby é funcional? λ + = ?%

  110. Photo by Maarten van den Heuvel on Unsplash Aplicação prática

  111. Helping the Rails helpers

  112. Helping the Rails helpers Imã para código procedural

  113. Helping the Rails helpers Imã para código ruim

  114. Lambda, Lambda, Lambda Parte 1 de 2

  115. None
  116. Lorem Lorem ipsum dolor sit amet, consectetur adipiscing elit. x

  117. None
  118. Refatorando em: 3, 2, 1...

  119. None
  120. None
  121. None
  122. None
  123. None
  124. None
  125. (... Legenda: Abrindo um rápido parêntese

  126. Functional objects (Parte 1 de 2)

  127. Functional objects (Parte 1 de 2) Callable objects = Respondem

    .call
  128. Functional objects (Parte 1 de 2)

  129. Functional objects (Parte 1 de 2) Sua classe é um

    verbo e faz uma única coisa? Então ela se comporta como uma função!
  130. …) Legenda: Fechando o parêntese

  131. None
  132. None
  133. None
  134. None
  135. (... Legenda: Abrindo um rápido parêntese

  136. Currying

  137. …) Legenda: Fechando o parêntese

  138. None
  139. Components, Components... Parte 2 de 2

  140. None
  141. None
  142. None
  143. Implementação do Components::Base

  144. None
  145. 56 LOC

  146. rails console snippets

  147. rails console snippets

  148. https://github.com/serradura/rails-components

  149. Legal… Mas, só tem exemplos com Rails?

  150. https://github.com/serradura/request_via

  151. None
  152. None
  153. Potencializar + simplificar = Código expressivo, sequencialmente lógico e modular.

    Por que? Como?
  154. λ O poder do Functional First Development

  155. "So much complexity in software comes from trying to make

    one thing do two things." — Ryan Singer
  156. None
  157. ActiveRecord model

  158. ActiveRecord model

  159. ActiveRecord model Mapeia os registros do banco de dados para

    objetos Ruby
  160. ActiveRecord model Mapeia os registros do banco de dados para

    objetos Ruby Contém as regras de validação de estado dos objetos
  161. ActiveRecord model Mapeia os registros do banco de dados para

    objetos Ruby Contém as regras de validação de estado dos objetos Gerencia as operações de CRUD
  162. ActiveRecord model Mapeia os registros do banco de dados para

    objetos Ruby Contém as regras de validação de estado dos objetos Gerencia as operações de CRUD Permite criar comandos para serem executados antes e depois das operações de CRUD. (callbacks)
  163. ActiveRecord model Mapeia os registros do banco de dados para

    objetos Ruby Contém as regras de validação de estado dos objetos Gerencia as operações de CRUD Permite criar comandos para serem executados antes e depois das operações de CRUD. (callbacks) Encapsula a construção de queries complexas.
  164. ActiveRecord model Mapeia os registros do banco de dados para

    objetos Ruby Contém as regras de validação de estado dos objetos Gerencia as operações de CRUD Permite criar comandos para serem executados antes e depois das operações de CRUD. (callbacks) Encapsula a construção de queries complexas. Encapsula as regras de negócio da sua aplicação.
  165. ActiveRecord model Mapeia os registros do banco de dados para

    objetos Ruby Contém as regras de validação de estado dos objetos Gerencia as operações de CRUD Permite criar comandos para serem executados antes e depois das operações de CRUD. (callbacks) Encapsula a construção de queries complexas. Encapsula as regras de negócio da sua aplicação. Potencializar + simplificar = Código expressivo, sequencialmente lógico e modular.
  166. SOLID

  167. Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation

    principle Dependency inversion principle
  168. Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation

    principle Dependency inversion principle CreateUser
  169. Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation

    principle Dependency inversion principle CreateUser CreateUser.new(UserRepository)
  170. Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation

    principle Dependency inversion principle CreateUser CreateUser.new(UserRepository) .call == Design by contract
  171. Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation

    principle Dependency inversion principle CreateUser CreateUser.new(UserRepository) .call == Design by contract Composition over Inheritance
  172. Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation

    principle Dependency inversion principle CreateUser CreateUser.new(UserRepository) .call == Design by contract Composition over Inheritance CreateUser é abstrato por não ter implementar o Repository
  173. ActiveRecord model Mapeia os registros do banco de dados para

    objetos Ruby Contém as regras de validação de estado dos objetos Gerencia as operações de CRUD Permite criar comandos para serem executados antes e depois das operações de CRUD. (callbacks) Encapsula a construção de queries complexas. Encapsula as regras de negócio da sua aplicação. Pensando no ActiveRecord… Como ser SOLID já que o mesmo tem tantas funcionalidades / responsabilidades?
  174. ActiveRecord model Mapeia os registros do banco de dados para

    objetos Ruby Contém as regras de validação de estado dos objetos Gerencia as operações de CRUD Permite criar comandos para serem executados antes e depois das operações de CRUD. (callbacks) Encapsula a construção de queries complexas. Encapsula as regras de negócio da sua aplicação. Pensando no ActiveRecord… Como ser SOLID já que o mesmo tem tantas funcionalidades / responsabilidades? Resposta: Crie implementações para cada uma dessas responsabilidades!
  175. ou melhor...

  176. seja DRY! (Don’t Repeat Yourself)

  177. None
  178. None
  179. None
  180. A simplicidade do paradigma funcional. O poder do Functional First

    Development. Opa! Calma aí… E aquela parada de Functional First Development?
  181. Functional First Development

  182. First, code everything you can without using any side effects.

    Then, code your side effects. Functional First Development
  183. None
  184. None
  185. dry-transaction

  186. Talk is cheap. Show me the code. Linus Torvalds

  187. https://github.com/serradura/backend-code-challenge

  188. None
  189. None
  190. None
  191. Mecanismo de entrega: HTTP Outros tipos: Tasks (ETL), Background jobs

    Domínio Operações: R(ead) Operações: CRUD
  192. V M C ActiveRecord, Rails... tem um enorme poder contido.

  193. M V C ActiveRecord, Rails... tem um enorme poder contido.

    Que tal canalizar, modularizar e maximizar todo o potencial?
  194. M V C ActiveRecord, Rails... tem um enorme poder contido.

    Que tal canalizar, modularizar e maximizar todo o potencial? λ, .( )
  195. Potencializar + simplificar = Código expressivo, sequencialmente lógico e modular.

    Por que? Como?
  196. "The cost of adding a feature isn’t just the time

    it takes to code it. The cost also includes the addition of an obstacle to future expansion. The trick is to pick the features that don’t fight each other." — John Carmack
  197. Obrigado @serradura rodrigo.serradura@gmail.com