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

Mantendo sistemas Ruby e Elixir: lições aprendidas

Elaine Naomi
September 09, 2022

Mantendo sistemas Ruby e Elixir: lições aprendidas

Se você acompanha notícias e discussões da comunidade de desenvolvimento de software há algum tempo, provavelmente já lidou com perguntas como:
Ruby está morrendo? Vale a pena aprender Elixir em 2022? Devemos migrar todos os sistemas Ruby para Elixir o quanto antes? Ou Elixir está morrendo também?

Com tantas opiniões divergentes, como podemos encontrar as nossas próprias respostas para essas perguntas e dilemas? Entender o ciclo do hype é o primeiro passo.
O segundo é entender como explorar novos universos e como adaptá-los a cada contexto.

Nessa palestra, vou apresentar a estratégia que eu utilizo para analisar ambos ecossistemas, compartilhando aprendizados e desafios que eu encontrei em sistemas Ruby e Elixir nos últimos anos,
incluindo a época em que trabalhei para a Plataformatec como desenvolvedora de software.

RubyConf+ 2022 Brasil

Elaine Naomi

September 09, 2022
Tweet

More Decks by Elaine Naomi

Other Decks in Programming

Transcript

  1. Desenvolvedora/Engenheira de Software (desde 2008) Bacharela em Engenharia da Computação

    Mestra em Ciência da Computação ELAINE NAOMI WATANABE twitter.com/elaine_nw speakerdeck.com/elainenaomi slides disponíveis
  2. Framework web criado em 2004 Criado por David Hansson (DHH)

    Última versão: 7.0.3.1 Lançada em 12 Julho 2022 Linguagem criada em 1995 Criada por Yukihiro "Matz" Última versão: 3.1.2 Publicada em 12 Abril 2022 +27 anos +18 anos
  3. #17

  4. Gartner Hype Cycle Acionador de inovação Pico de expectativas infladas

    Vale da desilusão Ladeira da informação Tempo Visibilidade Planície da produtividade https://www.gartner.com.br/pt-br/metodologias/gartner-hype-cycle
  5. Keynote: The Success of Ruby on Rails by Eileen Uchitelle

    https://www.youtube.com/watch?v=MbqJzACF-54 RUBY
  6. Linguagem criada em 2012 Criada por José Valim Última versão:

    1.14.0 Publicada em 01 Setembro 2022 +10 anos Linguagem + Plataforma + VM criada em 1986 Criada por Joe Armstrong, Robert Virding e Mike Williams Última versão: 25.0 Publicada em 18 Maio 2022 +36 anos
  7. ELIXIR defmodule Hello do def world do IO.puts "Hello, world"

    end end jeitinho de Ruby mas não é Ruby
  8. O case da Plataformatec com o Elixir - Hugo Baraúna

    https://www.youtube.com/watch?v=XnEAllPTNWw 2010
  9. Free lunch O software ficava mais rápido com o avanço

    das CPUs Não era necessário fazer nada além de atualizar o hardware
  10. Free lunch is over A partir de ~2003, o clock

    speed parou de crescer como antes. Se continuasse, seria comum ter CPUs com 10GHz, por ex. Em 2005, surgiu o primeiro processador dual-core 2005
  11. Framework web criado em 2014 Criado por Chris McCord Última

    versão: 1.6.12 Lançada em 06 Setembro 2022 +8 anos Linguagem criada em 2012 Criada por José Valim Última versão: 1.14.0 Publicada em 01 Setembro 2022 +10 anos
  12. #3

  13. ELIXIR Celebrating the 10 Years of Elixir | José Valim

    | ElixirConf EU 2022 https://www.youtube.com/watch?v=Jf5Hsa1KOc8
  14. soma_um = fn x -> x + 1 end Enum.map([1,

    2, 3], soma_um) # [2, 3, 4] ELIXIR
  15. soma_um = fn x -> x + 1 end Enum.map([1,

    2, 3], soma_um) # [2, 3, 4] função anônima ELIXIR
  16. soma_um = fn x -> x + 1 end Enum.map([1,

    2, 3], soma_um) # [2, 3, 4] ELIXIR
  17. soma_um = fn x -> x + 1 end Enum.map([1,

    2, 3], soma_um) # [2, 3, 4] ELIXIR
  18. #

  19. defmodule Matematica do def fatorial(0), do: 1 def fatorial(1), do:

    1 def fatorial(n) do n * fatorial(n-1) end end ELIXIR
  20. defmodule Matematica do def fatorial(0), do: 1 def fatorial(1), do:

    1 def fatorial(n) do n * fatorial(n-1) end end ELIXIR
  21. defmodule Matematica do def fatorial(0), do: 1 def fatorial(1), do:

    1 def fatorial(n) do n * fatorial(n-1) end end ELIXIR
  22. !!Con 2019- Tail Call Optimization: The Musical!! by Anjana Vakil

    & Natalia Margolis https://www.youtube.com/watch?v=-PX0BV9hGZY
  23. ELIXIR Ao invés de escrever isso 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
  24. Enum.reduce([1, 2, 3], 0, fn x, acc -> x +

    acc end) ELIXIR A gente escreve isso
  25. defmodule Calculadora do def soma(a, b) do a + b

    end end Ruby puts "Hello World" ELIXIR
  26. class Calculadora def soma(a, b) a + b end end

    defmodule Calculadora do def soma(a, b) do a + b end end ELIXIR RUBY
  27. case {:ok, "Hello World"} do {:ok, result} -> result {:error,

    _} -> "Oh no!" _ -> "Catch all" end ELIXIR
  28. case {:ok, "Hello World"} do {:ok, result} -> result {:error,

    _} -> "Oh no!" _ -> "Catch all" end ELIXIR
  29. case {:ok, "Hello World"} do {:ok, result} -> result {:error,

    _} -> "Oh no!" _ -> "Catch all" end ELIXIR
  30. case {:ok, "Hello World"} do {:ok, result} -> result {:error,

    _} -> "Oh no!" _ -> "Catch all" end ELIXIR
  31. case {:error, "Invalid credit card"} do {:ok, result} -> result

    {:error, _} -> "Oh no!" _ -> "Catch all" end ELIXIR
  32. case {:error, "Invalid credit card"} do {:ok, result} -> result

    {:error, _} -> "Oh no!" _ -> "Catch all" end ELIXIR
  33. case {:error, "Invalid credit card"} do {:ok, result} -> result

    {:error, _} -> "Oh no!" _ -> "Catch all" end ELIXIR
  34. case {:error, "Invalid credit card"} do {:ok, result} -> result

    {:error, _} -> "Oh no!" _ -> "Catch all" end ELIXIR
  35. defmodule Mensagem do def olar(nome) do nome |> criar_messagem() |>

    String.upcase() end defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end end ELIXIR
  36. defmodule Mensagem do def olar(nome) do nome |> criar_messagem() |>

    String.upcase() end defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end end pública ELIXIR
  37. defmodule Mensagem do def olar(nome) do nome |> criar_messagem() |>

    String.upcase() end defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end end privada ELIXIR
  38. defmodule Mensagem do def olar(nome) do nome |> criar_messagem() |>

    String.upcase() end defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end end ELIXIR dando um zoom…
  39. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end ELIXIR
  40. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end ELIXIR 3 funções com o mesmo nome e mesma quantidade de argumentos
  41. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end ELIXIR function clauses
  42. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end ELIXIR pattern matching vai definir qual função será utilizada
  43. defmodule Mensagem do def olar(nome) do nome |> criar_messagem() |>

    String.upcase() end defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end end ELIXIR
  44. defmodule Mensagem do def olar(nome) do nome |> criar_messagem() |>

    String.upcase() end defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end end ELIXIR
  45. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end
  46. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end
  47. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end
  48. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end
  49. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end
  50. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) when ano != ""

    do "Que bom encontrar vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end guard clause
  51. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) when ano != ""

    do "Que bom encontrar vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end resposta padrão porque o ano não está definido
  52. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) when ano != ""

    do "Que bom encontrar vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end
  53. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{evento: "Rubyconf Brasil"}) do "Que bom encontrar vocês aqui!" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end + uma function clause
  54. defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar

    vocês em #{ano}" end defp criar_messagem(%{evento: "Rubyconf Brasil"}) do "Que bom encontrar vocês aqui!" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end depende da ordem
  55. defp criar_messagem(%{evento: "Rubyconf Brasil"}) do "Que bom encontrar vocês aqui!"

    end defp criar_messagem(%{evento: "Rubyconf Brasil" <> ano}) do "Que bom encontrar vocês em #{ano}" end defp criar_messagem(%{participante: participante}) do "Olá, #{participante}" end defp criar_messagem(_) do "Hey! 🎉" end
  56. iex(5)> Mensagem.olar(%{evento: "Rubyconf Brasil"}) "QUE BOM ENCONTRAR VOCÊS AQUI!" iex(6)>

    Mensagem.olar(%{"evento" => "Rubyconf Brasil 2022"}) iex(7)>
  57. iex(5)> Mensagem.olar(%{evento: "Rubyconf Brasil"}) "QUE BOM ENCONTRAR VOCÊS AQUI!" iex(6)>

    Mensagem.olar(%{"evento" => "Rubyconf Brasil 2022"}) "HEY! 🎉" iex(7)>
  58. iex(5)> Mensagem.olar(%{evento: "Rubyconf Brasil"}) "QUE BOM ENCONTRAR VOCÊS AQUI!" iex(6)>

    Mensagem.olar(%{"evento" => "Rubyconf Brasil 2022"}) "HEY! 🎉" iex(7)>
  59. iex(5)> Mensagem.olar(%{evento: "Rubyconf Brasil"}) "QUE BOM ENCONTRAR VOCÊS AQUI!" iex(6)>

    Mensagem.olar(%{"evento" => "Rubyconf Brasil 2022"}) "HEY! 🎉" iex(7)> Ok, vamos parar por aqui! papo para outro dia
  60. #

  61. POO class Counter def initialize @count = 0 end def

    increment @count = @count + 1 end end c = Counter.new c.increment # @count = 1 c.increment # @count = 2 c.increment # @count = 3 RUBY
  62. POO class Counter def initialize @count = 0 end def

    increment @count = @count + 1 end end c = Counter.new c.increment # @count = 1 c.increment # @count = 2 c.increment # @count = 3 RUBY estado interno do objeto estado implícito um valor diferente para cada chamada
  63. PF defmodule Counter do def increment(count) do count + 1

    end end Counter.increment(1) # 2 Counter.increment(1) # 2 Counter.increment(1) # 2 estado interno do objeto ELIXIR
  64. PF defmodule Counter do def increment(count) do count + 1

    end end Counter.increment(1) # 2 Counter.increment(1) # 2 Counter.increment(1) # 2 estado interno do objeto ELIXIR a mesma resposta para a mesma entrada
  65. O essencial da programação funcional em Elixir, com Ulisses Almeida

    https://pt-br.eventials.com/locaweb/o-essencial-da-programacao-funcional-em-elixir-com-ulisses-almeida/
  66. #

  67. Idioms for Building Distributed Fault-tolerant Applications with Elixir • José

    Valim • GOTO 2014 https://www.youtube.com/watch?v=B4rOG9Bc65Q
  68. Erlang / Elixir BEAM process scheduler core process scheduler core

    Erlang/OTP + Bibliotecas + Princípios de design
  69. ElixirConf 2018 - Erlang OTP What's in the Box -

    João Britto youtube.com/watch?v=CozSfI-Zepw
  70. #

  71. You ain't gonna need write a GenServer - Ulisses Almeida

    (ENG) | Elixir Club Ukraine https://www.youtube.com/watch?v=AZcxoYB9keI
  72. Dívida Técnica Valor de negócio Custo da mudança Tempo How

    to Monetize Application Technical Debt, Gartner, 2011
  73. Lidar com novas features vs migrações Feature Toggles/ Feature Flags

    Código morto (unused code) Context switching
  74. You ain't gonna need write a GenServer - Ulisses Almeida

    (ENG) | Elixir Club Ukraine https://www.youtube.com/watch?v=AZcxoYB9keI
  75. You ain't gonna need write a GenServer - Ulisses Almeida

    (ENG) | Elixir Club Ukraine https://www.youtube.com/watch?v=AZcxoYB9keI
  76. #

  77. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  78. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  79. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  80. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  81. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  82. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  83. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  84. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  85. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  86. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  87. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  88. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  89. Reading code as a beginner defprotocol Size do @doc "Calculates

    the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  90. defprotocol Size do @doc "Calculates the size (and not the

    length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end Wait! Where is the function body? Reading code as a beginner ELIXIR
  91. defprotocol Size do @doc "Calculates the size (and not the

    length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end Wait! Where is the function body? Ah, ok! It's a protocol Reading code as a beginner ELIXIR
  92. defprotocol Size do @doc "Calculates the size (and not the

    length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end Wait! Where is the function body? Ah, ok! It's a protocol But, how do we normally use it? Reading code as a beginner ELIXIR
  93. Reading code as an experienced Elixir programmer defprotocol Size do

    @doc "Calculates the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  94. Reading code as an experienced Elixir programmer defprotocol Size do

    @doc "Calculates the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  95. Reading code as an experienced Elixir programmer defprotocol Size do

    @doc "Calculates the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end Ok, it's a protocol ELIXIR
  96. Reading code as an experienced Elixir programmer defprotocol Size do

    @doc "Calculates the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end Computing some size stuff ELIXIR
  97. Reading code as an experienced Elixir programmer defprotocol Size do

    @doc "Calculates the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  98. Reading code as an experienced Elixir programmer defprotocol Size do

    @doc "Calculates the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end ELIXIR
  99. Reading code as an experienced Elixir programmer defprotocol Size do

    @doc "Calculates the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end For strings and maps ELIXIR
  100. Reading code as an experienced Elixir programmer defprotocol Size do

    @doc "Calculates the size (and not the length!) of a data structure" def size(data) end defimpl Size, for: BitString do def size(string), do: byte_size(string) end defimpl Size, for: Map do def size(map), do: map_size(map) end Ah, ok! It's size and not the length ELIXIR
  101. M L

  102. O essencial da programação funcional em Elixir, com Ulisses Almeida

    https://pt-br.eventials.com/locaweb/o-essencial-da-programacao-funcional-em-elixir-com-ulisses-almeida/
  103. RailsConf 2019 - Maintaining a big open source project: lessons

    learned by Leonardo Tegon https://www.youtube.com/watch?v=rnOcDH_sgxg RUBY
  104. Celebrating the 10 Years of Elixir | José Valim |

    ElixirConf EU 2022 https://www.youtube.com/watch?v=Jf5Hsa1KOc8 ELIXIR