SlideShare ist ein Scribd-Unternehmen logo
"Hallo " <> "Elixir"
Mirko Zeibig
(mirko.zeibig@t-systems.com)
Agenda
●
Basis
●
Sprache
●
OTP
●
Ausblick
BEAM
[Bogdan‘s|Björn‘s] Erlang Abstract Machine
JVM
Java Virtual Machine
Elixir
•
mix
•
hex
•
ExUnit
Compiler, Tools, Runtime Library Compiler, Tools, Runtime Library
•
Gradle
•
Maven
•
JUnit
OTP
JDK
Sprache
●
Funktionale Sprache
●
Dynamisches Typsystem
●
Module
●
Garbage Collection
●
REPL (iex)
arity
●
Anzahl der Parameter einer Funktion
– alle Parameter auch optionale Parameter mit default
●
ähnlich der Methodensignatur in Java
– da Parameter keine Typen haben
●
[Modulname].[Funktionsname]/[Parameterzahl]
– Enum.map/2
– Enum.map_join/2
– Enum.map_join/3
– File.write/2
iex
●
interaktive shell
●
integrierte Hilfe
●
h/0, h/1
●
i/1
●
c/1
●
r/1
:observer.start
Funktionen
●
named function
def add(a, b  1) do
a + b
end
def square(a) do
a * a
end
add(40, 2)
add(41)
square(3)
Funktionen
●
anonymous function
f = fn x -> x * x end
f.(3)
Funktionen
●
function capturing
f = &square(&1)
f.(3)
Funktionen
●
guard clauses
def gt(a, b) when a > b do
:gt
end
def gt(a, b) when a < b do
:lt
end
def gt(a, b) when a == b do
:eq
end
Module
●
alle named functions müssen in Module
●
Schachtelung möglich
defmodule DevDay.Functions do
def add(a, b  1) do
a + b
end
defmodule MoreFunctions do
def square(a) do
a * a
end
end
end
Datentypen - immutable
●
string
●
integer
●
float
●
boolean
●
atom
●
range
●
tuple
●
list
●
map
●
struct
●
binary
●
pid
●
references
integer
●
Haben keine fixe Größe
●
2019
●
0xbabe
●
0x765
●
0b1011
●
1_000_000
integer
float
●
IEEE 754 double precision
●
1.0
●
3.14159
●
0.314159e1
●
314159.0e-5
:atoms
●
Konstanten deren Name der Wert ist
●
:devday
●
:devday2019
●
:devday@2019
●
:devday!
●
:hugbúnaðurVerktaki
●
:"Pippilotta Viktualia … Efraimsdotter Långstrump"
range
●
Von – bis Werte
●
1..10
●
10..1
●
0x13..0o777
tuples
●
Geordnete Menge von Werten
●
{42, :devday, "Radebeul"}
●
File.read("existing.file")
{:ok, "inhalt der Datei"}
●
File.read("nonexisting.file")
{:error, :enoent}
Keyword lists
●
Liste von Zwei-Element-Tuples
●
Keys sind Atome und nicht eindeutig
●
[foo: "bar", hello: "world"]
●
[{:foo, "bar"}, {:hello, "world"}]
●
x = [foo: "bar", hello: "world"]
●
x[:hello]
"world"
List
●
Verkettete Liste beliebiger Werte
●
list = [42, :devday, "Radebeul"]
●
["hello"] ++ list
["hello", 42, :devday, "Radebeul"]
●
list ++ ["world"]
[42, :devday, "Radebeul", "world"]
List
●
list = [42, :devday, "Radebeul"]
●
list -- [42]
[:devday, "Radebeul"]
●
hd(list)
42
●
tl(list)
[:devday, "Radebeul"]
●
["hallo" | [:devday, "Radebeul"]]
["hallo", :devday, "Radebeul"]]
Map
●
Key-Value-Speicher
●
map = %{:answer => 42, "was" => :devday, "wo" => "Radebeul"}
●
map[:answer]
42
●
map["was"]
:devday
●
map["wo"]
"Radebeul"
Map
●
map = %{answer: 42, was: :devday, wo: "Radebeul"}
●
map.answer
42
●
map.was
:devday
●
map.wo
"Radebeul"
●
%{map | answer: 3.14}
Enum (Module)
●
bietet Funktionen zu Arbeit mit Enumerables
– each/2
– filter/2
– map/2
– reduce/2
– join/2
– empty?/1
– any?/2
– all?/2
|> (pipe)
speakers = ["Mirko", "Emil", "Ida",
"Lina", "Alfred", "Alma", "Anton",
"Lukas", "Lotta"]
speakers
|> Enum.filter(fn s ->
String.length(s) > 3 end)
|> Enum.map(fn s ->
String.upcase(s) end)
|> Enum.sort()
|> Enum.each(fn s ->
IO.puts(s) end)
List<String> speakers =
Arrays.asList("Mirko", "Emil",
"Ida", "Lina", "Alfred", "Alma",
"Anton", "Lukas", "Lotta");
speakers.stream()
.filter(s ->
s.length() > 3)
.map(s ->
s.toUpperCase())
.sorted()
.peek(s ->
System.out.println(s));
|> (pipe)
speakers = ["Mirko", "Emil", "Ida",
"Lina", "Alfred", "Alma", "Anton",
"Lukas", "Lotta"]
speakers
|> Enum.filter(fn s ->
String.length(s) > 3 end)
|> Enum.map(fn s ->
String.upcase(s) end)
|> Enum.sort()
|> Enum.each(fn s ->
IO.puts(s) end)
List<String> speakers =
Arrays.asList("Mirko", "Emil",
"Ida", "Lina", "Alfred", "Alma",
"Anton", "Lukas", "Lotta");
speakers.stream()
.filter(s ->
s.length() > 3)
.map(s ->
s.toUpperCase())
.sorted()
.peek(s ->
System.out.println(s))
.collect(Collectors.toList());
|> (pipe)
speakers = ["Mirko", "Emil", "Ida",
"Lina", "Alfred", "Alma", "Anton",
"Lukas", "Lotta"]
speakers
|> Enum.filter(&String.length(&1)
> 3)
|> Enum.map(&String.upcase(&1))
|> Enum.sort()
|> Enum.each(&IO.puts(&1))
List<String> speakers =
Arrays.asList("Mirko", "Emil",
"Ida", "Lina", "Alfred", "Alma",
"Anton", "Lukas", "Lotta");
speakers.stream()
.filter(s ->
s.length() > 3)
.map(String::toUpperCase)
.sorted()
.peek(System.out::println)
.collect(Collectors.toList());
Struct
defmodule DevDay.Speaker do
alias __MODULE__
defstruct [:name, :age, :sessions]
def new(name) do
%Speaker{name: name}
end
end
Strings
●
String ist eigentlich kein eigener Typ
●
Zwei Typen von Strings
●
"" vs. ''
●
UTF-8
●
String interpolation
– "Hallo #{dd}!"
Strings – single quoted
●
Character Lists
●
Liste von Integer Codepoints
– 'DevDay' → [68,101,118,68,97,121]
– 'Måla' → [77, 229, 108, 97]
– 'noël' → [110, 111, 101, 776, 108]
●
es funktionieren alle Funktionen auf Listen
●
wird für Erlang-Interoperabilität benötigt
Strings – double quoted
●
Binaries
●
Sequenz von Bits
– "DevDay" → <<68,101,118,68,97,121>>
– "Måla" → <<77, 229, 108, 97>>
– "noël" → <<110, 111, 101, 776, 108>>
●
dies sind die Standard-Strings
String - noël
●
String.codepoints "noeu0308l"
["n","o","e","¨", "l"]
●
String.graphemes "noeu0308l"
["n", "o", "ë", "l"]
●
String.reverse "noeu0308l"
"lëon"
●
String.slice("noeu0308l", 0, 3)
"noë"
●
String.length "noeu0308l"
4
String – hä?
●
"hä?" == "hau0308?"
false
●
"hä?" == "hä?"
true
●
String.equivalent?("hä?", "hau0308?")
true
●
String.equivalent?("hä?", "hä?")
true
Pattern Matching
●
= ist in Elixir 'match operator'
●
wenn linke und rechte Seite matchen → alles ok
●
wenn nicht → MatchError
●
enthält linke Seite Variablen, werden bei match
Werte zugewiesen
●
funktioniert in Elixir fast überall
Pattern Matching
●
1 = 1
1
●
x = 1
1
●
1 = x
1
●
2 = x
** (MatchError) no match of right hand side value: 1
Pattern Matching
●
{a, b, c} = {"Hallo", "DevDay", 2019}
{"Hallo", "DevDay", 2019}
●
a
"Hallo"
●
b
"DevDay"
●
{a, b, 2018} = {"Hallo", "DevDay", 2019}
** (MatchError) no match of right hand side value: {"Hallo",
"DevDay", 2019}
Pattern Matching
●
[a, b, c] = [3, 14, 42]
[3, 14, 42]
●
[head | tail] = [3, 14, 42]
[3, 14, 42]
●
head
3
●
tail
[14, 42]
●
[head | tail] = []
** (MatchError) no match of right hand side value: []
Pattern Matching - case
def casematch(t) do
case t do
{1, 2, 3} ->
"das paßt nicht"
{3, 14, x} ->
"Die Antwort ist #{x}."
_ ->
"der Rest"
end
end
IO.puts casematch({1, 2, 3})
IO.puts casematch({3, 14, 42})
IO.puts casematch("DevDay")
Pattern Matching - case
def file_match() do
case File.read("/devday/speakers.txt") do
{:ok, data} -> tuwas(data)
{:error, reason} -> "#{:file.format_error(reason)}"
end
end
iex(1)> DevDay.Match.file_match
"no such file or directory"
Pattern Matching - function
def sum([]) do
0
end
def sum([head|tail]) do
head + sum(tail)
end
iex(3)> DevDay.Match.sum([1,2,3,4,5])
15
Prozesse
●
Wo man in Java ein Objekt erzeugt, startet man in
Elixir einen Prozeß.
●
keine OS-Prozesse oder -Threads
●
sehr leichtgewichtig
●
von VM verwaltet
●
isoliert – keine gemeinsamen Resourcen
●
kein lokales Errorhandling
●
kommuniyieren über Messages
Prozesse
defmodule DevDay.HelloProc do
def simple_hallo() do
IO.puts "Hallo"
end
end
iex(6)> DevDay.HelloProc.simple_hallo
Hallo
:ok
iex(7)> spawn(DevDay.HelloProc, :simple_hallo, [])
Hallo
#PID<0.155.0>
Prozesse - Messages
def hallo() do
receive do
{sender, msg} -> send(sender, {:ok, "Hallo, #{msg}!"})
end
end
iex> pid = spawn(DevDay.HelloProc, :hallo, [])
iex> send(pid, {self(), "DevDay"})
iex> receive do
{:ok, message} -> IO.puts message
end
Hallo, DevDay!
:ok
Prozesse - link
●
spawn/3 - startet neuen Prozeß
– im Fehlerfall wird er beendet
●
spawn_link/3 - startet neuen Prozeß und
verknüpft ihn mit dem Parent
– im Fehlerfall wird der verknüpfte Prozeß mit beendet
●
spawn_monitor/3 – startet neuen Prozeß und
überwacht ihn
– im Fehlerfall wird eine Nachricht verschickt
Prozesse - link
Prozesse - link
?
!
Prozesse - state
●
Daten sind unveränderlich
●
Funktionen sind stateless
●
Objekte gibt es nicht
●
Wer hält einen state?
→ Prozesse
defmodule DevDay.Simple do
def start_link do
spawn_link(__MODULE__, :loop, [%{}])
end
def loop(state) do
receive do
{:add, name} ->
new_state = Map.put(state, name, Speaker.new(name))
loop(new_state)
{:remove, name} ->
new_state = Map.delete(state, name)
loop(new_state)
{:list, pid} ->
send(pid, {:ok, state})
loop(state)
end
end
end
GenServer
●
Abstraktion für Server
●
Verarbeitet Nachrichten synchron/asynchron
●
Kümmert sich um
– Loop
– State
– Start
– Stop
●
Definiert Callbacks
defmodule DevDay.SpeakerServer do
use GenServer
def init(:ok) do
{:ok, %{}}
end
def handle_cast({:add, name}, state) do
new_state = Map.put(state, name, DevDay.Speaker.new(name))
{:noreply, new_state}
end
def handle_cast({:remove, name}, state) do
new_state = Map.delete(state, name)
{:noreply, new_state}
end
def handle_call(:speakers, _from, state) do
{:reply, state, state}
end
end
GenServer - Client
iex(1)> {:ok, pid} =
GenServer.start_link(DevDay.SpeakerServer, :ok)
{:ok, #PID<0.212.0>}
iex(2)> GenServer.call(pid, :speakers)
%{}
iex(3)> GenServer.cast(pid, {:add, "Mirko"})
:ok
iex(4)> GenServer.call(pid, :speakers)
%{"Mirko" => %DevDay.Speaker{age: nil, name: "Mirko",
sessions: nil}}
iex(5)> GenServer.cast(pid, {:remove, "Mirko"})
:ok
defmodule DevDay.SpeakerServer do
use GenServer
@name __MODULE__
def start_link() do
GenServer.start_link(__MODULE__, :ok, name: @name)
end
def add(name) do
GenServer.cast(@name, {:add, name})
end
def remove(name) do
GenServer.cast(@name, {:remove, name})
end
def speakers() do
GenServer.call(@name, :speakers)
end
...
end
GenServer - Client
iex(1)> DevDay.SpeakerServer.start_link
{:ok, #PID<0.212.0>}
iex(2)> DevDay.SpeakerServer.speakers
%{}
iex(3)> DevDay.SpeakerServer.add("Mirko")
:ok
iex(4)> DevDay.SpeakerServer.speakers
%{"Mirko" => %DevDay.Speaker{age: nil, name: "Mirko",
sessions: nil}}
iex(5)> DevDay.SpeakerServer.remove("Mirko")
:ok
Supervisor
●
Spezieller Prozeß
●
überwacht andere Prozesse
●
startet beendete Prozesse bei Bedarf neu
●
Regeln für Neustart können definiert werden
– Welche Prozesse?
– Wie oft pro Zeit?
– Unter welche Bedingungen?
●
Kann Kindprozesse auch dynamisch starten.
Supervisor
defmodule DevDay.Supervisor do
use Supervisor
def start_link do
Supervisor.start_link(__MODULE__, [])
end
def init(_) do
children = [
worker(DevDay.SpeakerServer, [])
]
supervise(children, strategy: :one_for_one)
end
end
Supervisor
S
S
S
S
!
Nodes
●
eine VM mit Namen
●
mehrere pro Rechner
●
verteilt auf mehrere Rechner
●
können untereinander kommunizieren
●
iex --sname node1 -S mix
●
Node.self/0
●
Node.list/0
●
Node.connect/1
Nodes - node1
●
iex --sname node1 -S mix
●
iex(node1@mzlv110)1> Node.self
:node1@mzlv110
●
iex(node1@mzlv110)2> DevDay.HelloProc.simple_hallo
Hallo
:ok
Nodes - node2
●
iex --sname node2
●
iex(node2@mzlv110)1> Node.spawn(:node1@mzlv110,
DevDay.HelloProc, :simple_hallo, [])
Hallo
#PID<10739.247.0>
●
iex(node2@mzlv110)2> Node.list
[:node1@mzlv110]
●
iex(node2@mzlv110)3> DevDay.HelloProc.simple_hallo
** (UndefinedFunctionError) function
DevDay.HelloProc.simple_hallo/0 is undefined (module
DevDay.HelloProc is not available)
DevDay.HelloProc.simple_hallo()
Ausblick - OTP
●
GenServer
●
Agent
●
Task
●
ETS (Erlang Term Storage)
●
Mnesia (heavy duty real-time distributed database)
●
:gen_tcp
●
GenStage
●
GenStateMachine / :gen_statem
●
otp_app
Ausblick - ecto
●
Datenzugriff
●
Zugriff über Repositories und Changesets
●
Daten sind Structs
●
Datendefinitionen als Schemas / Migrations
●
Build-in PostgreSQL und MySQL
Ausblick - Phoenix
●
Web Framework
●
MVC
●
Templates
●
Routing
●
Channels
– stateful connections
– pro Connection ein Prozeß
– Websockets
Links
●
https://elixir-lang.org/
●
https://elixir-lang.org/getting-started
●
https://elixirschool.com/
●
https://hexdocs.pm/
●
https://exercism.io/tracks/elixir
●
https://alchemist.camp/
●
http://www.erlang.org/
Ende
Fragen?

Weitere ähnliche Inhalte

Ähnlich wie Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"

Coffee Backone Introduction
Coffee Backone IntroductionCoffee Backone Introduction
Coffee Backone IntroductionTino Isnich
 
Go - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare SystemeGo - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare SystemeFrank Müller
 
Wie fange ich programmieren an?
Wie fange ich programmieren an?Wie fange ich programmieren an?
Wie fange ich programmieren an?hubx
 
Java und Go im Vergleich
Java und Go im VergleichJava und Go im Vergleich
Java und Go im VergleichQAware GmbH
 
Skalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoSkalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoFrank Müller
 
Devs@Home - Einführung in Go
Devs@Home - Einführung in GoDevs@Home - Einführung in Go
Devs@Home - Einführung in GoFrank Müller
 
Lehmanns Rails Erweitern
Lehmanns Rails ErweiternLehmanns Rails Erweitern
Lehmanns Rails Erweiternjan_mindmatters
 
Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
Von Automaten zu Programmen–Parsergeneratoren und AttributgrammatikenVon Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
Von Automaten zu Programmen–Parsergeneratoren und AttributgrammatikenTim Furche
 
Von Java Zu Groovy
Von Java Zu GroovyVon Java Zu Groovy
Von Java Zu Groovyjlink
 
Differenzial Analyse in der Praxis (Florian Walther)
Differenzial Analyse in der Praxis (Florian Walther)Differenzial Analyse in der Praxis (Florian Walther)
Differenzial Analyse in der Praxis (Florian Walther)GEEKcon
 
nagiosplugin - eine Python-Biblioth­ek für Monitoring-Plug­ins
nagiosplugin - eine Python-Biblioth­ek für Monitoring-Plug­ins nagiosplugin - eine Python-Biblioth­ek für Monitoring-Plug­ins
nagiosplugin - eine Python-Biblioth­ek für Monitoring-Plug­ins Christian Kauhaus
 
Funktionales Programmieren mit Clojure
Funktionales Programmieren mit ClojureFunktionales Programmieren mit Clojure
Funktionales Programmieren mit ClojureDr. Christian Betz
 
Scala : Monads for the Pragmatic Programmer , Composition with Stackable Traits
Scala : Monads for the Pragmatic Programmer , Composition with Stackable TraitsScala : Monads for the Pragmatic Programmer , Composition with Stackable Traits
Scala : Monads for the Pragmatic Programmer , Composition with Stackable TraitsAndreas Neumann
 
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...NETWAYS
 
Perl 5.20: Feature, Kultur, Module, Werkzeuge
Perl 5.20: Feature, Kultur, Module, WerkzeugePerl 5.20: Feature, Kultur, Module, Werkzeuge
Perl 5.20: Feature, Kultur, Module, Werkzeugelichtkind
 
Perl 6 Regex und Grammars
Perl 6 Regex und GrammarsPerl 6 Regex und Grammars
Perl 6 Regex und Grammarslichtkind
 

Ähnlich wie Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir" (20)

Coffee Backone Introduction
Coffee Backone IntroductionCoffee Backone Introduction
Coffee Backone Introduction
 
Go - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare SystemeGo - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare Systeme
 
Wie fange ich programmieren an?
Wie fange ich programmieren an?Wie fange ich programmieren an?
Wie fange ich programmieren an?
 
Java und Go im Vergleich
Java und Go im VergleichJava und Go im Vergleich
Java und Go im Vergleich
 
Skalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoSkalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google Go
 
Devs@Home - Einführung in Go
Devs@Home - Einführung in GoDevs@Home - Einführung in Go
Devs@Home - Einführung in Go
 
Lehmanns Rails Erweitern
Lehmanns Rails ErweiternLehmanns Rails Erweitern
Lehmanns Rails Erweitern
 
Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
Von Automaten zu Programmen–Parsergeneratoren und AttributgrammatikenVon Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken
 
Ruby on Rails SS09 04
Ruby on Rails SS09 04Ruby on Rails SS09 04
Ruby on Rails SS09 04
 
Von Java Zu Groovy
Von Java Zu GroovyVon Java Zu Groovy
Von Java Zu Groovy
 
Differenzial Analyse in der Praxis (Florian Walther)
Differenzial Analyse in der Praxis (Florian Walther)Differenzial Analyse in der Praxis (Florian Walther)
Differenzial Analyse in der Praxis (Florian Walther)
 
nagiosplugin - eine Python-Biblioth­ek für Monitoring-Plug­ins
nagiosplugin - eine Python-Biblioth­ek für Monitoring-Plug­ins nagiosplugin - eine Python-Biblioth­ek für Monitoring-Plug­ins
nagiosplugin - eine Python-Biblioth­ek für Monitoring-Plug­ins
 
Funktionales Programmieren mit Clojure
Funktionales Programmieren mit ClojureFunktionales Programmieren mit Clojure
Funktionales Programmieren mit Clojure
 
Scala : Monads for the Pragmatic Programmer , Composition with Stackable Traits
Scala : Monads for the Pragmatic Programmer , Composition with Stackable TraitsScala : Monads for the Pragmatic Programmer , Composition with Stackable Traits
Scala : Monads for the Pragmatic Programmer , Composition with Stackable Traits
 
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
OSMC 2008 | Programmierung von Nagios-Plugins für NetApp Speichergeräte by In...
 
Perl 5.20: Feature, Kultur, Module, Werkzeuge
Perl 5.20: Feature, Kultur, Module, WerkzeugePerl 5.20: Feature, Kultur, Module, Werkzeuge
Perl 5.20: Feature, Kultur, Module, Werkzeuge
 
Ruby on Rails SS09 03
Ruby on Rails SS09 03Ruby on Rails SS09 03
Ruby on Rails SS09 03
 
Drupal inside out
Drupal inside outDrupal inside out
Drupal inside out
 
Web Entwicklung mit PHP - Teil 1
Web Entwicklung mit PHP - Teil 1Web Entwicklung mit PHP - Teil 1
Web Entwicklung mit PHP - Teil 1
 
Perl 6 Regex und Grammars
Perl 6 Regex und GrammarsPerl 6 Regex und Grammars
Perl 6 Regex und Grammars
 

Mehr von DevDay Dresden

The Architecture of Uncertainty - Kevlin Henney
The Architecture of Uncertainty - Kevlin HenneyThe Architecture of Uncertainty - Kevlin Henney
The Architecture of Uncertainty - Kevlin HenneyDevDay Dresden
 
Dev Day 2021 - Stephan Pirnbaum - Anwendungsmodernisierung
Dev Day 2021 - Stephan Pirnbaum - AnwendungsmodernisierungDev Day 2021 - Stephan Pirnbaum - Anwendungsmodernisierung
Dev Day 2021 - Stephan Pirnbaum - AnwendungsmodernisierungDevDay Dresden
 
Tobias Nebel - Herausforderungen und Changen in Full-Stack-IoT-Projekten
Tobias Nebel - Herausforderungen und Changen in Full-Stack-IoT-ProjektenTobias Nebel - Herausforderungen und Changen in Full-Stack-IoT-Projekten
Tobias Nebel - Herausforderungen und Changen in Full-Stack-IoT-ProjektenDevDay Dresden
 
Andreas Roth - GraphQL erfolgreich im Backend einsetzen
Andreas Roth - GraphQL erfolgreich im Backend einsetzenAndreas Roth - GraphQL erfolgreich im Backend einsetzen
Andreas Roth - GraphQL erfolgreich im Backend einsetzenDevDay Dresden
 
Alexander Reelsen - Seccomp for Developers
Alexander Reelsen - Seccomp for DevelopersAlexander Reelsen - Seccomp for Developers
Alexander Reelsen - Seccomp for DevelopersDevDay Dresden
 
DevDay 19 Accessibility: Praxistipps für Entwickler
DevDay 19 Accessibility: Praxistipps für EntwicklerDevDay 19 Accessibility: Praxistipps für Entwickler
DevDay 19 Accessibility: Praxistipps für EntwicklerDevDay Dresden
 
Dev Day 2019: Phillip Krenn – Aggregierte Logging Patterns
Dev Day 2019: Phillip Krenn – Aggregierte Logging PatternsDev Day 2019: Phillip Krenn – Aggregierte Logging Patterns
Dev Day 2019: Phillip Krenn – Aggregierte Logging PatternsDevDay Dresden
 
Dev Day 2019: Mirko Seifert – Next Level Integration Testing mit Docker und T...
Dev Day 2019: Mirko Seifert – Next Level Integration Testing mit Docker und T...Dev Day 2019: Mirko Seifert – Next Level Integration Testing mit Docker und T...
Dev Day 2019: Mirko Seifert – Next Level Integration Testing mit Docker und T...DevDay Dresden
 
Dev Day 2019: Nathan Mattes – Kommunikation ist wichtig, scheiße wichtig und ...
Dev Day 2019: Nathan Mattes – Kommunikation ist wichtig, scheiße wichtig und ...Dev Day 2019: Nathan Mattes – Kommunikation ist wichtig, scheiße wichtig und ...
Dev Day 2019: Nathan Mattes – Kommunikation ist wichtig, scheiße wichtig und ...DevDay Dresden
 
Dev Day 2019: Stephan Birnbaum – Die Glaskugel hat ausgedient, wir machen Sof...
Dev Day 2019: Stephan Birnbaum – Die Glaskugel hat ausgedient, wir machen Sof...Dev Day 2019: Stephan Birnbaum – Die Glaskugel hat ausgedient, wir machen Sof...
Dev Day 2019: Stephan Birnbaum – Die Glaskugel hat ausgedient, wir machen Sof...DevDay Dresden
 
Dev Day 2019: Markus Winand – Die Mutter aller Abfragesprachen: SQL im 21. Ja...
Dev Day 2019: Markus Winand – Die Mutter aller Abfragesprachen: SQL im 21. Ja...Dev Day 2019: Markus Winand – Die Mutter aller Abfragesprachen: SQL im 21. Ja...
Dev Day 2019: Markus Winand – Die Mutter aller Abfragesprachen: SQL im 21. Ja...DevDay Dresden
 
Dev Day 2019: Kay Grebenstein – Wie wir müssen das noch testen? - design for ...
Dev Day 2019: Kay Grebenstein – Wie wir müssen das noch testen? - design for ...Dev Day 2019: Kay Grebenstein – Wie wir müssen das noch testen? - design for ...
Dev Day 2019: Kay Grebenstein – Wie wir müssen das noch testen? - design for ...DevDay Dresden
 
Dev Day 2019: Kathrin Friedrich/Michael Kunze – Design better together - Styl...
Dev Day 2019: Kathrin Friedrich/Michael Kunze – Design better together - Styl...Dev Day 2019: Kathrin Friedrich/Michael Kunze – Design better together - Styl...
Dev Day 2019: Kathrin Friedrich/Michael Kunze – Design better together - Styl...DevDay Dresden
 
Dev Day 2019: Benjamin Wolf – "Some fixes" - Commit Message 101
Dev Day 2019: Benjamin Wolf – "Some fixes" - Commit Message 101Dev Day 2019: Benjamin Wolf – "Some fixes" - Commit Message 101
Dev Day 2019: Benjamin Wolf – "Some fixes" - Commit Message 101DevDay Dresden
 
Dev Day 2019: Lucas Fiedler – DevOps-Dashboard: Transparenz für DevOps-Teams
Dev Day 2019: Lucas Fiedler – DevOps-Dashboard: Transparenz für DevOps-TeamsDev Day 2019: Lucas Fiedler – DevOps-Dashboard: Transparenz für DevOps-Teams
Dev Day 2019: Lucas Fiedler – DevOps-Dashboard: Transparenz für DevOps-TeamsDevDay Dresden
 
Dev Day 2019: Ulrich Deiters – Offene Daten und IT-Lösungen für den Radverkehr
Dev Day 2019: Ulrich Deiters – Offene Daten und IT-Lösungen für den RadverkehrDev Day 2019: Ulrich Deiters – Offene Daten und IT-Lösungen für den Radverkehr
Dev Day 2019: Ulrich Deiters – Offene Daten und IT-Lösungen für den RadverkehrDevDay Dresden
 
Dev Day 2019: Alexander Lichter - JAMstack - Eine neuartige Webanwendungs-Arc...
Dev Day 2019: Alexander Lichter - JAMstack - Eine neuartige Webanwendungs-Arc...Dev Day 2019: Alexander Lichter - JAMstack - Eine neuartige Webanwendungs-Arc...
Dev Day 2019: Alexander Lichter - JAMstack - Eine neuartige Webanwendungs-Arc...DevDay Dresden
 
Dev Day 2019: Martin Schurz - Manual Work Is A Bug!
Dev Day 2019: Martin Schurz - Manual Work Is A Bug!Dev Day 2019: Martin Schurz - Manual Work Is A Bug!
Dev Day 2019: Martin Schurz - Manual Work Is A Bug!DevDay Dresden
 
Dev Day 2019: Stefan Schleyer: How to build an cloud-based IoT application“
Dev Day 2019: Stefan Schleyer: How to build an cloud-based IoT application“Dev Day 2019: Stefan Schleyer: How to build an cloud-based IoT application“
Dev Day 2019: Stefan Schleyer: How to build an cloud-based IoT application“DevDay Dresden
 
Dev Day 2019: Mike Sperber – Software Design für die Seele
Dev Day 2019: Mike Sperber – Software Design für die SeeleDev Day 2019: Mike Sperber – Software Design für die Seele
Dev Day 2019: Mike Sperber – Software Design für die SeeleDevDay Dresden
 

Mehr von DevDay Dresden (20)

The Architecture of Uncertainty - Kevlin Henney
The Architecture of Uncertainty - Kevlin HenneyThe Architecture of Uncertainty - Kevlin Henney
The Architecture of Uncertainty - Kevlin Henney
 
Dev Day 2021 - Stephan Pirnbaum - Anwendungsmodernisierung
Dev Day 2021 - Stephan Pirnbaum - AnwendungsmodernisierungDev Day 2021 - Stephan Pirnbaum - Anwendungsmodernisierung
Dev Day 2021 - Stephan Pirnbaum - Anwendungsmodernisierung
 
Tobias Nebel - Herausforderungen und Changen in Full-Stack-IoT-Projekten
Tobias Nebel - Herausforderungen und Changen in Full-Stack-IoT-ProjektenTobias Nebel - Herausforderungen und Changen in Full-Stack-IoT-Projekten
Tobias Nebel - Herausforderungen und Changen in Full-Stack-IoT-Projekten
 
Andreas Roth - GraphQL erfolgreich im Backend einsetzen
Andreas Roth - GraphQL erfolgreich im Backend einsetzenAndreas Roth - GraphQL erfolgreich im Backend einsetzen
Andreas Roth - GraphQL erfolgreich im Backend einsetzen
 
Alexander Reelsen - Seccomp for Developers
Alexander Reelsen - Seccomp for DevelopersAlexander Reelsen - Seccomp for Developers
Alexander Reelsen - Seccomp for Developers
 
DevDay 19 Accessibility: Praxistipps für Entwickler
DevDay 19 Accessibility: Praxistipps für EntwicklerDevDay 19 Accessibility: Praxistipps für Entwickler
DevDay 19 Accessibility: Praxistipps für Entwickler
 
Dev Day 2019: Phillip Krenn – Aggregierte Logging Patterns
Dev Day 2019: Phillip Krenn – Aggregierte Logging PatternsDev Day 2019: Phillip Krenn – Aggregierte Logging Patterns
Dev Day 2019: Phillip Krenn – Aggregierte Logging Patterns
 
Dev Day 2019: Mirko Seifert – Next Level Integration Testing mit Docker und T...
Dev Day 2019: Mirko Seifert – Next Level Integration Testing mit Docker und T...Dev Day 2019: Mirko Seifert – Next Level Integration Testing mit Docker und T...
Dev Day 2019: Mirko Seifert – Next Level Integration Testing mit Docker und T...
 
Dev Day 2019: Nathan Mattes – Kommunikation ist wichtig, scheiße wichtig und ...
Dev Day 2019: Nathan Mattes – Kommunikation ist wichtig, scheiße wichtig und ...Dev Day 2019: Nathan Mattes – Kommunikation ist wichtig, scheiße wichtig und ...
Dev Day 2019: Nathan Mattes – Kommunikation ist wichtig, scheiße wichtig und ...
 
Dev Day 2019: Stephan Birnbaum – Die Glaskugel hat ausgedient, wir machen Sof...
Dev Day 2019: Stephan Birnbaum – Die Glaskugel hat ausgedient, wir machen Sof...Dev Day 2019: Stephan Birnbaum – Die Glaskugel hat ausgedient, wir machen Sof...
Dev Day 2019: Stephan Birnbaum – Die Glaskugel hat ausgedient, wir machen Sof...
 
Dev Day 2019: Markus Winand – Die Mutter aller Abfragesprachen: SQL im 21. Ja...
Dev Day 2019: Markus Winand – Die Mutter aller Abfragesprachen: SQL im 21. Ja...Dev Day 2019: Markus Winand – Die Mutter aller Abfragesprachen: SQL im 21. Ja...
Dev Day 2019: Markus Winand – Die Mutter aller Abfragesprachen: SQL im 21. Ja...
 
Dev Day 2019: Kay Grebenstein – Wie wir müssen das noch testen? - design for ...
Dev Day 2019: Kay Grebenstein – Wie wir müssen das noch testen? - design for ...Dev Day 2019: Kay Grebenstein – Wie wir müssen das noch testen? - design for ...
Dev Day 2019: Kay Grebenstein – Wie wir müssen das noch testen? - design for ...
 
Dev Day 2019: Kathrin Friedrich/Michael Kunze – Design better together - Styl...
Dev Day 2019: Kathrin Friedrich/Michael Kunze – Design better together - Styl...Dev Day 2019: Kathrin Friedrich/Michael Kunze – Design better together - Styl...
Dev Day 2019: Kathrin Friedrich/Michael Kunze – Design better together - Styl...
 
Dev Day 2019: Benjamin Wolf – "Some fixes" - Commit Message 101
Dev Day 2019: Benjamin Wolf – "Some fixes" - Commit Message 101Dev Day 2019: Benjamin Wolf – "Some fixes" - Commit Message 101
Dev Day 2019: Benjamin Wolf – "Some fixes" - Commit Message 101
 
Dev Day 2019: Lucas Fiedler – DevOps-Dashboard: Transparenz für DevOps-Teams
Dev Day 2019: Lucas Fiedler – DevOps-Dashboard: Transparenz für DevOps-TeamsDev Day 2019: Lucas Fiedler – DevOps-Dashboard: Transparenz für DevOps-Teams
Dev Day 2019: Lucas Fiedler – DevOps-Dashboard: Transparenz für DevOps-Teams
 
Dev Day 2019: Ulrich Deiters – Offene Daten und IT-Lösungen für den Radverkehr
Dev Day 2019: Ulrich Deiters – Offene Daten und IT-Lösungen für den RadverkehrDev Day 2019: Ulrich Deiters – Offene Daten und IT-Lösungen für den Radverkehr
Dev Day 2019: Ulrich Deiters – Offene Daten und IT-Lösungen für den Radverkehr
 
Dev Day 2019: Alexander Lichter - JAMstack - Eine neuartige Webanwendungs-Arc...
Dev Day 2019: Alexander Lichter - JAMstack - Eine neuartige Webanwendungs-Arc...Dev Day 2019: Alexander Lichter - JAMstack - Eine neuartige Webanwendungs-Arc...
Dev Day 2019: Alexander Lichter - JAMstack - Eine neuartige Webanwendungs-Arc...
 
Dev Day 2019: Martin Schurz - Manual Work Is A Bug!
Dev Day 2019: Martin Schurz - Manual Work Is A Bug!Dev Day 2019: Martin Schurz - Manual Work Is A Bug!
Dev Day 2019: Martin Schurz - Manual Work Is A Bug!
 
Dev Day 2019: Stefan Schleyer: How to build an cloud-based IoT application“
Dev Day 2019: Stefan Schleyer: How to build an cloud-based IoT application“Dev Day 2019: Stefan Schleyer: How to build an cloud-based IoT application“
Dev Day 2019: Stefan Schleyer: How to build an cloud-based IoT application“
 
Dev Day 2019: Mike Sperber – Software Design für die Seele
Dev Day 2019: Mike Sperber – Software Design für die SeeleDev Day 2019: Mike Sperber – Software Design für die Seele
Dev Day 2019: Mike Sperber – Software Design für die Seele
 

Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"

  • 1. "Hallo " <> "Elixir" Mirko Zeibig (mirko.zeibig@t-systems.com)
  • 3. BEAM [Bogdan‘s|Björn‘s] Erlang Abstract Machine JVM Java Virtual Machine Elixir • mix • hex • ExUnit Compiler, Tools, Runtime Library Compiler, Tools, Runtime Library • Gradle • Maven • JUnit OTP JDK
  • 5. arity ● Anzahl der Parameter einer Funktion – alle Parameter auch optionale Parameter mit default ● ähnlich der Methodensignatur in Java – da Parameter keine Typen haben ● [Modulname].[Funktionsname]/[Parameterzahl] – Enum.map/2 – Enum.map_join/2 – Enum.map_join/3 – File.write/2
  • 8. Funktionen ● named function def add(a, b 1) do a + b end def square(a) do a * a end add(40, 2) add(41) square(3)
  • 9. Funktionen ● anonymous function f = fn x -> x * x end f.(3)
  • 11. Funktionen ● guard clauses def gt(a, b) when a > b do :gt end def gt(a, b) when a < b do :lt end def gt(a, b) when a == b do :eq end
  • 12. Module ● alle named functions müssen in Module ● Schachtelung möglich defmodule DevDay.Functions do def add(a, b 1) do a + b end defmodule MoreFunctions do def square(a) do a * a end end end
  • 14. integer ● Haben keine fixe Größe ● 2019 ● 0xbabe ● 0x765 ● 0b1011 ● 1_000_000
  • 16. float ● IEEE 754 double precision ● 1.0 ● 3.14159 ● 0.314159e1 ● 314159.0e-5
  • 17. :atoms ● Konstanten deren Name der Wert ist ● :devday ● :devday2019 ● :devday@2019 ● :devday! ● :hugbúnaðurVerktaki ● :"Pippilotta Viktualia … Efraimsdotter Långstrump"
  • 18. range ● Von – bis Werte ● 1..10 ● 10..1 ● 0x13..0o777
  • 19. tuples ● Geordnete Menge von Werten ● {42, :devday, "Radebeul"} ● File.read("existing.file") {:ok, "inhalt der Datei"} ● File.read("nonexisting.file") {:error, :enoent}
  • 20. Keyword lists ● Liste von Zwei-Element-Tuples ● Keys sind Atome und nicht eindeutig ● [foo: "bar", hello: "world"] ● [{:foo, "bar"}, {:hello, "world"}] ● x = [foo: "bar", hello: "world"] ● x[:hello] "world"
  • 21. List ● Verkettete Liste beliebiger Werte ● list = [42, :devday, "Radebeul"] ● ["hello"] ++ list ["hello", 42, :devday, "Radebeul"] ● list ++ ["world"] [42, :devday, "Radebeul", "world"]
  • 22. List ● list = [42, :devday, "Radebeul"] ● list -- [42] [:devday, "Radebeul"] ● hd(list) 42 ● tl(list) [:devday, "Radebeul"] ● ["hallo" | [:devday, "Radebeul"]] ["hallo", :devday, "Radebeul"]]
  • 23. Map ● Key-Value-Speicher ● map = %{:answer => 42, "was" => :devday, "wo" => "Radebeul"} ● map[:answer] 42 ● map["was"] :devday ● map["wo"] "Radebeul"
  • 24. Map ● map = %{answer: 42, was: :devday, wo: "Radebeul"} ● map.answer 42 ● map.was :devday ● map.wo "Radebeul" ● %{map | answer: 3.14}
  • 25. Enum (Module) ● bietet Funktionen zu Arbeit mit Enumerables – each/2 – filter/2 – map/2 – reduce/2 – join/2 – empty?/1 – any?/2 – all?/2
  • 26. |> (pipe) speakers = ["Mirko", "Emil", "Ida", "Lina", "Alfred", "Alma", "Anton", "Lukas", "Lotta"] speakers |> Enum.filter(fn s -> String.length(s) > 3 end) |> Enum.map(fn s -> String.upcase(s) end) |> Enum.sort() |> Enum.each(fn s -> IO.puts(s) end) List<String> speakers = Arrays.asList("Mirko", "Emil", "Ida", "Lina", "Alfred", "Alma", "Anton", "Lukas", "Lotta"); speakers.stream() .filter(s -> s.length() > 3) .map(s -> s.toUpperCase()) .sorted() .peek(s -> System.out.println(s));
  • 27. |> (pipe) speakers = ["Mirko", "Emil", "Ida", "Lina", "Alfred", "Alma", "Anton", "Lukas", "Lotta"] speakers |> Enum.filter(fn s -> String.length(s) > 3 end) |> Enum.map(fn s -> String.upcase(s) end) |> Enum.sort() |> Enum.each(fn s -> IO.puts(s) end) List<String> speakers = Arrays.asList("Mirko", "Emil", "Ida", "Lina", "Alfred", "Alma", "Anton", "Lukas", "Lotta"); speakers.stream() .filter(s -> s.length() > 3) .map(s -> s.toUpperCase()) .sorted() .peek(s -> System.out.println(s)) .collect(Collectors.toList());
  • 28. |> (pipe) speakers = ["Mirko", "Emil", "Ida", "Lina", "Alfred", "Alma", "Anton", "Lukas", "Lotta"] speakers |> Enum.filter(&String.length(&1) > 3) |> Enum.map(&String.upcase(&1)) |> Enum.sort() |> Enum.each(&IO.puts(&1)) List<String> speakers = Arrays.asList("Mirko", "Emil", "Ida", "Lina", "Alfred", "Alma", "Anton", "Lukas", "Lotta"); speakers.stream() .filter(s -> s.length() > 3) .map(String::toUpperCase) .sorted() .peek(System.out::println) .collect(Collectors.toList());
  • 29. Struct defmodule DevDay.Speaker do alias __MODULE__ defstruct [:name, :age, :sessions] def new(name) do %Speaker{name: name} end end
  • 30. Strings ● String ist eigentlich kein eigener Typ ● Zwei Typen von Strings ● "" vs. '' ● UTF-8 ● String interpolation – "Hallo #{dd}!"
  • 31. Strings – single quoted ● Character Lists ● Liste von Integer Codepoints – 'DevDay' → [68,101,118,68,97,121] – 'Måla' → [77, 229, 108, 97] – 'noël' → [110, 111, 101, 776, 108] ● es funktionieren alle Funktionen auf Listen ● wird für Erlang-Interoperabilität benötigt
  • 32. Strings – double quoted ● Binaries ● Sequenz von Bits – "DevDay" → <<68,101,118,68,97,121>> – "Måla" → <<77, 229, 108, 97>> – "noël" → <<110, 111, 101, 776, 108>> ● dies sind die Standard-Strings
  • 33. String - noël ● String.codepoints "noeu0308l" ["n","o","e","¨", "l"] ● String.graphemes "noeu0308l" ["n", "o", "ë", "l"] ● String.reverse "noeu0308l" "lëon" ● String.slice("noeu0308l", 0, 3) "noë" ● String.length "noeu0308l" 4
  • 34. String – hä? ● "hä?" == "hau0308?" false ● "hä?" == "hä?" true ● String.equivalent?("hä?", "hau0308?") true ● String.equivalent?("hä?", "hä?") true
  • 35. Pattern Matching ● = ist in Elixir 'match operator' ● wenn linke und rechte Seite matchen → alles ok ● wenn nicht → MatchError ● enthält linke Seite Variablen, werden bei match Werte zugewiesen ● funktioniert in Elixir fast überall
  • 36. Pattern Matching ● 1 = 1 1 ● x = 1 1 ● 1 = x 1 ● 2 = x ** (MatchError) no match of right hand side value: 1
  • 37. Pattern Matching ● {a, b, c} = {"Hallo", "DevDay", 2019} {"Hallo", "DevDay", 2019} ● a "Hallo" ● b "DevDay" ● {a, b, 2018} = {"Hallo", "DevDay", 2019} ** (MatchError) no match of right hand side value: {"Hallo", "DevDay", 2019}
  • 38. Pattern Matching ● [a, b, c] = [3, 14, 42] [3, 14, 42] ● [head | tail] = [3, 14, 42] [3, 14, 42] ● head 3 ● tail [14, 42] ● [head | tail] = [] ** (MatchError) no match of right hand side value: []
  • 39. Pattern Matching - case def casematch(t) do case t do {1, 2, 3} -> "das paßt nicht" {3, 14, x} -> "Die Antwort ist #{x}." _ -> "der Rest" end end IO.puts casematch({1, 2, 3}) IO.puts casematch({3, 14, 42}) IO.puts casematch("DevDay")
  • 40. Pattern Matching - case def file_match() do case File.read("/devday/speakers.txt") do {:ok, data} -> tuwas(data) {:error, reason} -> "#{:file.format_error(reason)}" end end iex(1)> DevDay.Match.file_match "no such file or directory"
  • 41. Pattern Matching - function def sum([]) do 0 end def sum([head|tail]) do head + sum(tail) end iex(3)> DevDay.Match.sum([1,2,3,4,5]) 15
  • 42. Prozesse ● Wo man in Java ein Objekt erzeugt, startet man in Elixir einen Prozeß. ● keine OS-Prozesse oder -Threads ● sehr leichtgewichtig ● von VM verwaltet ● isoliert – keine gemeinsamen Resourcen ● kein lokales Errorhandling ● kommuniyieren über Messages
  • 43. Prozesse defmodule DevDay.HelloProc do def simple_hallo() do IO.puts "Hallo" end end iex(6)> DevDay.HelloProc.simple_hallo Hallo :ok iex(7)> spawn(DevDay.HelloProc, :simple_hallo, []) Hallo #PID<0.155.0>
  • 44. Prozesse - Messages def hallo() do receive do {sender, msg} -> send(sender, {:ok, "Hallo, #{msg}!"}) end end iex> pid = spawn(DevDay.HelloProc, :hallo, []) iex> send(pid, {self(), "DevDay"}) iex> receive do {:ok, message} -> IO.puts message end Hallo, DevDay! :ok
  • 45. Prozesse - link ● spawn/3 - startet neuen Prozeß – im Fehlerfall wird er beendet ● spawn_link/3 - startet neuen Prozeß und verknüpft ihn mit dem Parent – im Fehlerfall wird der verknüpfte Prozeß mit beendet ● spawn_monitor/3 – startet neuen Prozeß und überwacht ihn – im Fehlerfall wird eine Nachricht verschickt
  • 48. Prozesse - state ● Daten sind unveränderlich ● Funktionen sind stateless ● Objekte gibt es nicht ● Wer hält einen state? → Prozesse
  • 49. defmodule DevDay.Simple do def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> new_state = Map.put(state, name, Speaker.new(name)) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:list, pid} -> send(pid, {:ok, state}) loop(state) end end end
  • 50. GenServer ● Abstraktion für Server ● Verarbeitet Nachrichten synchron/asynchron ● Kümmert sich um – Loop – State – Start – Stop ● Definiert Callbacks
  • 51. defmodule DevDay.SpeakerServer do use GenServer def init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do new_state = Map.put(state, name, DevDay.Speaker.new(name)) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:speakers, _from, state) do {:reply, state, state} end end
  • 52. GenServer - Client iex(1)> {:ok, pid} = GenServer.start_link(DevDay.SpeakerServer, :ok) {:ok, #PID<0.212.0>} iex(2)> GenServer.call(pid, :speakers) %{} iex(3)> GenServer.cast(pid, {:add, "Mirko"}) :ok iex(4)> GenServer.call(pid, :speakers) %{"Mirko" => %DevDay.Speaker{age: nil, name: "Mirko", sessions: nil}} iex(5)> GenServer.cast(pid, {:remove, "Mirko"}) :ok
  • 53. defmodule DevDay.SpeakerServer do use GenServer @name __MODULE__ def start_link() do GenServer.start_link(__MODULE__, :ok, name: @name) end def add(name) do GenServer.cast(@name, {:add, name}) end def remove(name) do GenServer.cast(@name, {:remove, name}) end def speakers() do GenServer.call(@name, :speakers) end ... end
  • 54. GenServer - Client iex(1)> DevDay.SpeakerServer.start_link {:ok, #PID<0.212.0>} iex(2)> DevDay.SpeakerServer.speakers %{} iex(3)> DevDay.SpeakerServer.add("Mirko") :ok iex(4)> DevDay.SpeakerServer.speakers %{"Mirko" => %DevDay.Speaker{age: nil, name: "Mirko", sessions: nil}} iex(5)> DevDay.SpeakerServer.remove("Mirko") :ok
  • 55. Supervisor ● Spezieller Prozeß ● überwacht andere Prozesse ● startet beendete Prozesse bei Bedarf neu ● Regeln für Neustart können definiert werden – Welche Prozesse? – Wie oft pro Zeit? – Unter welche Bedingungen? ● Kann Kindprozesse auch dynamisch starten.
  • 56. Supervisor defmodule DevDay.Supervisor do use Supervisor def start_link do Supervisor.start_link(__MODULE__, []) end def init(_) do children = [ worker(DevDay.SpeakerServer, []) ] supervise(children, strategy: :one_for_one) end end
  • 58. Nodes ● eine VM mit Namen ● mehrere pro Rechner ● verteilt auf mehrere Rechner ● können untereinander kommunizieren ● iex --sname node1 -S mix ● Node.self/0 ● Node.list/0 ● Node.connect/1
  • 59. Nodes - node1 ● iex --sname node1 -S mix ● iex(node1@mzlv110)1> Node.self :node1@mzlv110 ● iex(node1@mzlv110)2> DevDay.HelloProc.simple_hallo Hallo :ok
  • 60. Nodes - node2 ● iex --sname node2 ● iex(node2@mzlv110)1> Node.spawn(:node1@mzlv110, DevDay.HelloProc, :simple_hallo, []) Hallo #PID<10739.247.0> ● iex(node2@mzlv110)2> Node.list [:node1@mzlv110] ● iex(node2@mzlv110)3> DevDay.HelloProc.simple_hallo ** (UndefinedFunctionError) function DevDay.HelloProc.simple_hallo/0 is undefined (module DevDay.HelloProc is not available) DevDay.HelloProc.simple_hallo()
  • 61. Ausblick - OTP ● GenServer ● Agent ● Task ● ETS (Erlang Term Storage) ● Mnesia (heavy duty real-time distributed database) ● :gen_tcp ● GenStage ● GenStateMachine / :gen_statem ● otp_app
  • 62. Ausblick - ecto ● Datenzugriff ● Zugriff über Repositories und Changesets ● Daten sind Structs ● Datendefinitionen als Schemas / Migrations ● Build-in PostgreSQL und MySQL
  • 63. Ausblick - Phoenix ● Web Framework ● MVC ● Templates ● Routing ● Channels – stateful connections – pro Connection ein Prozeß – Websockets