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
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
79
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
高専キャリア LT 発表内容
crysta1221
6
5.7k
Swift愛好会100回記念 第1回を振り返る
jollyjoester
0
120
AWS DevOps Agentで インシデント対応をAIに任せたい
honmarkhunt
7
2.8k
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
160
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
150
AIを上手に使っていこうとしたら越境せざるを得なくなった話 〜実践1年で見えた境界を越えなければならない理由と進め方〜 / Crossing borders with AI
tomoyakitaura
4
1.1k
JPUG勉強会 OSSデータベースの内部構造を理解しよう(第2回)
oga5
0
170
XHTMLが残したもの
yosuke_furukawa
PRO
2
750
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
140
選挙速報を多くのユーザーへ 届ける Live Activities 設計
hamayokokuririn
0
130
AI に Inclusive UI を書かせよう — Design Rules Skill で Compose UI を作り直す
theoriatec2024
1
480
{ Android | Kotlin } Gradle Plugin in 2026
ryunen344
1
310
Featured
See All Featured
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
460
Technical Leadership for Architectural Decision Making
baasie
3
560
Game over? The fight for quality and originality in the time of robots
wayneb77
1
270
A Tale of Four Properties
chriscoyier
163
24k
Typedesign – Prime Four
hannesfritz
42
3.2k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
For a Future-Friendly Web
brad_frost
183
10k
Git: the NoSQL Database
bkeepers
PRO
432
67k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
A designer walks into a library…
pauljervisheath
211
25k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
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!