Slide 1

Slide 1 text

TUTORIAL PHOENIX FRAMEWORK ARTHUR BRAGA ALFREDO

Slide 2

Slide 2 text

TUTORIAL EM DUAS PARTES

Slide 3

Slide 3 text

PRIMEIRA PARTE ELIXIR ▸ Conceitos de programação funcional ▸ IEx ▸ Mix ▸ Tipos de dados ▸ Operador Pipe ▸ Módulos e funções nomeadas ▸ Controles de fluxo ▸ Estruturas de repetição

Slide 4

Slide 4 text

SEGUNDA PARTE PHOENIX FRAMEWORK ▸ Criação do projeto ▸ Estrutura de arquivos ▸ Rotas e pipelines ▸ Controllers e Models ▸ Templates e Views ▸ Channels

Slide 5

Slide 5 text

APLICAÇÃO DE CHAT EM PHOENIX

Slide 6

Slide 6 text

ELIXIR PRIMEIRA PARTE

Slide 7

Slide 7 text

ELIXIR JOSÉ VALIM ▸ Brasileiro ▸ Fez parte do core team do rails ▸ Participou de vários projetos open source ▸ Decidiu criar o Elixir em 2011

Slide 8

Slide 8 text

OBJETIVO Criar uma linguagem que possibilitasse alta performance, extensibilidade, produtividade e que rodasse na máquina virtual do Erlang(BEAM). ELIXIR

Slide 9

Slide 9 text

PORQUE ERLANG? ▸ Criado 1986 para resolver problemas na área de telefonia ▸ Altamente tolerante a falhas ▸ Feito para concorrência e paralelismo. ELIXIR

Slide 10

Slide 10 text

PORQUE ERLANG? https://blog.whatsapp.com/196/1-million-is-so-2011 ELIXIR

Slide 11

Slide 11 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

Slide 12

Slide 12 text

O QUE É PROGRAMAÇÃO FUNCIONAL ?

Slide 13

Slide 13 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL É um paradigma de programação que trata a computação como uma avaliação de funções matemáticas e que evita estados ou dados mutáveis. O QUE É PROGRAMAÇÃO FUNCIONAL?

Slide 14

Slide 14 text

IMUTABILIDADE

Slide 15

Slide 15 text

Uma vez que uma variável é criada, seu valor não pode mais ser alterado IMUTABILIDADE CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

Slide 16

Slide 16 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL Eshell V8.0.3 1> A = 10. 10 2> A = 20. ** exception error: no match of right hand side value 20

Slide 17

Slide 17 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL Interactive Elixir (1.3.2) iex(1)> a = 10 10 iex(2)> a = 20 20

Slide 18

Slide 18 text

IMUTÁVEL?

Slide 19

Slide 19 text

SINGLE MATCHING A variável não pode mais ser reutilizada CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

Slide 20

Slide 20 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL Interactive Elixir (1.3.2) iex(4)> a = 10 10 iex(5)> ^a = 20 ** (MatchError) no match of right hand side value: 20

Slide 21

Slide 21 text

REBINDING O valor na memória continua imutável, mas a variável pode ser reutilizada CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

Slide 22

Slide 22 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL soma = 25 func_soma = fn -> "A soma é #{ soma }" end soma = 100 func_soma.() "A soma é 25"

Slide 23

Slide 23 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL soma = 25 func_soma = -> { puts soma } soma = 100 func_soma.() 100

Slide 24

Slide 24 text

FUNÇÕES ANÔNIMAS

Slide 25

Slide 25 text

São funções que podem ser tratadas como valores e que podem ser manipuladas ou retornadas por outras funções. CONCEITOS DE PROGRAMAÇÃO FUNCIONAL FUNÇÕES ANÔNIMAS

Slide 26

Slide 26 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL soma10 = fn (x) -> x + 10 end soma10.(20) => 30 multiplica = fn x,y -> x * y end multiplica.(10,10) => 100 lista = [1,2,3,4,5] Enum.map(lista, soma10) => [11, 12, 13, 14, 15, 16]

Slide 27

Slide 27 text

FUNÇÕES PURAS

Slide 28

Slide 28 text

‣ Funções sem efeitos colaterais ‣ Não acessam banco ‣ Não acessam arquivos ‣ Sempre retornam os mesmos valores para os mesmo parâmetros CONCEITOS DE PROGRAMAÇÃO FUNCIONAL FUNÇÕES PURAS

Slide 29

Slide 29 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL FUNÇÕES PURAS

Slide 30

