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
Building a sustainable architecture
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Marcelo Piva
October 26, 2019
Programming
120
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Building a sustainable architecture
Marcelo Piva
October 26, 2019
More Decks by Marcelo Piva
See All by Marcelo Piva
Maintaining consistency in distributed systems with an effect machine
mpivaa
1
290
Fun with Monads
mpivaa
2
200
Go Pure with ClojureScript
mpivaa
2
190
Other Decks in Programming
See All in Programming
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
170
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
570
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
150
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
380
『コードを書く以外の』エンジニアリング〜課金基盤移行プロジェクト推進のためのTips4選
yuriko1211
0
560
Claude Team Plan導入・ガイド
tk3fftk
0
250
yield再入門 #phpcon
o0h
PRO
0
850
Japan Community Day at Kubecon + CloudNativeCon Japan 2026: Learning Container Privilege Control by Building My Own Low-Level Container Runtime
ternbusty
1
100
なぜ関数型プログラミングで「型」と「証明」が語られるのか #fp_matsuri
kajitack
3
1.1k
壊れたパーサから始める関数型設計と構成的なパーサ #fp_matsuri
raiga0310
2
420
komatsuna「分散システムにおけるバグ分析手法」
komatsunaqa
0
140
コーディングルールの鮮度を保ちたい for SRE NEXT 2026 / keep-fresh-go-internal-conventions-sre-next-2026
handlename
0
160
Featured
See All Featured
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
920
Exploring anti-patterns in Rails
aemeredith
3
450
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.7k
The Language of Interfaces
destraynor
162
27k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6k
Making the Leap to Tech Lead
cromwellryan
135
10k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
240
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
260
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.2k
First, design no harm
axbom
PRO
2
1.2k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.7k
Transcript
Building a sustainable architecture
Marcelo Piva Software Engineer @ Nubank @mpivaa github.com/mpivaa instagram.com/mah.piva
Carolina Pascale Campos Software Engineer @ Nubank @CarolinaPascale github.com/carolpc instagram.com/carolpc
books, coffee, running
motivation
None
smooth learning curve shipped code to production
almost no guidance
why?
None
300+ engineers 300+ services 15M customers
None
patterns among services
functional programming tests △ hexagonal architecture ⬡
functional programming
fp is about pure functions
fp is about referential transparency
��
Consistency Predictability Safety
we need to talk about side effects
not infecting your fp code with imperative code
limit the amount of imperative code
immutability vs mutability
pure functions + immutability
✅ easier to reason ✅ easier to debug
persistent data structures (copy-on-write)
Structural Sharing A =
Structural Sharing A = B =
Structural Sharing
Structural Sharing A
Structural Sharing B
focus on what matters
Class Object Instance Inheritance Polymorphism Abstract Factory Builder Factory Method
Object Pool Prototype Singleton Adapter Bridge Composite Decorator Facade Flyweight Private Class Data Proxy Chain of responsibility Command Interpreter Iterator Mediator Memento Null Object Observer State
None
eliminate shared state so order does not matter
don't have to set up anything up
be as functional as you can
tests △
confidence safety
feedback
accuracy
speed
reliability
✅ accuracy ✅ speed ✅ reliability
why highly testable code?
bonus: generative and property based testing
how to design our code?
high maintainability low tech debt
maintainability is a long term concept
first attempt: hexagonal architecture
inner layer: domain model
second layer: application
third layer: IO
separates business logic from IO
tests in isolation with mocks and stubs
dependency injection
first discover
hard things in OOP can be easy in FP (tests)
boundaries
third layer: IO
hexagonal architecture in FP is natural
push impure code to the boundaries
great discovery!
but, are we leveraring FP to its max?
services need to communicate
None
second layer with imperative code and side effects
why not imperative? harder to reason about harder to compose
harder to test slower feedback
why not imperative? harder to reason about harder to compose
harder to test slower feedback
why not imperative? (block! card datomic producer) ; =>
why not imperative? (defn block! [card datomic producer] (when (logic.card/can-block?
card) (let [locked-card (logic.card/block card)] (datomic.card/update! blocked-card datomic) (producer.card/status-changed! blocked-card producer))))
why not imperative? harder to reason about harder to compose
harder to test slower feedback
why not imperative? (defn block-all! [customer cards datomic producer] (doseq
[card cards] (block! card datomic producer)) (cards-blocked-notify! customer producer))
why not imperative? (defn block-all! [customer cards datomic producer] (doseq
[card cards] (block! card datomic producer)) (cards-blocked-notify! customer producer))
why not imperative? (defn block-all! [customer cards datomic producer] (doseq
[card cards] (block! card datomic producer)) (cards-blocked-notify! customer producer))
why not imperative? harder to reason about harder to compose
harder to test slower feedback
why not imperative? mocks & integration tests
None
Unit Integration E2E
why not imperative? harder to reason about harder to compose
harder to test slower feedback
None
❌ pure functions ❌ tests ❌ maintainability
let's try another approach
declaring effects on the return of functions
decouple decisions from effects
decouple intent from execution
(block card) ; => [{:effects/datoms [...] ; :effects/messages [...]}]
data as first class citizens
declarative
atomic operations
Global dependencies
Global dependencies Dependency injection
Dependency rejection Global dependencies Dependency injection
(defn block [card] (if (logic.card/can-block? card) (let [blocked-card (logic.card/block card)]
(-> e/empty-effects (effect.card/update blocked-card) (effect.card/status-changed blocked-card)))) e/empty-effects))
None
second layer without side effects
become more expressive
✅ pure functions ✅ tests ✅ maintainability
Thanks! We're hiring! https://grnh.se/5fc5f7e51 @mpivaa github.com/mpivaa instagram.com/mah.piva