View
68
Download
2
Category
Preview:
Citation preview
TUTORIAL PHOENIX FRAMEWORKARTHUR BRAGA ALFREDO
TUTORIAL EM DUAS PARTES
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
SEGUNDA PARTE
PHOENIX FRAMEWORK
▸ Criação do projeto
▸ Estrutura de arquivos
▸ Rotas e pipelines
▸ Controllers e Models
▸ Templates e Views
▸ Channels
APLICAÇÃO DE CHAT EM PHOENIX
ELIXIRPRIMEIRA PARTE
ELIXIR
JOSÉ VALIM
▸ Brasileiro
▸ Fez parte do core team do rails
▸ Participou de vários projetos open source
▸ Decidiu criar o Elixir em 2011
OBJETIVO
Criar uma linguagem que possibilitasse alta performance, extensibilidade, produtividade e que rodasse na máquina virtual do Erlang(BEAM).
ELIXIR
PORQUE ERLANG?
▸ Criado 1986 para resolver problemas na área de telefonia
▸ Altamente tolerante a falhas
▸ Feito para concorrência e paralelismo.
ELIXIR
PORQUE ERLANG?
https://blog.whatsapp.com/196/1-million-is-so-2011
ELIXIR
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
O QUE É PROGRAMAÇÃO FUNCIONAL ?
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?
IMUTABILIDADE
Uma vez que uma variável é criada, seu valor não pode mais ser alterado
IMUTABILIDADE
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
Eshell V8.0.3
1> A = 10.102> A = 20. ** exception error: no match of right hand side value 20
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
Interactive Elixir (1.3.2)
iex(1)> a = 1010iex(2)> a = 2020
IMUTÁVEL?
SINGLE MATCHING
A variável não pode mais ser reutilizada
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
Interactive Elixir (1.3.2)
iex(4)> a = 1010iex(5)> ^a = 20** (MatchError) no match of right hand side value: 20
REBINDING
O valor na memória continua imutável, mas a variável pode ser reutilizada
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
soma = 25
func_soma = fn -> "A soma é #{ soma }" end
soma = 100
func_soma.()"A soma é 25"
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
soma = 25
func_soma = -> { puts soma }
soma = 100
func_soma.()100
FUNÇÕES ANÔNIMAS
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
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
soma10 = fn (x) -> x + 10 endsoma10.(20) => 30
multiplica = fn x,y -> x * y endmultiplica.(10,10) => 100
lista = [1,2,3,4,5]Enum.map(lista, soma10) => [11, 12, 13, 14, 15, 16]
FUNÇÕES PURAS
‣ 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
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
FUNÇÕES PURAS
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
soma10 = fn (x) -> x + 10 endsoma10.(20) => 30
multiplica = fn x,y -> x * y endmultiplica.(10,10)=> 100
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
FUNÇÕES PURAS
HIGHER ORDER FUNCTIONS
São funções que recebem ou retornam outras funções
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
HIGHER ORDER FUNCTIONS
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]
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
add = fn x -> fn y -> x + y endend
increment = add.(1)increment.(3)=> 4
PATTERN MATCHING
O operador “=“ significa “Faça com que o lado esquerdo seja igual ao direito”
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
PATTERN MATCHING
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
PATTERN MATCHING
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
{a, b, c} = {:hello, "world", 42}
a:hello
b"world"
{a, _, c} = {:hello, "world", 42}
a:hello
c42
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
{a, b, c} = {:hello, “world"}
** (MatchError) no match of right hand side value: {:hello, "world"}
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
[head | tail] = [1, 2, 3][1, 2, 3]
head1
tail[2, 3]
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 endend
IO.puts Math.sum_list([1, 2, 3], 0) 6
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 endend
IO.puts Math.sum_list([1, 2, 3], 0) 6
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 endend
IO.puts Math.sum_list([1, 2, 3], 0) 6
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 endend
IO.puts Math.sum_list([1, 2, 3], 0) 6
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) endend
IO.puts Math.sum_list([1, 2, 3], 0) 6
RECURSÃO
Funções recursivas são aquelas que chamam elas mesmas.
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
RECURSÃO
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
defmodule Fatorial do def de(1), do: 1 def de(n) when n > 0 do n * de(n-1) endend
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) endend
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
SEM TAIL CALL OPTIMIZATION
CONCEITOS DE PROGRAMAÇÃO FUNCIONAL
COM TAIL CALL OPTIMIZATION
ELIXIR
IEX
Read evaluate print loop(REPL) para Elixir.
ELIXIR
IEX
MIX
É uma ferramenta que vem junto com o Elixir para criar tarefas, compilar código, testar, gerenciar dependências e muito mais.
ELIXIR
MIX
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.
ELIXIR
BAIXAR DEPENDÊNCIAS› mix deps.get
Running dependency resolutionDependency 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
ELIXIR
BUSCAR INFORMAÇÕES DE DEPENDÊNCIAS
› mix hex.info postgrexPostgreSQL 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 FishLicenses: Apache 2.0Links: Github: https://github.com/elixir-ecto/postgrex
HEX
Repositório de pacotes do Elixir
ELIXIR
HEX
TIPOS DE DADOS
1 # integer0x1F # integer1.0 # floattrue # boolean:atom # atom / symbol"elixir" # string'elixir' # char list[1, 2, 3] # list{1, 2, 3} # tuple
ELIXIR
TIPOS DE DADOS
CONTROLES DE FLUXO
lang = "Elixir"
if lang do IO.puts langendElixir:ok
ELIXIR
IF
lang = "Phyton"
if lang == "Elixir" do IO.puts lang else IO.puts "Não é elixir"end Não é elixir:ok
ELIXIR
IF / ELSE
lang = "Elixir"
unless lang do IO.puts langendnil
lang = "Phyton"
unless lang == "Elixir" do IO.puts lang end "Python"
ELIXIR
UNLESS
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
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
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
calcular = fn expressao -> case expressao do {:+, num1, num2} -> num1 + num2 {:-, num1, num2} -> num1 - num2 {:*, num1, num2} -> num1 * num2 {:/, num1, num2} -> num1 / num2 endend
calcular.({:+, 2 ,2})4calcular.({:-, 2 ,2})0calcular.({:/, 2 ,0})** (ArithmeticError) bad argument in arithmetic expression :erlang./(2, 0)
ELIXIR
CASE
ESTRUTURAS DE REPETIÇÃO
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
stream = 1..3|> Stream.map(&IO.inspect(&1))|> Stream.map(&(&1 * 2))|> Stream.map(&IO.inspect(&1))
Enum.to_list(stream)122436=> [2, 4, 6]
ELIXIR
STREAM
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
MÓDULOS E FUNÇÕES
ELIXIR
CHAMANDO FUNÇÕES
Para chamar uma função nomeada, a sintaxe sempre é:
Modulo.funcao(parametro1, parametro2, ..)
defmodule Math do def sum(a, b) do a + b endend
Math.sum(1,2) => 3
ELIXIR
MÓDULOS
defmodule Math do def sum(a, b) do do_sum(a, b) end
defp do_sum(a, b) do a + b endend
IO.puts Math.sum(1, 2) => 3IO.puts Math.do_sum(1, 2) => ** (UndefinedFunctionError)
ELIXIR
FUNÇÕES
defmodule Math do def zero?(0), do: true def zero?(x) when is_integer(x), do: falseend
ELIXIR
FUNÇÕES
GUARD CLAUSES
calcular = fn expressao -> case expressao do {:+, num1, num2} -> num1 + num2 {:-, num1, num2} -> num1 - num2 {:*, num1, num2} -> num1 * num2 {:/, num1, num2} -> num1 / num2 endend
calcular.({:+, 2 ,2})4calcular.({:-, 2 ,2})0calcular.({:/, 2 ,0})** (ArithmeticError) bad argument in arithmetic expression :erlang./(2, 0)
ELIXIR
GUARD CLAUSES
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" endend
calcular.({:/, 2, 0})Não é possível dividir por 0:ok
calcular.({:/, 2, 1})2.0
ELIXIR
GUARD CLAUSES
PIPE OPERATOR ( |>)
Envia o retorno da função anterior como primeiro argumento da próxima função.
ELIXIR
PIPE OPERATOR (|>)
PIPE OPERATOR (|>)
foo( bar( baz( new_function( other_function()))))
ELIXIR
other_function() |> new_function() |> baz() |> bar() |> foo()
"Elixir rocks" |> String.upcase |> String.split["ELIXIR", "ROCKS"]
"elixir" |> String.ends_with?("ixir")true
ELIXIR
PHOENIXSEGUNDA PARTE
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.
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
LIVE CODING: CHAT COM PHOENIX
Repo: https://github.com/arthurbragaa/phoenix-chat-pyse
ONDE APRENDER MAIS
ONDE APRENDER MAIS
MUITO OBRIGADO
Recommended