Slide 30 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL soma10 = fn (x) -> x + 10 end soma10.(20) => 30 multiplica = fn x,y -> x * y end multiplica.(10,10) => 100

Slide 31

Slide 31 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL FUNÇÕES PURAS

Slide 32

Slide 32 text

HIGHER ORDER FUNCTIONS

Slide 33

Slide 33 text

São funções que recebem ou retornam outras funções CONCEITOS DE PROGRAMAÇÃO FUNCIONAL HIGHER ORDER FUNCTIONS

Slide 34

Slide 34 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL lista = [1,2,3,4,5] [1, 2, 3, 4, 5] Enum.map(lista, fn x -> x * x end) [1, 4, 9, 16, 25] Enum.reduce(lista, 0, fn(x,y) -> x + y end) 15 Enum.reduce(lista, 0, &(&1 + &2)) 15 Enum.filter(lista, fn x -> x > 2 end) [3, 4, 5]

Slide 35

Slide 35 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL add = fn x -> fn y -> x + y end end increment = add.(1) increment.(3) => 4

Slide 36

Slide 36 text

PATTERN MATCHING

Slide 37

Slide 37 text

O operador “=“ significa “Faça com que o lado esquerdo seja igual ao direito” CONCEITOS DE PROGRAMAÇÃO FUNCIONAL PATTERN MATCHING

Slide 38

Slide 38 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL PATTERN MATCHING

Slide 39

Slide 39 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL {a, b, c} = {:hello, "world", 42} a :hello b "world" {a, _, c} = {:hello, "world", 42} a :hello c 42

Slide 40

