Going off the Rails into
Elixir
Dan Ivovich
DC |> Elixir
March 19, 2019
Why the dev team wants to
❗
AND
Why they should
Who Am I?
Who Am I?
• Software Developer
Who Am I?
• Software Developer
• Director of Development at SmartLogic
Who Am I?
• Software Developer
• Director of Development at SmartLogic
• Rails developer for 12 years
Who Am I?
• Software Developer
• Director of Development at SmartLogic
• Rails developer for 12 years
• Elixir convert since Summer 2016
Who Am I?
• Software Developer
• Director of Development at SmartLogic
• Rails developer for 12 years
• Elixir convert since Summer 2016
• Organizer of the Baltimore Elixir and Erlang
Meetup
Why Devs Love
Elixir
https://unsplash.com/photos/FoKO4DpXamQ
New!
https://unsplash.com/photos/CqKNkmNNLnI
Shiny!
https://unsplash.com/photos/nmUwlzQeQ
Fun!
https://unsplash.com/photos/TVfVo1pga9s
Compiled
https://xkcd.com/303/
But More Seriously
https://unsplash.com/photos/heyiNKAAJWc
Pattern Matching
https://unsplash.com/photos/vdbG0z6YDwM
Pattern Matching
> [1, b, 4] = [1, 5, 4]
[1, 5, 4]
> b
5
> [head | tail] = [1, 2, 3]
[1, 2, 3]
> head
1
> tail
[2, 3]
Pattern Matching
> [1, b, 4] = [1, 5, 4]
[1, 5, 4]
> b
5
> [head | tail] = [1, 2, 3]
[1, 2, 3]
> head
1
> tail
[2, 3]
Pattern Matching
> [1, b, 4] = [1, 5, 4]
[1, 5, 4]
> b
5
> [head | tail] = [1, 2, 3]
[1, 2, 3]
> head
1
> tail
[2, 3]
Pattern Matching
> [1, b, 4] = [1, 5, 4]
[1, 5, 4]
> b
5
> [head | tail] = [1, 2, 3]
[1, 2, 3]
> head
1
> tail
[2, 3]
Pattern Matching
> [1, b, 4] = [1, 5, 4]
[1, 5, 4]
> b
5
> [head | tail] = [1, 2, 3]
[1, 2, 3]
> head
1
> tail
[2, 3]
Pattern Matching
def execute({:ok, value}) do
IO.puts "Execute: #{value}"
end
def execute({:error, reason}) do
IO.puts "Error: #{reason}"
end
> execute({:ok, "Well Done!"})
Execute: Well Done!
> execute({:error, "Fail!"})
Error: Fail!
Pattern Matching
def execute({:ok, value}) do
IO.puts "Execute: #{value}"
end
def execute({:error, reason}) do
IO.puts "Error: #{reason}"
end
> execute({:ok, "Well Done!"})
Execute: Well Done!
> execute({:error, "Fail!"})
Error: Fail!
Pattern Matching
def execute({:ok, value}) do
IO.puts "Execute: #{value}"
end
def execute({:error, reason}) do
IO.puts "Error: #{reason}"
end
> execute({:ok, "Well Done!"})
Execute: Well Done!
> execute({:error, "Fail!"})
Error: Fail!
Pattern Matching
def execute({:ok, value}) do
IO.puts "Execute: #{value}"
end
def execute({:error, reason}) do
IO.puts "Error: #{reason}"
end
> execute({:ok, "Well Done!"})
Execute: Well Done!
> execute({:error, "Fail!"})
Error: Fail!
Pattern Matching
def execute({:ok, value}) do
IO.puts "Execute: #{value}"
end
def execute({:error, reason}) do
IO.puts "Error: #{reason}"
end
> execute({:ok, "Well Done!"})
Execute: Well Done!
> execute({:error, "Fail!"})
Error: Fail!
Pattern Matching
case HTTP.get(url) do
{:ok, %HTTP.Resp{status: 200, body: body}} ->
IO.puts body
{:ok, %HTTP.Resp{status: 404}} ->
IO.puts "Not found!"
{:ok, %HTTP.Resp{status: status}} ->
IO.puts "HTTP Status: #{status}"
{:error, %HTTP.Error{reason: reason}} ->
IO.inspect reason
_ ->
IO.puts "Some other error"
end
Pattern Matching
case HTTP.get(url) do
{:ok, %HTTP.Resp{status: 200, body: body}} ->
IO.puts body
{:ok, %HTTP.Resp{status: 404}} ->
IO.puts "Not found!"
{:ok, %HTTP.Resp{status: status}} ->
IO.puts "HTTP Status: #{status}"
{:error, %HTTP.Error{reason: reason}} ->
IO.inspect reason
_ ->
IO.puts "Some other error"
end
Pattern Matching
case HTTP.get(url) do
{:ok, %HTTP.Resp{status: 200, body: body}} ->
IO.puts body
{:ok, %HTTP.Resp{status: 404}} ->
IO.puts "Not found!"
{:ok, %HTTP.Resp{status: status}} ->
IO.puts "HTTP Status: #{status}"
{:error, %HTTP.Error{reason: reason}} ->
IO.inspect reason
_ ->
IO.puts "Some other error"
end
Pattern Matching
case HTTP.get(url) do
{:ok, %HTTP.Resp{status: 200, body: body}} ->
IO.puts body
{:ok, %HTTP.Resp{status: 404}} ->
IO.puts "Not found!"
{:ok, %HTTP.Resp{status: status}} ->
IO.puts "HTTP Status: #{status}"
{:error, %HTTP.Error{reason: reason}} ->
IO.inspect reason
_ ->
IO.puts "Some other error"
end
Pattern Matching
case HTTP.get(url) do
{:ok, %HTTP.Resp{status: 200, body: body}} ->
IO.puts body
{:ok, %HTTP.Resp{status: 404}} ->
IO.puts "Not found!"
{:ok, %HTTP.Resp{status: status}} ->
IO.puts "HTTP Status: #{status}"
{:error, %HTTP.Error{reason: reason}} ->
IO.inspect reason
_ ->
IO.puts "Some other error"
end
Pattern Matching
case HTTP.get(url) do
{:ok, %HTTP.Resp{status: 200, body: body}} ->
IO.puts body
{:ok, %HTTP.Resp{status: 404}} ->
IO.puts "Not found!"
{:ok, %HTTP.Resp{status: status}} ->
IO.puts "HTTP Status: #{status}"
{:error, %HTTP.Error{reason: reason}} ->
IO.inspect reason
_ ->
IO.puts "Some other error"
end
Pattern Matching
case HTTP.get(url) do
{:ok, %HTTP.Resp{status: 200, body: body}} ->
IO.puts body
{:ok, %HTTP.Resp{status: 404}} ->
IO.puts "Not found!"
{:ok, %HTTP.Resp{status: status}} ->
IO.puts "HTTP Status: #{status}"
{:error, %HTTP.Error{reason: reason}} ->
IO.inspect reason
_ ->
IO.puts "Some other error"
end
Pipe Operator
three = add(1, 2)
six = add(three, 3)
ten = add(six, 4)
ten = add(add(add(1, 2), 3), 4)
ten =
1
|> add(2)
|> add(3)
|> add(4)
Pipe Operator
three = add(1, 2)
six = add(three, 3)
ten = add(six, 4)
ten = add(add(add(1, 2), 3), 4)
ten =
1
|> add(2)
|> add(3)
|> add(4)
Pipe Operator
three = add(1, 2)
six = add(three, 3)
ten = add(six, 4)
ten = add(add(add(1, 2), 3), 4)
ten =
1
|> add(2)
|> add(3)
|> add(4)
Pipe Operator
three = add(1, 2)
six = add(three, 3)
ten = add(six, 4)
ten = add(add(add(1, 2), 3), 4)
ten =
1
|> add(2)
|> add(3)
|> add(4)
Ecto
Changesets
Ecto
Changesets
• Ever try and run just some ActiveRecord
validations depending on the current user?
Ecto
Changesets
• Ever try and run just some ActiveRecord
validations depending on the current user?
• Ever have a set of validations dependent on
data state?
Ecto
Changesets
def edit_self_changeset(user, params  %{}) do
user
|> cast(params, [:name, :age])
|> validate_required([:name])
|> validate_inclusion(:age, 18..100)
end
def admin_edit_changeset(user, params  %{}) do
user
|> cast(params, [:name, :email, :age])
|> validate_required([:name, :email])
|> validate_format(:email, ~r/@/)
|> validate_inclusion(:age, 18..100)
|> unique_constraint(:email)
end
Ecto
Changesets
def edit_self_changeset(user, params  %{}) do
user
|> cast(params, [:name, :age])
|> validate_required([:name])
|> validate_inclusion(:age, 18..100)
end
def admin_edit_changeset(user, params  %{}) do
user
|> cast(params, [:name, :email, :age])
|> validate_required([:name, :email])
|> validate_format(:email, ~r/@/)
|> validate_inclusion(:age, 18..100)
|> unique_constraint(:email)
end
Ecto
Changesets
def edit_self_changeset(user, params  %{}) do
user
|> cast(params, [:name, :age])
|> validate_required([:name])
|> validate_inclusion(:age, 18..100)
end
def admin_edit_changeset(user, params  %{}) do
user
|> cast(params, [:name, :email, :age])
|> validate_required([:name, :email])
|> validate_format(:email, ~r/@/)
|> validate_inclusion(:age, 18..100)
|> unique_constraint(:email)
end
Ecto
Changesets
def edit_self_changeset(user, params  %{}) do
user
|> cast(params, [:name, :age])
|> validate_required([:name])
|> validate_inclusion(:age, 18..100)
end
def admin_edit_changeset(user, params  %{}) do
user
|> cast(params, [:name, :email, :age])
|> validate_required([:name, :email])
|> validate_format(:email, ~r/@/)
|> validate_inclusion(:age, 18..100)
|> unique_constraint(:email)
end
Phoenix
Param Matching
def show(conn, %{"user_params" => user_params} = params) do
end
def show(conn, %{"admin_params" => admin_params} = params) do
end
Phoenix
View Code
Phoenix
View Code
• Not a pile of global namespace helpers
Phoenix
View Code
• Not a pile of global namespace helpers
• Good encapsulation of presentation logic
Gen Server
No need for external workers
GenServer.cast(MyWorker, {:process, this_thing})
def handle_cast({:process, this_thing}, state) do
# do work
{:noreply, state}
end
Gen Server
No need for external workers
GenServer.cast(MyWorker, {:process, this_thing})
def handle_cast({:process, this_thing}, state) do
# do work
{:noreply, state}
end
Gen Server
No need for external workers
GenServer.cast(MyWorker, {:process, this_thing})
def handle_cast({:process, this_thing}, state) do
# do work
{:noreply, state}
end
Management should support
Elixir
https://unsplash.com/photos/FoKO4DpXamQ
All that cool tech didn't
convince you!?!
https://unsplash.com/photos/FO7JIlwjOtU
What does Elixir bring?
What does Elixir bring?
• Ruby-inspired syntax
What does Elixir bring?
• Ruby-inspired syntax
• Meta programming
What does Elixir bring?
• Ruby-inspired syntax
• Meta programming
• Polymorphism via protocols
What does Elixir bring?
• Ruby-inspired syntax
• Meta programming
• Polymorphism via protocols
• Great tooling
What does Elixir bring?
• Ruby-inspired syntax
• Meta programming
• Polymorphism via protocols
• Great tooling
• Better code organization facilities than Erlang
What does Elixir bring?
• Ruby-inspired syntax
• Meta programming
• Polymorphism via protocols
• Great tooling
• Better code organization facilities than Erlang
• Erlang functions can be called from Elixir
What does Elixir bring?
What does Elixir bring?
• Lightweight and isolated concurrency
What does Elixir bring?
• Lightweight and isolated concurrency
• Shared nothing concurrent programming
What does Elixir bring?
• Lightweight and isolated concurrency
• Shared nothing concurrent programming
• Lazy and async collections
What does Elixir bring?
• Lightweight and isolated concurrency
• Shared nothing concurrent programming
• Lazy and async collections
• Pattern matching
What does Elixir bring?
• Lightweight and isolated concurrency
• Shared nothing concurrent programming
• Lazy and async collections
• Pattern matching
• Unicode support and UTF-8 strings
Scaleable and Fault-tolerant
Scaleable and Fault-tolerant
• Isolation means each process is garbage
collected independently
Scaleable and Fault-tolerant
• Isolation means each process is garbage
collected independently
• This means less system wide pauses.
Scaleable and Fault-tolerant
• Isolation means each process is garbage
collected independently
• This means less system wide pauses.
• Things go wrong. Especially with network or
disk activity.
Scaleable and Fault-tolerant
• Isolation means each process is garbage
collected independently
• This means less system wide pauses.
• Things go wrong. Especially with network or
disk activity.
• Supervisor processes are instructed in how to
maintain your application
Stable and Extensible
Stable and Extensible
• Only 1 planned language deprecation for 2.0
Stable and Extensible
• Only 1 planned language deprecation for 2.0
• No planned timeline for 2.0
Stable and Extensible
• Only 1 planned language deprecation for 2.0
• No planned timeline for 2.0
• The core team believes all the right
fundamentals are in place
Speed (Throughput)
Speed (Throughput)
• Sure, it isn't C
Speed (Throughput)
• Sure, it isn't C
• For a Rails shop, that isn't the benchmark
Speed (Throughput)
• Sure, it isn't C
• For a Rails shop, that isn't the benchmark
• Multi-thread by default, no global lock
Speed (Throughput)
• Sure, it isn't C
• For a Rails shop, that isn't the benchmark
• Multi-thread by default, no global lock
• Fast garbage collection
Speed (Throughput)
• Sure, it isn't C
• For a Rails shop, that isn't the benchmark
• Multi-thread by default, no global lock
• Fast garbage collection
• All means high throughput web apps
Used by Big Names
Used by Big Names
• Discord
Used by Big Names
• Discord
• Pagerduty
Used by Big Names
• Discord
• Pagerduty
• Bleacher Report
Used by Big Names
• Discord
• Pagerduty
• Bleacher Report
• Square Enix
Used by Big Names
• Discord
• Pagerduty
• Bleacher Report
• Square Enix
• Motorola
Used by Big Names
• Discord
• Pagerduty
• Bleacher Report
• Square Enix
• Motorola
• https://elixir-companies.com/browse
Costs
All of the items we've discussed have a real impact on:
Costs
All of the items we've discussed have a real impact on:
• Development pace, build from pure functions
Costs
All of the items we've discussed have a real impact on:
• Development pace, build from pure functions
• Developer focus, cognitive load of functions over
objects
Costs
All of the items we've discussed have a real impact on:
• Development pace, build from pure functions
• Developer focus, cognitive load of functions over
objects
• Ease of implementing new features
Costs
All of the items we've discussed have a real impact on:
• Development pace, build from pure functions
• Developer focus, cognitive load of functions over
objects
• Ease of implementing new features
• Test quality and speed
Costs
All of the items we've discussed have a real impact on:
• Development pace, build from pure functions
• Developer focus, cognitive load of functions over
objects
• Ease of implementing new features
• Test quality and speed
• Bug rates
Costs
All of the items we've discussed have a real impact on:
• Development pace, build from pure functions
• Developer focus, cognitive load of functions over
objects
• Ease of implementing new features
• Test quality and speed
• Bug rates
• Maintainability
Staffing
Staffing
• Innovative tech attracts innovative developers
Staffing
• Innovative tech attracts innovative developers
• Syntax is approachable
Staffing
• Innovative tech attracts innovative developers
• Syntax is approachable
• Resources are plentiful
Staffing
• Innovative tech attracts innovative developers
• Syntax is approachable
• Resources are plentiful
• Training is easy, and fun
Paradigm Shift?
Functional Programming
Paradigm Shift?
Functional Programming
• Might take some adjustment
Paradigm Shift?
Functional Programming
• Might take some adjustment
• Fits your use case more than you expect, it is
about the data
Paradigm Shift?
Functional Programming
• Might take some adjustment
• Fits your use case more than you expect, it is
about the data
• Makes writing great tests easy
Paradigm Shift?
Functional Programming
• Might take some adjustment
• Fits your use case more than you expect, it is
about the data
• Makes writing great tests easy
• Makes writing fast tests easy
Ecosystem and Resources
https://unsplash.com/photos/FzrjgIId6NU
Mix and IEx
Mix - A great build tool for dependency
management and other tasks
IEx - An interactive shell
Docs, Tests, and DocTests
Documentation - a first class citizen in the
Elixir ecosystem
Tests - Testing libraries built into the language
with ExUnit
DocTests - A hybrid of testing and documentation
What is Next
https://unsplash.com/photos/FoKO4DpXamQ
Getting Started
See my other talks
https://www.danivovich.com/other
Resources - Books
Programming Elixir
https://pragprog.com/book/elixir16/programming-elixir-1-6
Programming Phoenix
https://pragprog.com/book/phoenix14/programming-phoenix-1-4
Metaprogramming Elixir
https://pragprog.com/book/cmelixir/metaprogramming-elixir
Functional Web Development with Elixir, OTP, and Phoenix
https://pragprog.com/book/lhelph/functional-web-development-with-
elixir-otp-and-phoenix
Resources - Newsletters
Elixir Radar
http://plataformatec.com.br/elixir-radar
Elixir Weekly
https://elixirweekly.net/
Elixir Digest
https://elixirdigest.net
Resources - Conferences
ElixirConf EU (April 8-10, Prague)
http://www.elixirconf.eu/
EMPEX NYC (May 18, NYC)
http://empex.co/nyc
ElixirConf (August, Colorado)
https://elixirconf.com/
Resources - Podcasts
Smart Software with SmartLogic (First Season on Elixir in
Production)
https://podcast.smartlogic.io/
Elixir Outlaws Podcast
https://elixiroutlaws.com/
ElixirTalk Podcast
http://elixirtalk.com/
Elixir Mix Podcast
https://devchat.tv/elixir-mix
Resources - Meetups
DC
https://www.meetup.com/DC-Elixir/
Baltimore
https://www.meetup.com/Baltimore-Elixir-and-
Erlang-Meetup/
Resources - Others
Elixir Status Twitter
https://twitter.com/elixirstatus
Elixir Slack
http://elixir-slackin.herokuapp.com/
Elixir Forum
https://elixirforum.com
❤
We hope you will too
Questions? ❔

