Migrating a complex JS app
to ClojureScript
Alex King
Slide 2
Slide 2 text
Alexander James King
• github.com/alexanderjamesking
• Clojure dev at Exoscale
• Clojure(script) / Scala / Java / JS
• Previous: JUXT / BBC / HMRC
Slide 3
Slide 3 text
No content
Slide 4
Slide 4 text
• European cloud provider
• Data centres in Switzerland, Germany and Austria
• CPU, GPU, Object Storage, Elastic IPs, DNS, Run Status
• Data Security, GDPR Compliance, Data Privacy
Slide 5
Slide 5 text
No content
Slide 6
Slide 6 text
No content
Slide 7
Slide 7 text
Product
Problems
Going fast
Implementation
Lessons learned
Conclusion
Slide 8
Slide 8 text
No content
Slide 9
Slide 9 text
No content
Slide 10
Slide 10 text
No content
Slide 11
Slide 11 text
Browser
Python
API
Architecture
JS
Platform
API
Gateway
Slide 12
Slide 12 text
Product
Problems
Going fast
Implementation
Lessons learned
Conclusion
Slide 13
Slide 13 text
#1 Feature Slowdown
Features
Time
Slide 14
Slide 14 text
#2 Tests
UI
Integration
Unit
Manual
Slide 15
Slide 15 text
#3 Tooling
Slide 16
Slide 16 text
No content
Slide 17
Slide 17 text
No content
Slide 18
Slide 18 text
No content
Slide 19
Slide 19 text
No content
Slide 20
Slide 20 text
No content
Slide 21
Slide 21 text
Problems
• Velocity
• Lack of tests
• Tooling
• Build tools
• Dependencies
• Speed of change
Slide 22
Slide 22 text
Product
Problems
Going fast
Implementation
Lessons learned
Conclusion
Slide 23
Slide 23 text
–Robert Cecil Martin
“The higher the quality, the faster you go.
The only way to go fast is to go well.”
Slide 24
Slide 24 text
Improving the Quality
• Tests at all levels of the pyramid
• Fewer dependencies
• Small, focused libraries
• Better tooling
ClojureScript
Reitit
Integrant
re-frame
More
Dependencies!
Reagent
Slide 27
Slide 27 text
“Sometimes, things have to get
worse before they can get better”
Slide 28
Slide 28 text
Product
Problems
Going fast
Implementation
Lessons learned
Conclusion
Slide 29
Slide 29 text
The grand redesign in the sky
This time we will get it right!
Slide 30
Slide 30 text
No content
Slide 31
Slide 31 text
No content
Slide 32
Slide 32 text
No content
Slide 33
Slide 33 text
Greenfield vs Brownfield
Build a Replacement
Not very agile ∴ High risk
Moving target ∴ High risk
Migrate the existing app
Agile ∴ Low risk
Complex ∴ Medium risk
Slide 34
Slide 34 text
Brownfield:
Migrate the existing app
Slide 35
Slide 35 text
How can we migrate?
URL: Server
Page reloads (e.g nginx)
URL: Browser
HTML5 History API
Component
Lots of JS Interop
1 2
3
Slide 36
Slide 36 text
Clojure
Python
:option-1 URL: Server
JS
CLJS
Slide 37
Slide 37 text
Clojure
Python
:option-1 URL: Server
JS
CLJS
Slide 38
Slide 38 text
Clojure
Python
:option-1 URL: Server
JS
CLJS
+ Clean codebase
- Page reloads required
- Multiple apps to manage
Slide 39
Slide 39 text
Python
:option-2 URL: Browser
JS
CLJS
A2
Router
A1
Router
History
API
Slide 40
Slide 40 text
Python
:option-2 URL: Browser
JS
CLJS
A2
Router
Router A1
History
API
Slide 41
Slide 41 text
Python
:option-2 URL: Browser
JS
CLJS
A2
Router A1
+Single app
+No page reloads
- Challenging Interop?
History
API
::namespaced/keywords
• Namespace owns the data
• Avoid deeply nested DB
• Avoid circular dependencies
• (::ip/list not :portal.data.ip/list)
• Separate transient and persistent state