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
Aprendizados de um projeto Elixir OTP
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Amanda
May 26, 2019
Technology
640
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Aprendizados de um projeto Elixir OTP
Elixir Brasil 2019
Amanda
May 26, 2019
More Decks by Amanda
See All by Amanda
Lessons Learned From an Elixir OTP Project
amandasposito
2
99
SOLID - Dependency inversion principle
amandasposito
0
93
Como concorrência funciona em Elixir?
amandasposito
1
240
Programação Funcional & Elixir
amandasposito
3
130
Ecto, você sabe o que é ?
amandasposito
4
250
Novidades no Rails 5
amandasposito
0
100
Rails Engines & RSpec
amandasposito
0
240
Elixir e Phoenix
amandasposito
3
600
Elixir em 5 minutos
amandasposito
1
100
Other Decks in Technology
See All in Technology
AI時代のエンジニアキャリアについて今一度考える
sakamoto_582
0
270
AWS Summit の片隅で、体育座りしながらコミュニティがにぎわう理由を考えた
k_adachi_01
2
340
小さいから、全部わかる。— 常駐AI "xangi" のすすめ
sugupoko
0
230
AIで政治は変わるのか? — 中高生と考えたAI時代の民主主義(東海高校サタデープログラム)
eitarosuda
0
360
10x Speed With QA Agent Platform - How we scaled adoption from individual effort to organizational capability
lycorptech_jp
PRO
0
110
なぜ人は自分のプロジェクトを 「なんちゃってアジャイル」と 自嘲するのか
kozotaira
0
230
從觀望到全公司落地:AI Agentic Coding 導入實戰 — 流程整合與安全治理
appleboy
1
530
AWS Summit 2026で見えたSIerにとっての Amazon Quickの位置づけ
maf_0521
0
150
ご挨拶「10周年を迎える共創ラボのこれまでとこれから」
iotcomjpadmin
0
180
初めてのDatabricks勉強会
taka_aki
2
230
勉強会企画をアプリで構造化してみた 〜そこで見えた、AIとの付き合い方〜 / I've structured a study group plan using an app.
pauli
0
280
Kotlin 開発のツラミを爆破した話! / Explode the difficulty of Kotlin dev!
eller86
0
130
Featured
See All Featured
RailsConf 2023
tenderlove
30
1.5k
Accessibility Awareness
sabderemane
1
150
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
350
How Software Deployment tools have changed in the past 20 years
geshan
0
34k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
150
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
How to Think Like a Performance Engineer
csswizardry
28
2.7k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
450
Building Applications with DynamoDB
mza
96
7.1k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
340
Transcript
Aprendizados de um projeto Elixir/OTP
→ amandasposito.com → speakerdeck.com/amandasposito → linkedin.com/in/amandasposito
careers.plataformatec.com.br
Disclaimer
Como foi começar em um projeto Elixir, vindo de outra
linguagem?
None
None
None
Como utilizar o ferramental da linguagem a seu favor?
None
Lidar com banco de dados se tornou muito mais comum
Preloads
None
SELECT * FROM Courses; SELECT * FROM Users WHERE course_id
= ? SELECT * FROM Users WHERE course_id = ? SELECT * FROM Users WHERE course_id = ?
None
Repo.all from c in Course, preload: [:users]
Ecto tem muitas features interessantes que podem te ajudar no
dia-a-dia
→ Changesets
→ Changesets → Schemas
→ Changesets → Schemas → Ecto.Multi
→ Changesets → Schemas → Ecto.Multi → etc.
Lidando com tabelas gigantescas
Qualquer coisa que fossemos alterar no banco era difícil
None
None
use Mix.Task
defmodule Mix.Tasks.Echo do use Mix.Task @impl Mix.Task def run(_args) do
Mix.shell.info "Hello World" end end
Saber analisar a performance é muito importante
Explain Analyze
EXPLAIN ANALYZE SELECT "courses"."id", "courses"."data" FROM "courses" INNER JOIN "users"
ON ("courses"."user_id" = "users"."id") WHERE "users".account_id = 4500000;
Gather (cost=847239.21..2458486.98 rows=2 width=16) (actual time=35048.574..45161.127 rows=2 loops=1) Workers Planned:
2 Workers Launched: 2 -> Hash Join (cost=846239.21..2457486.78 rows=1 width=16) (actual time=32820.132..45130.374 rows=1 loops=3) Hash Cond: (courses.user_id = users.id) -> Parallel Seq Scan on courses (cost=0.00..1040678.17 rows=45193617 width=16) (actual time=0.044..29710.148 rows=33333333 loops=3) -> Hash (cost=846239.20..846239.20 rows=1 width=8) (actual time=8318.392..8318.392 rows=1 loops=3) Buckets: 1024 Batches: 1 Memory Usage: 9kB -> Seq Scan on users (cost=0.00..846239.20 rows=1 width=8) (actual time=819.773..8318.380 rows=1 loops=3) Filter: (account_id = 4500000) Rows Removed by Filter: 49999999 Planning time: 0.421 ms Execution time: 45169.333 ms
None
None
http://blog.plataformatec.com.br/2019/02/migrations-in-databases-with-large-amount-of-data/
Tabelas ETS
"These provide the ability to store very large quantities of
data in an Erlang runtime system, and to have constant access time to the data." — Erlang Documentation
def hello do opts = [ :set, :named_table, :public, read_concurrency:
true ] table_name = :elixir_brasil :ets.new(table_name, opts) for n <- 1..100 do :ets.insert(table_name, {n, "Key #{n}"}) end end
None
Nesse momento não tinhamos muita visão da quantidade de dados
Velocidade x Quantidade de itens
A estimativa estava em 76GB de consumo de memória por
máquina
None
Tabelas ETS não possuem muitas opções de otimização como o
Redis
None
São como se fossem um Hash direto na memória
Consomem a memória disponível da aplicação
None
https://moz.com/devblog/moz-analytics-db-free
None
Testes
Doctest != Test
None
Sua aplicação está se comunicando com o mundo exterior, e
agora?
None
None
None
None
Como fazer para stubar/mockar uma requisição?
Bypass
None
setup do bypass = Bypass.open {:ok, bypass: bypass} end
test "fetch/1 returns and formats tweets", %{bypass: bypass} do response
= Jason.encode!([%{"text" => "Elixir Brasil 2019"}]) Bypass.expect(bypass, fn conn -> assert "/1.1/search/tweets.json" == conn.request_path assert "GET" == conn.method Plug.Conn.resp(conn, 200, response) end) tweets = TwitterClient.fetch("http://localhost:#{bypass.port}") assert tweets == [%{"text" => "Elixir Brasil 2019"}] end
test "fetch/1 returns and formats tweets", %{bypass: bypass} do response
= Jason.encode!([%{"text" => "Elixir Brasil 2019"}]) Bypass.expect(bypass, fn conn -> assert "/1.1/search/tweets.json" == conn.request_path assert "GET" == conn.method Plug.Conn.resp(conn, 200, response) end) tweets = TwitterClient.fetch("http://localhost:#{bypass.port}") assert tweets == [%{"text" => "Elixir Brasil 2019"}] end
def fetch(url \\ "https://api.twitter.com") do {:ok, response} = HTTPoison.get("#{url}/1.1/search/tweets.json") Jason.decode!(response.body)
end
Quando usar bypass?
Código que precisa realizar requests HTTP
None
Mox
None
None
test "messages/0 lists all messages from the timeline" do TwitterMock
|> expect(:fetch, fn -> [%{"text" => "Olá mundo"}] end) assert Timeline.messages() == {:ok, 1} end https://github.com/amandasposito/mox_example
http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/
GenServer
Como testar processos?
Testar Callback de GenServer não é uma boa prática
None
GenServer.cast
GenServer.call
https://devonestes.herokuapp.com/unit-tests-in-elixir-part-2
Quais os problemas mais comuns encontrados?
→ Tudo que eu aprendi em OOP, vou jogar fora
em funcional? → Como eu organizo meu código? → Todos os problemas que eu tinha em OOP, somem em funcional? → E esse tal de Context? Comé qui usa?
A probabilidade do código ficar complexo diminui
Mas os problemas ainda existem
Muitos dos problemas que vemos em OOP reconhecemos em FP
→ Funções muito grandes
→ Funções muito grandes → Funções difíceis de testar
→ Funções muito grandes → Funções difíceis de testar →
Mudanças simples precisam ser feitas em vários lugares
→ Funções muito grandes → Funções difíceis de testar →
Mudanças simples precisam ser feitas em vários lugares → Feature Envy
→ Funções muito grandes → Funções difíceis de testar →
Mudanças simples precisam ser feitas em vários lugares → Feature Envy → Contextos com muitas linhas
→ Funções muito grandes → Funções difíceis de testar →
Mudanças simples precisam ser feitas em vários lugares → Feature Envy → Contextos com muitas linhas → Acoplamento
→ Funções muito grandes → Funções difíceis de testar →
Mudanças simples precisam ser feitas em vários lugares → Feature Envy → Contextos com muitas linhas → Acoplamento
https://youtu.be/eldYot7uxUc
None
Contexts
A idéia é definir limites entre diferentes módulos da aplicação
Com o passar do tempo e a necessidade de interação
com vários schemas
Os contextos podem ficar maiores do que deveriam
Preste atenção para não manter código ortogonal ao contexto, no
contexto
Mantenha queries próximas de seu schema
A exceção são queries que lidam com mais de um
schema
http://devonestes.herokuapp.com/a-proposal-for-context-rules
None
Umbrella Projects
Dentro de um Umbrella app os apps deveriam acessar arquivos
uns dos outros?
É uma maneira de organizar seu código
None
None