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
81
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
5
Дмитрий Бровкин – Почему исправление опечаток сложнее, чем кажется, и как мы с этим српавляемся @ PythoNN
sobolevn
0
5
Алексей Гончарук – Современный веб с темлейтами @ PythoNN
sobolevn
0
17
Алексей Голобурдин – Демистификация PostgreSQL-индексов @ PythoNN
sobolevn
0
13
PythoNN – Александр Гончаров
sobolevn
0
55
PythoNN – Андрей Пронин
sobolevn
0
100
PythoNN: Василий Рябов – "Парсинг бинарных данных с помощью ctypes, или пишем на питоне как на Си"
sobolevn
0
210
GitHub Planet - OpenSource
sobolevn
0
250
Polymorphism and Typeclasses
sobolevn
2
140
Other Decks in Programming
See All in Programming
CTFのWebにおける⾼難易度問題について
hamayanhamayan
1
1k
今から始めるCursor / Windsurf / Cline
kengo_hayano
0
110
ローコードサービスの進化のためのモノレポ移行
taro28
1
350
自分のために作ったアプリが、グローバルに使われるまで / Indie App Development Lunch LT
pixyzehn
1
140
Defying Front-End Inertia: Inertia.js on Rails
skryukov
0
370
PsySHから紐解くREPLの仕組み
muno92
PRO
1
530
AI時代のプログラミング教育 / programming education in ai era
kishida
23
21k
Boost Your Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
550
DataStoreをテストする
mkeeda
0
230
PHPer's Guide to Daemon Crafting Taming and Summoning
uzulla
2
1.1k
OpenTelemetryを活用したObservability入門 / Introduction to Observability with OpenTelemetry
seike460
PRO
1
390
Day0 初心者向けワークショップ実践!ソフトウェアテストの第一歩
satohiroyuki
0
500
Featured
See All Featured
BBQ
matthewcrist
88
9.5k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.5k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
12
630
The Art of Programming - Codeland 2020
erikaheidi
53
13k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.2k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
30k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
29
2k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.4k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
4
490
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.8k
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