Programação funcional em Ruby - Rubyconf Brasil 2018

Programação funcional em Ruby - Rubyconf Brasil 2018

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 abordagem orientada a objetos e/ou 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 aplicações Ruby na prática do Procedural/OOP ao FP.

C8018fd681f3d02ee52af7c72dd53e9d?s=128

Rodrigo Serradura

December 14, 2018
Tweet

Transcript

  1. programação funcional em Ruby

  2. Alta coesão + Baixo acoplamento = Princípios funcionais

  3. SOLID = Princípios funcionais

  4. @serradura rodrigo.serradura@gmail.com

  5. Objetivos

  6. A simplicidade do paradigma funcional.

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

    Development.
  8. A simplicidade do paradigma funcional. O poder do Functional First

    Development. SOLID
  9. λ Paradigma funcional

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

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

    entrada para uma saída.
  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. Exemplo: f(x) = x + 1
  15. 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
  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 O output é determinado pelo input!
  17. None
  18. None
  19. None
  20. O output é determinado pelo input!

  21. O output é determinado pelo input!

  22. O output é determinado pelo input! Discover Define Develop Deliver

  23. O output é determinado pelo input! Discover Define Develop Deliver

  24. O output é determinado pelo input! Discover Define Develop Deliver

    Double Diamond = Design process
  25. "Most of the biggest problems in software are problems of

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

  27. 1. Lambda calculus λ-calculus

  28. 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²
  29. 2. Linguagem de programação Lisp

  30. 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:
  31. 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:
  32. Lisp - Executando uma função anônima (λ)

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

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

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

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

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

  38. Semelhanças entre λ-calculus e LISP

  39. None
  40. 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.
  41. Bacana, mas o que isso tudo tem haver com Ruby?

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

  43. None
  44. None
  45. Semelhanças entre λ-calculus, LISP e Ruby

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

  48. None
  49. Para quem curtiu a introdução...

  50. None
  51. None
  52. Alerta de Spoiler

  53. 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...
  54. 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...
  55. Ruby é funcional? λ + = ?%

  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. https://en.wikipedia.org/wiki/Functional_programming

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

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

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

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

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

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

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

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

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

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

  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?
  75. 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
  76. Pure functions (1 de 4) Operações sem side-effects (memória ou

    I/O) O que significa closure?
  77. 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.
  78. …) Legenda: Fechando o parêntese

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

    I/O)
  80. Pure functions (3 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. Pure functions (4 de 4) Operações sem side-effects (memória ou

    I/O)
  83. Recursion

  84. Recursion

  85. Recursion

  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. Strict versus non-strict evaluation Lazy evaluation = computar um resultado

    apenas quando necessário
  89. Type systems

  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!
  91. 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.
  92. Type Systems (1 de 2)

  93. Type Systems (2 de 2)

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

  95. Type Systems (2 de 2) Closures!

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

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

  98. Type Systems (2 de 2)

  99. Imutabilidade Referential transparency

  100. Referential transparency (1 de 4) Imutabilidade

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

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

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

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

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

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

    de 4) Em Ruby, podemos invocar qualquer callable com .()
  107. 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)
  108. …) Legenda: Fechando o parêntese

  109. Referential transparency Imutabilidade

  110. Ruby é funcional? λ + = ?%

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

  112. Rakefile Procedural |> Funcional bit.ly/2EfljJM

  113. None
  114. None
  115. None
  116. None
  117. None
  118. None
  119. None
  120. None
  121. None
  122. None
  123. None
  124. (... Legenda: Abrindo um rápido parêntese

  125. None
  126. None
  127. None
  128. …) Legenda: Fechando o parêntese

  129. None
  130. None
  131. None
  132. None
  133. None
  134. Functional Objects

  135. Functional objects (Parte 1 de 2)

  136. Functional objects (Parte 1 de 2)

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

    .call
  138. Functional objects (Parte 2 de 2)

  139. Functional objects (Parte 1 de 2) Sua classe/objeto é um

    verbo e faz uma única coisa? Então ela se comporta como uma função!
  140. Photo by Maarten van den Heuvel on Unsplash Aplicação prática

  141. Rakefile Functional Objects bit.ly/2Qqsqq2

  142. None
  143. None
  144. None
  145. None
  146. None
  147. None
  148. None
  149. None
  150. None
  151. None
  152. None
  153. None
  154. https://github.com/serradura/request_via

  155. None
  156. λ O poder do Functional First Development

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

    one thing do two things." — Ryan Singer
  158. ActiveRecord model

  159. ActiveRecord model

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

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

    objetos Ruby Contém as regras de validação de estado dos objetos
  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
  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)
  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.
  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.
  166. 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. Desafio: Como obter um código expressivo, sequencialmente lógico e modular?
  167. SOLID

  168. Functional Objects

  169. Sua classe/objeto é um verbo e faz uma única coisa?

    Então ela se comporta como uma função!
  170. None
  171. Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation

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

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

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

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

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

    principle Dependency inversion principle CreateUser CreateUser.new(UserRepository) .call(input) == Design by contract Composition over Inheritance CreateUser é uma abstração por não ter de implementar o Repository
  177. SOLID + Princípios Funcionais

  178. SOLID + Princípios Funcionais 1. Uma função faz uma única

    coisa e muito bem. 2. Use uma composição de funções para atender requisitos complexos. 3. Atenção: A composição tem que ser sequencialmente lógica e expressiva. 4. Dica: Modularize apenas o necessário. 5.
  179. SOLID + Princípios Funcionais 1. Uma função faz uma única

    coisa e muito bem. 2. Use uma composição de funções para atender requisitos complexos. 3. Atenção: A composição tem que ser sequencialmente lógica e expressiva. 4. Dica: Modularize apenas o necessário. 5. Troque função por objeto no texto acima e tudo irá funcionar.
  180. 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?
  181. 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!
  182. ou melhor...

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

  184. None
  185. None
  186. None
  187. A simplicidade do paradigma funcional. O poder do Functional First

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

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

    Then, code your side effects. Functional First Development
  190. None
  191. None
  192. dry-transaction

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

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

  195. None
  196. None
  197. None
  198. None
  199. Mecanismo de entrega: HTTP Outros tipos: Tasks (ETL), Background jobs

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

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

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

    Que tal canalizar, modularizar e maximizar todo o potencial? λ, .( )
  203. "Sometimes, the elegant implementation is just a function. Not a

    method. Not a class. Not a framework. Just a function." — John Carmack
  204. Obrigado @serradura rodrigo.serradura@gmail.com