Data-Oriented programming in JavaScript
To Immutability and Beyond
Yehonathan Sharvit viebel
Data-Oriented programming in JavaScript
To Immutability and Beyond
Yehonathan Sharvit viebel
💻 Developer since 2001 (JavaScript since 2009, Clojure since 2012)
🎁️Maintainer of Klipse
📖 Author of Data-Oriented programming
📝 Blogger at blog.klipse.tech
👷Software architect at Cycognito (we are hiring)
Complexity of information systems
Principles of Data-Oriented programming
Various ways to achieve data immutability in JavaScript
⚙️Computational complexity
The amount of machine resources (e.g. CPU, memory) required to run a program.
😰 System Complexity
The amount of brain resources required to understand a system.
Systems that manipulate real-word information and activity.
Examples of information systems:
Web services that fetch data from data sources and serves it as JSON
Web workers that listen to events and enrich event data from multiple data sources
Front end applications that communicate with a back end
A programming paradigm aimed at
reducing complexity of information systems by
treating data as a first-class citizen ️
Principles
Separate code from data
Represent data with generic data structures
Do not mutate data
Avoid hidden side effects
Thread safety without locks
Simpler state management
Optimistic locking
Time travel
Work on a snapshot
Values never change
Fast equality check
Testability
Easier to test results than side-effects
Order of tests might have an impact on test results
Development time
Reproducibility
JavaScript is single threaded
Services are usually stateless
function setBackgroundColor(color) {
var elem = document.getElementById("book-list");
elem.style.backgroundColor = color;
}
function benchmark(iterations, f) {
var start = new Date();
for (var i = 0; i < iterations; i++) {
f();
}
var end = new Date();
return "Elapsed time: " + (end - start) + " msec";
}
A member of an online library
| Data enrichment
|
What happened to |
|
| Watchmen |
The fundamental theorem of JavaScript:
We can solve any problem in JavaScript with a library
and a couple of changes to ECMAScript
The old LISP way!
|
|
Let’s clone!
| kelly is untouched
|
⚠️Performance issues: Memory consumption, CPU consumption
The fundamental theorem of data immutability:
It is safe to share immutable data.
var kelly = {
email: "kelly@doe.com", history: [/*huge array*/],
details: {
books: 0, preferences: {
theme: "dark", notifications: true
}
}
}
var updatedKelly = {
...kelly,
details: {
...kelly.details,
preferences: {
...kelly.details.preferences,
theme: "light"
}
}
}
Original version
| Create new version
|
Original version is untouched
| Data in common is shared
|
⚠️Mutations could happen by accident
⚠️Not IDE/TypeScript friendly
|
|
In non-strict mode
| In strict mode
|
⚠️We need to remember to freeze
Original version
| Create new version
|
Original version is untouched
| New version is frozen
|
Records
| Associative arrays
|
Economizing on mechanisms and concepts for want of time, as I've discussed with many over the years. See the HOPL IV paper (https://t.co/T067GT5DOn) or my interview with Lex Fridman (https://t.co/7Jr8AVkyOl).
— BrendanEich (@BrendanEich) April 23, 2021
"... plurality should not be posited without necessity" (Ockham)
— BrendanEich (@BrendanEich) April 24, 2021
Structural sharing doesn’t scale with associative arrays
Shallow copying becomes expensive
Welcome HAMT and Immutable.js
var brown = Immutable.List([0, 1, 2, 3, 4, 5, 6, 7, 8])
var blue = brown.set(5, "beef")
A big native object
| A big immutable map
|
Perfs on shallow copying
| Perfs of advanced structural sharing
|
⚠️CPU consumption during conversion to native Objects
|
|
Fake it…
| ... until you make it
|
|
|
Equality is defined by value
| Data cannot me accidentally mutated
|
Various ways to achieve immutability:
Spread operator
Lodash FP
Immer
Immutable.js
JavaScript Records
Parameters to consider:
State management
Associative arrays or records