Slide 40 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL {a, b, c} = {:hello, “world"} ** (MatchError) no match of right hand side value: {:hello, "world"}

Slide 41

Slide 41 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL [head | tail] = [1, 2, 3] [1, 2, 3] head 1 tail [2, 3]

Slide 42

Slide 42 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL defmodule Math do def sum_list([head | tail], accumulator) do sum_list(tail, head + accumulator) end def sum_list([], accumulator) do accumulator end end IO.puts Math.sum_list([1, 2, 3], 0) 6

Slide 43

Slide 43 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL defmodule Math do def sum_list([head (1) | tail ([2,3])], accumulator (0) ) do sum_list(tail([2,3]), head (1) + accumulator (0)) end def sum_list([], accumulator) do accumulator end end IO.puts Math.sum_list([1, 2, 3], 0) 6

Slide 44

Slide 44 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL defmodule Math do def sum_list([head (2) | tail ([3])], accumulator (1) ) do sum_list(tail([3]), head (2) + accumulator (1)) end def sum_list([], accumulator) do accumulator end end IO.puts Math.sum_list([1, 2, 3], 0) 6

Slide 45

Slide 45 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL defmodule Math do def sum_list([head (3) | tail ([])], accumulator (3) ) do sum_list(tail([]), head (3) + accumulator (3)) end def sum_list([], accumulator) do accumulator end end IO.puts Math.sum_list([1, 2, 3], 0) 6

Slide 46

Slide 46 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL defmodule Math do def sum_list([head | tail], accumulator ) do sum_list(tail, head + accumulator) end def sum_list([], accumulator (6) ) do accumulator (6) end end IO.puts Math.sum_list([1, 2, 3], 0) 6

Slide 47

Slide 47 text

RECURSÃO

Slide 48

Slide 48 text

Funções recursivas são aquelas que chamam elas mesmas. CONCEITOS DE PROGRAMAÇÃO FUNCIONAL RECURSÃO

Slide 49

Slide 49 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL defmodule Fatorial do def de(1), do: 1 def de(n) when n > 0 do n * de(n-1) end end

Slide 50

Slide 50 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL defmodule Fatorial do def de(1, acc), do: acc def de(n, acc) when n > 0 do de(n-1, acc * n) end end

Slide 51

Slide 51 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL SEM TAIL CALL OPTIMIZATION

Slide 52

Slide 52 text

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL COM TAIL CALL OPTIMIZATION

Slide 53

Slide 53 text

ELIXIR

Slide 54

Slide 54 text

IEX

Slide 55

Slide 55 text

Read evaluate print loop(REPL) para Elixir. ELIXIR IEX

Slide 56

Slide 56 text

MIX

Slide 57

Slide 57 text

É uma ferramenta que vem junto com o Elixir para criar tarefas, compilar código, testar, gerenciar dependências e muito mais. ELIXIR MIX

Slide 58

Slide 58 text

ELIXIR CRIAÇÃO DE UM NOVO PROJETO › mix new teste * creating README.md * creating .gitignore * creating mix.exs * creating config * creating config/config.exs * creating lib * creating lib/teste.ex * creating test * creating test/test_helper.exs * creating test/teste_test.exs Your Mix project was created successfully. You can use "mix" to compile it, test it, and more: cd teste mix test Run "mix help" for more commands.

Slide 59

Slide 59 text

ELIXIR BAIXAR DEPENDÊNCIAS › mix deps.get Running dependency resolution Dependency resolution completed connection: 1.0.4 db_connection: 1.0.0 decimal: 1.2.0 postgrex: 0.12.1 * Getting postgrex (Hex package) Checking package (https://repo.hex.pm/tarballs/postgrex-0.12.1.tar) Using locally cached package * Getting connection (Hex package) Checking package (https://repo.hex.pm/tarballs/connection-1.0.4.tar) Using locally cached package * Getting db_connection (Hex package) Checking package (https://repo.hex.pm/tarballs/db_connection-1.0.0.tar) Using locally cached package * Getting decimal (Hex package) Checking package (https://repo.hex.pm/tarballs/decimal-1.2.0.tar) Using locally cached package

Slide 60

Slide 60 text

ELIXIR BUSCAR INFORMAÇÕES DE DEPENDÊNCIAS › mix hex.info postgrex PostgreSQL driver for Elixir. Config: {:postgrex, "~> 0.12.1"} Releases: 0.12.1, 0.12.0, 0.11.2, 0.11.1, 0.11.0, 0.10.0, 0.9.1, 0.9.0, 0.8.4, 0.8.3, ... Maintainers: Eric Meadows-Jönsson, James Fish Licenses: Apache 2.0 Links: Github: https://github.com/elixir-ecto/postgrex

Slide 61

Slide 61 text

HEX

Slide 62

Slide 62 text

Repositório de pacotes do Elixir ELIXIR HEX

Slide 63

Slide 63 text

TIPOS DE DADOS

Slide 64

Slide 64 text

1 # integer 0x1F # integer 1.0 # float true # boolean :atom # atom / symbol "elixir" # string 'elixir' # char list [1, 2, 3] # list {1, 2, 3} # tuple ELIXIR TIPOS DE DADOS

Slide 65

Slide 65 text

CONTROLES DE FLUXO

Slide 66

Slide 66 text

lang = "Elixir" if lang do IO.puts lang end Elixir :ok ELIXIR IF

Slide 67

Slide 67 text

lang = "Phyton" if lang == "Elixir" do IO.puts lang else IO.puts "Não é elixir" end Não é elixir :ok ELIXIR IF / ELSE

Slide 68

Slide 68 text

lang = "Elixir" unless lang do IO.puts lang end nil lang = "Phyton" unless lang == "Elixir" do IO.puts lang end "Python" ELIXIR UNLESS

Slide 69

Slide 69 text

cond do 2 + 2 == 5 -> "Falso" 2 * 2 == 3 -> "Falso" 1 + 1 == 2 -> "Verdadeiro" true -> "Se nada der certo chega aqui" end "Verdadeiro" ELIXIR COND

Slide 70

Slide 70 text

case {1, 2, 3} do {4, 5, 6} -> "Não vai dar match" {1, x, 3} -> "Vai dar match e o x vai receber o valor 2" _ -> "Essa clausula vai dar match em qualquer valor" end "Vai dar match e o x vai receber o valor 2" ELIXIR CASE

Slide 71

Slide 71 text

case {1, 2, 3} do {4, 5, 6} -> "Não vai dar match" {1, ^x, 3} -> "Vai dar match e o x vai receber o valor 2" _ -> "Essa clausula vai dar match em qualquer valor" end "Essa clausula vai dar match em qualquer valor" ELIXIR CASE

Slide 72

Slide 72 text

calcular = fn expressao -> case expressao do {:+, num1, num2} -> num1 + num2 {:-, num1, num2} -> num1 - num2 {:*, num1, num2} -> num1 * num2 {:/, num1, num2} -> num1 / num2 end end calcular.({:+, 2 ,2}) 4 calcular.({:-, 2 ,2}) 0 calcular.({:/, 2 ,0}) ** (ArithmeticError) bad argument in arithmetic expression :erlang./(2, 0) ELIXIR CASE

Slide 73

Slide 73 text

ESTRUTURAS DE REPETIÇÃO

Slide 74

Slide 74 text

lista = [1,2,3,4,5] [1, 2, 3, 4, 5] Enum.map(lista, fn x -> x * x end) [1, 4, 9, 16, 25] Enum.reduce(lista, 0, fn(x,y) -> x + y end) 15 Enum.reduce(lista, 0, &(&1 + &2)) 15 Enum.filter(lista, fn x -> x > 2 end) [3, 4, 5] ELIXIR ENUM

Slide 75

Slide 75 text

stream = 1..3 |> Stream.map(&IO.inspect(&1)) |> Stream.map(&(&1 * 2)) |> Stream.map(&IO.inspect(&1)) Enum.to_list(stream) 1 2 2 4 3 6 => [2, 4, 6] ELIXIR STREAM

Slide 76

Slide 76 text

File.stream!("path/to/some/file") |> Flow.from_enumerable() |> Flow.flat_map(fn line -> for word <- String.split(" "), do: {word, 1} end) |> Flow.reduce_by_key(& &1 + &2) |> Enum.to_list() ELIXIR FLOW

Slide 77

Slide 77 text

MÓDULOS E FUNÇÕES

Slide 78

Slide 78 text

ELIXIR CHAMANDO FUNÇÕES Para chamar uma função nomeada, a sintaxe sempre é: Modulo.funcao(parametro1, parametro2, ..)

Slide 79

Slide 79 text

defmodule Math do def sum(a, b) do a + b end end Math.sum(1,2) => 3 ELIXIR MÓDULOS

Slide 80

Slide 80 text

defmodule Math do def sum(a, b) do do_sum(a, b) end defp do_sum(a, b) do a + b end end IO.puts Math.sum(1, 2) => 3 IO.puts Math.do_sum(1, 2) => ** (UndefinedFunctionError) ELIXIR FUNÇÕES

Slide 81

Slide 81 text

defmodule Math do def zero?(0), do: true def zero?(x) when is_integer(x), do: false end ELIXIR FUNÇÕES

Slide 82

Slide 82 text

GUARD CLAUSES

Slide 83

Slide 83 text

calcular = fn expressao -> case expressao do {:+, num1, num2} -> num1 + num2 {:-, num1, num2} -> num1 - num2 {:*, num1, num2} -> num1 * num2 {:/, num1, num2} -> num1 / num2 end end calcular.({:+, 2 ,2}) 4 calcular.({:-, 2 ,2}) 0 calcular.({:/, 2 ,0}) ** (ArithmeticError) bad argument in arithmetic expression :erlang./(2, 0) ELIXIR GUARD CLAUSES

Slide 84

Slide 84 text

calcular = fn expressao -> case expressao do {:+, num1, num2} -> num1 + num2 {:-, num1, num2} -> num1 - num2 {:*, num1, num2} -> num1 * num2 {:/, num1, num2} when num2 != 0 -> num1 / num2 {:/, num1, num2} when num2 == 0 -> IO.puts "Não é possível dividir por 0" end end calcular.({:/, 2, 0}) Não é possível dividir por 0 :ok calcular.({:/, 2, 1}) 2.0 ELIXIR GUARD CLAUSES

Slide 85

Slide 85 text

PIPE OPERATOR ( |>)

Slide 86

Slide 86 text

Envia o retorno da função anterior como primeiro argumento da próxima função. ELIXIR PIPE OPERATOR (|>)

Slide 87

Slide 87 text

PIPE OPERATOR (|>) foo( bar( baz( new_function( other_function())))) ELIXIR

Slide 88

Slide 88 text

other_function() |> new_function() |> baz() |> bar() |> foo() "Elixir rocks" |> String.upcase |> String.split ["ELIXIR", "ROCKS"] "elixir" |> String.ends_with?("ixir") true ELIXIR

Slide 89

Slide 89 text

PHOENIX SEGUNDA PARTE

Slide 90

Slide 90 text

PHOENIX FRAMEWORK CHRIS MCCORD ▸ Descobriu Elixir em 2013 ▸ Desenvolveu uma biblioteca de websockets ▸ Viu a oportunidade de criar um framework com foco em produtividade no estilo do Rails.

Slide 91

Slide 91 text

TIMELINE Dezembro de 2013: Início do desenvolvimento Setembro de 2014: José Valim entra para o time Agosto de 2015: Versão 1.0 Junho de 2016: Versão 1.2 com Phoenix Presence Janeiro de 2017: Versão 1.3 sem models e pasta web PHOENIX FRAMEWORK

Slide 92

Slide 92 text

LIVE CODING: CHAT COM PHOENIX

Slide 93

Slide 93 text

Repo: https://github.com/arthurbragaa/phoenix- chat-pyse

Slide 94

Slide 94 text

ONDE APRENDER MAIS

Slide 95

Slide 95 text

ONDE APRENDER MAIS

Slide 96

Slide 96 text

MUITO OBRIGADO