Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Elixir is not Ruby, it is better
Search
Sobolev Nikita
September 23, 2017
Programming
0
88
Elixir is not Ruby, it is better
Sobolev Nikita
September 23, 2017
Tweet
Share
More Decks by Sobolev Nikita
See All by Sobolev Nikita
Михаил Гурбанов – Are you NATS? @ PythoNN
sobolevn
0
59
Дмитрий Бровкин – Почему исправление опечаток сложнее, чем кажется, и как мы с этим српавляемся @ PythoNN
sobolevn
0
38
Алексей Гончарук – Современный веб с темлейтами @ PythoNN
sobolevn
0
110
Алексей Голобурдин – Демистификация PostgreSQL-индексов @ PythoNN
sobolevn
0
160
PythoNN – Александр Гончаров
sobolevn
0
69
PythoNN – Андрей Пронин
sobolevn
0
130
PythoNN: Василий Рябов – "Парсинг бинарных данных с помощью ctypes, или пишем на питоне как на Си"
sobolevn
0
250
GitHub Planet - OpenSource
sobolevn
0
280
Polymorphism and Typeclasses
sobolevn
2
170
Other Decks in Programming
See All in Programming
How Android Uses Data Structures Behind The Scenes
l2hyunwoo
0
480
Compose Multiplatform × AI で作る、次世代アプリ開発支援ツールの設計と実装
thagikura
0
170
AIと私たちの学習の変化を考える - Claude Codeの学習モードを例に
azukiazusa1
11
4.4k
HTMLの品質ってなんだっけ? “HTMLクライテリア”の設計と実践
unachang113
4
2.9k
個人軟體時代
ethanhuang13
0
330
Testing Trophyは叫ばない
toms74209200
0
890
Putting The Genie in the Bottle - A Crash Course on running LLMs on Android
iurysza
0
140
もうちょっといいRubyプロファイラを作りたい (2025)
osyoyu
1
460
API Platform 4.2: Redefining API Development
soyuka
0
230
Improving my own Ruby thereafter
sisshiki1969
1
160
Android端末で実現するオンデバイスLLM 2025
masayukisuda
1
170
Platformに“ちょうどいい”責務ってどこ? 関心の熱さにあわせて考える、責務分担のプラクティス
estie
1
170
Featured
See All Featured
Making Projects Easy
brettharned
117
6.4k
GraphQLとの向き合い方2022年版
quramy
49
14k
Designing for humans not robots
tammielis
253
25k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.9k
Site-Speed That Sticks
csswizardry
10
830
Visualization
eitanlees
148
16k
How GitHub (no longer) Works
holman
315
140k
Why Our Code Smells
bkeepers
PRO
339
57k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.4k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.1k
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1.1k
Transcript
Никита Соболев https://github.com/sobolevn
None
О чем я расскажу • О языке Elixir и интересных
концепциях: почему Elixir - не такой как Ruby? • О принципах построения архитектуры приложения • О том, как писать логику приложения
Почему появляются новые языки?
У существующих есть проблемы • Асинхронность ??? • Производительность ??
• Fault-tolerance ?
Elixir - не Ruby, а лучше
Elixir • Функциональный динамический язык • Основан на виртуальной машине
Erlang • Быстрый и надежный • Просто создан для асинхронных операций
Архитектура
iex(1)> example = [1, 2, 3] [1, 2, 3] iex(2)>
List.replace_at(example, 1, 99) [1, 99, 3] iex(3)> example [1, 2, 3] Иммутабельность
• Ничего нельзя "нахачить" • Идеально подходит для асинхронных задач
• Разные параллельные процессы используют свои копии данных
Асинхронность или «притча о легковесных процессах»
Actor Model
None
None
Есть много высоко- уровневых абстракций Task, GenServer, Agent, ...
iex(1)> task = Task.async(fn -> 4 + 4 end) %Task{owner:
#PID<0.84.0>, pid: #PID<0.86.0>, ref: #Reference<>} iex(2)> Task.await(task) 8
None
Отсутствие состояния
https://github.com/petrovich/ petrovich_elixir
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
None
Обработка ошибок
None
None
• Такой подход прекрасно ложится на логику процессов • Позволяет
писать бизнес-код, а не городить костыли
Нам не нужны внешние инфраструктурные зависимости
None
• Docker убивает половину плюсов BeamVM • Redis уступает в
скорости ets • Nginx может быть использован, но не обязательно • (G)Unicorn совсем не нужен
Бизнес-логика
Pipes
Enum.count(Enum.uniq([1, 2, 2, 2, 3])) # => 3 [1, 2,
2, 2, 3] |> Enum.uniq() |> Enum.count() # => 3
request |> validate_request() |> fetch_users() |> attach_messages(:sent) |> render_result(:json)
• Код очень легко читать и писать • Низкий порог
входа
• Вызывает привыкание
Паттерн матчинг «Сопоставление с шаблоном»
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
iex(1)> {:ok, result} = {:ok, 15} {:ok, 15} iex(1)> {:ok,
result} = {:error, "Timeout"} ** (MatchError) no match of right hand side value: {:error, "Timeout"}
iex(1)> person = %{"name" => "Nikita", "job" => "developer"} %{"job"
=> "developer", "name" => "Nikita"} iex(2)> %{"name" => name} = person %{"job" => "developer", "name" => "Nikita"} iex(3)> name "Nikita"
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
• Очень удобно
• Вызывает сильное привыкание
Отсутствует if
None
case Some.fetch_data() do %{"user" => user} -> {:ok, user} %{"error"
=> reason} -> {:error, reason} _ -> {:error, "Unknown"} end
defmodule Increment do def one(a) when is_integer(a) do a +
1 end def one(_) do :error end end
iex(1)> Increment.one(1) 2 iex(2)> Increment.one("Some") :error
• Делает наш код понятнее • Такой код легче тестировать
• Его легче расширять
Нет return
None
• Удобнее тестировать • Легче запомнить, как работает функция
Другой взгляд на полиморфизм
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
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
• Позволяет переиспользовать код • Позволяет проектировать красивый API
None
https://twitter.com/elixir_lang_mos https://github.com/wunsh/elixir-docs-ru
https://github.com/sobolevn