Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Protocols and Structs
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Claudio Ortolina
December 02, 2015
Programming
170
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Protocols and Structs
Processing a data flow in Elixir
Claudio Ortolina
December 02, 2015
More Decks by Claudio Ortolina
See All by Claudio Ortolina
The Perils of Large Files
cloud8421
0
80
Back on your Feet
cloud8421
0
110
Idiomatic Elixir
cloud8421
1
560
GenStage in the Kitchen
cloud8421
4
790
Being a happy developer
cloud8421
2
120
Cooking Lessons with Vim and Tmux
cloud8421
3
300
Rails.vim Projections
cloud8421
0
430
Other Decks in Programming
See All in Programming
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
170
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
490
自サークルのIdPからログアウトできるようになるまで
taiseiue
1
140
Railsバージョンを4倍にした話
optim
0
250
ソニーのクラウド共通基盤の変遷とAI時代の開発スタイルに合わせた進化 / The Journey of Sony’s Common Cloud Platform and Its Evolution for AI-Native Development
kenjiyoneyama
0
260
Workers Cache を知る
syumai
0
360
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
120
SalesForceを内製化!? ~ HR事業を支える顧客管理基盤のインフラを大公開 ~
oku053
0
170
CodeRabbitの効果検証と過ごしてみた3ヶ月
armondando
0
230
[ハンズオン]AIへの指示だけで「五目並べ」を作ってみよう
satoshi256kbyte
1
370
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
150
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
540
Featured
See All Featured
Become a Pro
speakerdeck
PRO
31
6.3k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
330
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
260
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
430
Large-scale JavaScript Application Architecture
addyosmani
516
110k
HDC tutorial
michielstock
2
960
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
460
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.8k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
590
Transcript
PROTOCOLS AND STRUCTS FOR EFFECTIVE DATA FLOW
THE DOMAIN CHECK-IN PROCESS NOTIFY
RECAP ABOUT PROTOCOLS AND STRUCTS
STRUCTS defmodule Checkin do defstruct id: nil, lat: 0.0, lng:
0.0 end
STRUCTS %Checkin{id: "123", lat: 51.50, lng: 0.12} struct(Checkin, id: "123",
lat: 51.50, lng: 0.12) struct(Checkin, %{id: "123", lat: 51.50, lng: 0.12}) struct(Checkin, id: "123", lat: 51.50, lng: 0.12, ignored: true)
PROTOCOLS defprotocol Persistence do def create(thing) end
IMPLEMENTATION defimpl Persistence, for: Checkin do def create(checkin) do %Doc{class:
"Checkin", fields: Map.from_struct(checkin)} |> Repo.create end end
FALLBACK defprotocol Persistence do @fallback_to_any true def create(thing) end
FALLBACK defimpl Persistence, for: Any do def create(thing) do class
= Map.get(thing, :__struct__) |> to_string %Doc{class: class, fields: Map.from_struct(thing)} |> Repo.create end end
USAGE %Checkin{id: "123", lat: 51.50, lng: 0.12} |> Persistence.create
FLOW MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY
FLOW MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY
IDENTIFY { "meta" : { "version" : 1, "topic" :
"checkins", "type" : "create", "request_id" : "15456d4e-782b-11e5-8bcf-feff819cdc9f" }, "data" : { "ref" : "123ASDS", "lat" : 51.50, "lng" : 0.12 } }
IDENTIFY defmodule V1.Checkin.Create do defstruct request_id: nil, ref: nil, lat:
0.0, lng: 0.0 end
IDENTIFY def identify(payload) do case payload["meta"] do %{"version" => 1,
"topic" => "checkins", "type" => "create"} -> V1.Checkins.Create _other -> {:error, :unsupported_payload} end end
POPULATE def populate(struct_name, payload) do request_id = get_in(payload, "meta", "request_id")
struct_attrs = Map.put(payload["data"], "request_id", request_id) Kernel.struct(struct_name, Utils.atomise_map(struct_attrs)) end
ALL TOGETHER NOW message |> identify |> populate(message)
WINS STABLE INTERFACE DEFINES A BOUNDARY EXTENSIBLE INTENTION REVEALING
FLOW MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY
LOG defimpl String.Chars, for: V1.Checkins.Create do def to_string(create_struct) do "type=create
status=accepted request_id=#{create_struct.request_id} ref={create_struct.ref}" end end
LOG def log(item) do :ok = Logger.info item item end
ALL TOGETHER NOW message |> identify |> populate(message) |> log
FLOW MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY
PROCESS defimpl Job, for: V1.Checkin.Create do def process(create_struct) do {:ok,
new_record} = Persistence.create(create_struct) %V1.Checkin.Created{request_id: create_struct.request_id, record: new_record} end end
ALL TOGETHER NOW message |> identify |> populate(message) |> log
|> Job.process
WINS STABLE INTERFACE DEFINES A BOUNDARY EXTENSIBLE INTENTION REVEALING
FLOW MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY
LOG defimpl String.Chars, for: V1.Checkins.Created do def to_string(created_struct) do "type=create
status=processed request_id=#{create_struct.request_id} id={created_struct.record.id}" end end
ALL TOGETHER NOW message |> identify |> populate(message) |> log
|> Job.process |> log
NOTIFY MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY
NOTIFY defimpl Notify, for: V1.Checkin.Created do def topics(created_struct), do: ["checkins",
"users"] def to_message(created_struct) do %Message{request_id: created_struct.request_id, type: :create, data: %{id: created_struct.record.id}} end end
NOTIFY def notify(item) do payload = Notify.to_message(item) topics = Notify.topics(item)
PubSub.broadcast(payload, topics) end
ALL TOGETHER NOW message |> identify |> populate(message) |> log
|> Job.process |> log |> notify
EXECUTION MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY LISTENER PROCESS POOL
PUBSUB POOL
EXTENDING FURTHER ADD NEW STRUCTS IMPLEMENT PROTOCOLS
CORE IDEAS ASSIGN INTENT TO DATA DEFINE FUNCTIONALITY AS PROTOCOLS
DEFINE STRICT BOUNDARIES BETWEEN STEPS
THANK YOU! http://bit.ly/ff-protocols-structs
PLUG ELIXIR, JAVASCRIPT, ELM DEVELOPMENT ELIXIR, JAVASCRIPT, ELM TRAINING ASK
ME ABOUT IT!