DC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich

  • 1.
    Going off theRails into Elixir Dan Ivovich DC |> Elixir March 19, 2019
  • 2.
    Why the devteam wants to ❗ AND Why they should
  • 3.
  • 4.
    Who Am I? •Software Developer
  • 5.
    Who Am I? •Software Developer • Director of Development at SmartLogic
  • 6.
    Who Am I? •Software Developer • Director of Development at SmartLogic • Rails developer for 12 years
  • 7.
    Who Am I? •Software Developer • Director of Development at SmartLogic • Rails developer for 12 years • Elixir convert since Summer 2016
  • 8.
    Who Am I? •Software Developer • Director of Development at SmartLogic • Rails developer for 12 years • Elixir convert since Summer 2016 • Organizer of the Baltimore Elixir and Erlang Meetup
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
    Pattern Matching > [1,b, 4] = [1, 5, 4] [1, 5, 4] > b 5 > [head | tail] = [1, 2, 3] [1, 2, 3] > head 1 > tail [2, 3]
  • 17.
    Pattern Matching > [1,b, 4] = [1, 5, 4] [1, 5, 4] > b 5 > [head | tail] = [1, 2, 3] [1, 2, 3] > head 1 > tail [2, 3]
  • 18.
    Pattern Matching > [1,b, 4] = [1, 5, 4] [1, 5, 4] > b 5 > [head | tail] = [1, 2, 3] [1, 2, 3] > head 1 > tail [2, 3]
  • 19.
    Pattern Matching > [1,b, 4] = [1, 5, 4] [1, 5, 4] > b 5 > [head | tail] = [1, 2, 3] [1, 2, 3] > head 1 > tail [2, 3]
  • 20.
    Pattern Matching > [1,b, 4] = [1, 5, 4] [1, 5, 4] > b 5 > [head | tail] = [1, 2, 3] [1, 2, 3] > head 1 > tail [2, 3]
  • 21.
    Pattern Matching def execute({:ok,value}) do IO.puts "Execute: #{value}" end def execute({:error, reason}) do IO.puts "Error: #{reason}" end > execute({:ok, "Well Done!"}) Execute: Well Done! > execute({:error, "Fail!"}) Error: Fail!
  • 22.
    Pattern Matching def execute({:ok,value}) do IO.puts "Execute: #{value}" end def execute({:error, reason}) do IO.puts "Error: #{reason}" end > execute({:ok, "Well Done!"}) Execute: Well Done! > execute({:error, "Fail!"}) Error: Fail!
  • 23.
    Pattern Matching def execute({:ok,value}) do IO.puts "Execute: #{value}" end def execute({:error, reason}) do IO.puts "Error: #{reason}" end > execute({:ok, "Well Done!"}) Execute: Well Done! > execute({:error, "Fail!"}) Error: Fail!
  • 24.
    Pattern Matching def execute({:ok,value}) do IO.puts "Execute: #{value}" end def execute({:error, reason}) do IO.puts "Error: #{reason}" end > execute({:ok, "Well Done!"}) Execute: Well Done! > execute({:error, "Fail!"}) Error: Fail!
  • 25.
    Pattern Matching def execute({:ok,value}) do IO.puts "Execute: #{value}" end def execute({:error, reason}) do IO.puts "Error: #{reason}" end > execute({:ok, "Well Done!"}) Execute: Well Done! > execute({:error, "Fail!"}) Error: Fail!
  • 26.
    Pattern Matching case HTTP.get(url)do {:ok, %HTTP.Resp{status: 200, body: body}} -> IO.puts body {:ok, %HTTP.Resp{status: 404}} -> IO.puts "Not found!" {:ok, %HTTP.Resp{status: status}} -> IO.puts "HTTP Status: #{status}" {:error, %HTTP.Error{reason: reason}} -> IO.inspect reason _ -> IO.puts "Some other error" end
  • 27.
    Pattern Matching case HTTP.get(url)do {:ok, %HTTP.Resp{status: 200, body: body}} -> IO.puts body {:ok, %HTTP.Resp{status: 404}} -> IO.puts "Not found!" {:ok, %HTTP.Resp{status: status}} -> IO.puts "HTTP Status: #{status}" {:error, %HTTP.Error{reason: reason}} -> IO.inspect reason _ -> IO.puts "Some other error" end
  • 28.
    Pattern Matching case HTTP.get(url)do {:ok, %HTTP.Resp{status: 200, body: body}} -> IO.puts body {:ok, %HTTP.Resp{status: 404}} -> IO.puts "Not found!" {:ok, %HTTP.Resp{status: status}} -> IO.puts "HTTP Status: #{status}" {:error, %HTTP.Error{reason: reason}} -> IO.inspect reason _ -> IO.puts "Some other error" end
  • 29.
    Pattern Matching case HTTP.get(url)do {:ok, %HTTP.Resp{status: 200, body: body}} -> IO.puts body {:ok, %HTTP.Resp{status: 404}} -> IO.puts "Not found!" {:ok, %HTTP.Resp{status: status}} -> IO.puts "HTTP Status: #{status}" {:error, %HTTP.Error{reason: reason}} -> IO.inspect reason _ -> IO.puts "Some other error" end
  • 30.
    Pattern Matching case HTTP.get(url)do {:ok, %HTTP.Resp{status: 200, body: body}} -> IO.puts body {:ok, %HTTP.Resp{status: 404}} -> IO.puts "Not found!" {:ok, %HTTP.Resp{status: status}} -> IO.puts "HTTP Status: #{status}" {:error, %HTTP.Error{reason: reason}} -> IO.inspect reason _ -> IO.puts "Some other error" end
  • 31.
    Pattern Matching case HTTP.get(url)do {:ok, %HTTP.Resp{status: 200, body: body}} -> IO.puts body {:ok, %HTTP.Resp{status: 404}} -> IO.puts "Not found!" {:ok, %HTTP.Resp{status: status}} -> IO.puts "HTTP Status: #{status}" {:error, %HTTP.Error{reason: reason}} -> IO.inspect reason _ -> IO.puts "Some other error" end
  • 32.
    Pattern Matching case HTTP.get(url)do {:ok, %HTTP.Resp{status: 200, body: body}} -> IO.puts body {:ok, %HTTP.Resp{status: 404}} -> IO.puts "Not found!" {:ok, %HTTP.Resp{status: status}} -> IO.puts "HTTP Status: #{status}" {:error, %HTTP.Error{reason: reason}} -> IO.inspect reason _ -> IO.puts "Some other error" end
  • 33.
    Pipe Operator three =add(1, 2) six = add(three, 3) ten = add(six, 4) ten = add(add(add(1, 2), 3), 4) ten = 1 |> add(2) |> add(3) |> add(4)
  • 34.
    Pipe Operator three =add(1, 2) six = add(three, 3) ten = add(six, 4) ten = add(add(add(1, 2), 3), 4) ten = 1 |> add(2) |> add(3) |> add(4)
  • 35.
    Pipe Operator three =add(1, 2) six = add(three, 3) ten = add(six, 4) ten = add(add(add(1, 2), 3), 4) ten = 1 |> add(2) |> add(3) |> add(4)
  • 36.
    Pipe Operator three =add(1, 2) six = add(three, 3) ten = add(six, 4) ten = add(add(add(1, 2), 3), 4) ten = 1 |> add(2) |> add(3) |> add(4)
  • 37.
  • 38.
    Ecto Changesets • Ever tryand run just some ActiveRecord validations depending on the current user?
  • 39.
    Ecto Changesets • Ever tryand run just some ActiveRecord validations depending on the current user? • Ever have a set of validations dependent on data state?
  • 40.
    Ecto Changesets def edit_self_changeset(user, params %{}) do user |> cast(params, [:name, :age]) |> validate_required([:name]) |> validate_inclusion(:age, 18..100) end def admin_edit_changeset(user, params %{}) do user |> cast(params, [:name, :email, :age]) |> validate_required([:name, :email]) |> validate_format(:email, ~r/@/) |> validate_inclusion(:age, 18..100) |> unique_constraint(:email) end
  • 41.
    Ecto Changesets def edit_self_changeset(user, params %{}) do user |> cast(params, [:name, :age]) |> validate_required([:name]) |> validate_inclusion(:age, 18..100) end def admin_edit_changeset(user, params %{}) do user |> cast(params, [:name, :email, :age]) |> validate_required([:name, :email]) |> validate_format(:email, ~r/@/) |> validate_inclusion(:age, 18..100) |> unique_constraint(:email) end
  • 42.
    Ecto Changesets def edit_self_changeset(user, params %{}) do user |> cast(params, [:name, :age]) |> validate_required([:name]) |> validate_inclusion(:age, 18..100) end def admin_edit_changeset(user, params %{}) do user |> cast(params, [:name, :email, :age]) |> validate_required([:name, :email]) |> validate_format(:email, ~r/@/) |> validate_inclusion(:age, 18..100) |> unique_constraint(:email) end
  • 43.
    Ecto Changesets def edit_self_changeset(user, params %{}) do user |> cast(params, [:name, :age]) |> validate_required([:name]) |> validate_inclusion(:age, 18..100) end def admin_edit_changeset(user, params %{}) do user |> cast(params, [:name, :email, :age]) |> validate_required([:name, :email]) |> validate_format(:email, ~r/@/) |> validate_inclusion(:age, 18..100) |> unique_constraint(:email) end
  • 44.
    Phoenix Param Matching def show(conn,%{"user_params" => user_params} = params) do end def show(conn, %{"admin_params" => admin_params} = params) do end
  • 45.
  • 46.
    Phoenix View Code • Nota pile of global namespace helpers
  • 47.
    Phoenix View Code • Nota pile of global namespace helpers • Good encapsulation of presentation logic
  • 48.
    Gen Server No needfor external workers GenServer.cast(MyWorker, {:process, this_thing}) def handle_cast({:process, this_thing}, state) do # do work {:noreply, state} end
  • 49.
    Gen Server No needfor external workers GenServer.cast(MyWorker, {:process, this_thing}) def handle_cast({:process, this_thing}, state) do # do work {:noreply, state} end
  • 50.
    Gen Server No needfor external workers GenServer.cast(MyWorker, {:process, this_thing}) def handle_cast({:process, this_thing}, state) do # do work {:noreply, state} end
  • 51.
  • 52.
    All that cooltech didn't convince you!?! https://unsplash.com/photos/FO7JIlwjOtU
  • 53.
  • 54.
    What does Elixirbring? • Ruby-inspired syntax
  • 55.
    What does Elixirbring? • Ruby-inspired syntax • Meta programming
  • 56.
    What does Elixirbring? • Ruby-inspired syntax • Meta programming • Polymorphism via protocols
  • 57.
    What does Elixirbring? • Ruby-inspired syntax • Meta programming • Polymorphism via protocols • Great tooling
  • 58.
    What does Elixirbring? • Ruby-inspired syntax • Meta programming • Polymorphism via protocols • Great tooling • Better code organization facilities than Erlang
  • 59.
    What does Elixirbring? • Ruby-inspired syntax • Meta programming • Polymorphism via protocols • Great tooling • Better code organization facilities than Erlang • Erlang functions can be called from Elixir
  • 60.
  • 61.
    What does Elixirbring? • Lightweight and isolated concurrency
  • 62.
    What does Elixirbring? • Lightweight and isolated concurrency • Shared nothing concurrent programming
  • 63.
    What does Elixirbring? • Lightweight and isolated concurrency • Shared nothing concurrent programming • Lazy and async collections
  • 64.
    What does Elixirbring? • Lightweight and isolated concurrency • Shared nothing concurrent programming • Lazy and async collections • Pattern matching
  • 65.
    What does Elixirbring? • Lightweight and isolated concurrency • Shared nothing concurrent programming • Lazy and async collections • Pattern matching • Unicode support and UTF-8 strings
  • 66.
  • 67.
    Scaleable and Fault-tolerant •Isolation means each process is garbage collected independently
  • 68.
    Scaleable and Fault-tolerant •Isolation means each process is garbage collected independently • This means less system wide pauses.
  • 69.
    Scaleable and Fault-tolerant •Isolation means each process is garbage collected independently • This means less system wide pauses. • Things go wrong. Especially with network or disk activity.
  • 70.
    Scaleable and Fault-tolerant •Isolation means each process is garbage collected independently • This means less system wide pauses. • Things go wrong. Especially with network or disk activity. • Supervisor processes are instructed in how to maintain your application
  • 71.
  • 72.
    Stable and Extensible •Only 1 planned language deprecation for 2.0
  • 73.
    Stable and Extensible •Only 1 planned language deprecation for 2.0 • No planned timeline for 2.0
  • 74.
    Stable and Extensible •Only 1 planned language deprecation for 2.0 • No planned timeline for 2.0 • The core team believes all the right fundamentals are in place
  • 75.
  • 76.
  • 77.
    Speed (Throughput) • Sure,it isn't C • For a Rails shop, that isn't the benchmark
  • 78.
    Speed (Throughput) • Sure,it isn't C • For a Rails shop, that isn't the benchmark • Multi-thread by default, no global lock
  • 79.
    Speed (Throughput) • Sure,it isn't C • For a Rails shop, that isn't the benchmark • Multi-thread by default, no global lock • Fast garbage collection
  • 80.
    Speed (Throughput) • Sure,it isn't C • For a Rails shop, that isn't the benchmark • Multi-thread by default, no global lock • Fast garbage collection • All means high throughput web apps
  • 81.
  • 82.
    Used by BigNames • Discord
  • 83.
    Used by BigNames • Discord • Pagerduty
  • 84.
    Used by BigNames • Discord • Pagerduty • Bleacher Report
  • 85.
    Used by BigNames • Discord • Pagerduty • Bleacher Report • Square Enix
  • 86.
    Used by BigNames • Discord • Pagerduty • Bleacher Report • Square Enix • Motorola
  • 87.
    Used by BigNames • Discord • Pagerduty • Bleacher Report • Square Enix • Motorola • https://elixir-companies.com/browse
  • 88.
    Costs All of theitems we've discussed have a real impact on:
  • 89.
    Costs All of theitems we've discussed have a real impact on: • Development pace, build from pure functions
  • 90.
    Costs All of theitems we've discussed have a real impact on: • Development pace, build from pure functions • Developer focus, cognitive load of functions over objects
  • 91.
    Costs All of theitems we've discussed have a real impact on: • Development pace, build from pure functions • Developer focus, cognitive load of functions over objects • Ease of implementing new features
  • 92.
    Costs All of theitems we've discussed have a real impact on: • Development pace, build from pure functions • Developer focus, cognitive load of functions over objects • Ease of implementing new features • Test quality and speed
  • 93.
    Costs All of theitems we've discussed have a real impact on: • Development pace, build from pure functions • Developer focus, cognitive load of functions over objects • Ease of implementing new features • Test quality and speed • Bug rates
  • 94.
    Costs All of theitems we've discussed have a real impact on: • Development pace, build from pure functions • Developer focus, cognitive load of functions over objects • Ease of implementing new features • Test quality and speed • Bug rates • Maintainability
  • 95.
  • 96.
    Staffing • Innovative techattracts innovative developers
  • 97.
    Staffing • Innovative techattracts innovative developers • Syntax is approachable
  • 98.
    Staffing • Innovative techattracts innovative developers • Syntax is approachable • Resources are plentiful
  • 99.
    Staffing • Innovative techattracts innovative developers • Syntax is approachable • Resources are plentiful • Training is easy, and fun
  • 100.
  • 101.
  • 102.
    Paradigm Shift? Functional Programming •Might take some adjustment • Fits your use case more than you expect, it is about the data
  • 103.
    Paradigm Shift? Functional Programming •Might take some adjustment • Fits your use case more than you expect, it is about the data • Makes writing great tests easy
  • 104.
    Paradigm Shift? Functional Programming •Might take some adjustment • Fits your use case more than you expect, it is about the data • Makes writing great tests easy • Makes writing fast tests easy
  • 105.
  • 106.
    Mix and IEx Mix- A great build tool for dependency management and other tasks IEx - An interactive shell
  • 107.
    Docs, Tests, andDocTests Documentation - a first class citizen in the Elixir ecosystem Tests - Testing libraries built into the language with ExUnit DocTests - A hybrid of testing and documentation
  • 108.
  • 109.
    Getting Started See myother talks https://www.danivovich.com/other
  • 110.
    Resources - Books ProgrammingElixir https://pragprog.com/book/elixir16/programming-elixir-1-6 Programming Phoenix https://pragprog.com/book/phoenix14/programming-phoenix-1-4 Metaprogramming Elixir https://pragprog.com/book/cmelixir/metaprogramming-elixir Functional Web Development with Elixir, OTP, and Phoenix https://pragprog.com/book/lhelph/functional-web-development-with- elixir-otp-and-phoenix
  • 111.
    Resources - Newsletters ElixirRadar http://plataformatec.com.br/elixir-radar Elixir Weekly https://elixirweekly.net/ Elixir Digest https://elixirdigest.net
  • 112.
    Resources - Conferences ElixirConfEU (April 8-10, Prague) http://www.elixirconf.eu/ EMPEX NYC (May 18, NYC) http://empex.co/nyc ElixirConf (August, Colorado) https://elixirconf.com/
  • 113.
    Resources - Podcasts SmartSoftware with SmartLogic (First Season on Elixir in Production) https://podcast.smartlogic.io/ Elixir Outlaws Podcast https://elixiroutlaws.com/ ElixirTalk Podcast http://elixirtalk.com/ Elixir Mix Podcast https://devchat.tv/elixir-mix
  • 114.
  • 115.
    Resources - Others ElixirStatus Twitter https://twitter.com/elixirstatus Elixir Slack http://elixir-slackin.herokuapp.com/ Elixir Forum https://elixirforum.com
  • 116.
  • 117.
    We hope youwill too
  • 118.