О чем я расскажу
• О языке Elixir и интересных концепциях: почему
Elixir - не такой как Ruby?
• О принципах построения архитектуры
приложения
• О том, как писать логику приложения
Slide 4
Slide 4 text
Почему появляются
новые языки?
Slide 5
Slide 5 text
У существующих есть
проблемы
• Асинхронность ???
• Производительность ??
• Fault-tolerance ?
Slide 6
Slide 6 text
Elixir - не Ruby, а
лучше
Slide 7
Slide 7 text
Elixir
• Функциональный динамический язык
• Основан на виртуальной машине Erlang
• Быстрый и надежный
• Просто создан для асинхронных операций
def start_link do
Agent.start_link(fn ->
load_values()
end, name: __MODULE__)
end
def get(key) do
Agent.get(__MODULE__, fn(state) ->
Map.get(state, key)
end)
end
def all do
Agent.get(__MODULE__, fn(state) ->
state
end)
end
Slide 21
Slide 21 text
No content
Slide 22
Slide 22 text
Обработка ошибок
Slide 23
Slide 23 text
No content
Slide 24
Slide 24 text
No content
Slide 25
Slide 25 text
• Такой подход прекрасно ложится на логику
процессов
• Позволяет писать бизнес-код, а не городить
костыли
Slide 26
Slide 26 text
Нам не нужны внешние
инфраструктурные
зависимости
Slide 27
Slide 27 text
No content
Slide 28
Slide 28 text
• Docker убивает половину плюсов BeamVM
• Redis уступает в скорости ets
• Nginx может быть использован, но не
обязательно
• (G)Unicorn совсем не нужен
• Код очень легко читать и писать
• Низкий порог входа
Slide 34
Slide 34 text
• Вызывает привыкание
Slide 35
Slide 35 text
Паттерн матчинг
«Сопоставление с шаблоном»
Slide 36
Slide 36 text
iex(1)> i = [1, 2, 3]
[1, 2, 3]
iex(2)> [one, two, three] = i
[1, 2, 3]
iex(3)> one
1
iex(4)> three
3
Slide 37
Slide 37 text
iex(1)> {:ok, result} = {:ok, 15}
{:ok, 15}
iex(1)> {:ok, result} = {:error, "Timeout"}
** (MatchError) no match of right hand side
value: {:error, "Timeout"}
Slide 38
Slide 38 text
iex(1)> person = %{"name" => "Nikita", "job" =>
"developer"}
%{"job" => "developer", "name" => "Nikita"}
iex(2)> %{"name" => name} = person
%{"job" => "developer", "name" => "Nikita"}
iex(3)> name
"Nikita"
Slide 39
Slide 39 text
defmodule Greetings do
def hello(:people), do: "Hello, people!"
def hello({name, surname}) do
"Hello, dear #{name} #{surname}"
end
def hello(_), do: "Hello, stranger"
end
Slide 40
Slide 40 text
• Очень удобно
Slide 41
Slide 41 text
• Вызывает сильное привыкание
Slide 42
Slide 42 text
Отсутствует if
Slide 43
Slide 43 text
No content
Slide 44
Slide 44 text
case Some.fetch_data() do
%{"user" => user} ->
{:ok, user}
%{"error" => reason} ->
{:error, reason}
_ -> {:error, "Unknown"}
end
Slide 45
Slide 45 text
defmodule Increment do
def one(a) when is_integer(a) do
a + 1
end
def one(_) do
:error
end
end
• Делает наш код понятнее
• Такой код легче тестировать
• Его легче расширять
Slide 48
Slide 48 text
Нет return
Slide 49
Slide 49 text
No content
Slide 50
Slide 50 text
• Удобнее тестировать
• Легче запомнить, как работает функция
Slide 51
Slide 51 text
Другой взгляд на
полиморфизм
Slide 52
Slide 52 text
defprotocol Size do
@doc "Calculates the size 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
defimpl Size, for: Tuple do
def size(tuple), do: tuple_size(tuple)
end
Slide 53
Slide 53 text
defmodule Parser do
@callback parse(String.t) :: any
@callback extensions() :: [String.t]
end
defmodule JSONParser do
@behaviour Parser
def parse(str), do: # ... parse JSON
def extensions, do: ["json"]
end
defmodule YAMLParser do
@behaviour Parser
def parse(str), do: # ... parse YAML
def extensions, do: ["yml"]
end
Slide 54
Slide 54 text
• Позволяет переиспользовать код
• Позволяет проектировать красивый API