SlideShare a Scribd company logo
Immutability
And how I do it in JavaScripts
Shameless self-promotion
CrossHub Chrome Extension
Go to Declaration and “Find Usages” for TypeScript

projects on Github
textik.com
ASCII diagrams drawer
I’m not going to talk about

let vs const vs var
const is for
immutable
bindings
const foo = 1;
foo = 2; // nope
const someObject = {};
someObject["foo"] = "bar"; // yup
It’s an object, that cannot be modified after it’s creation
Immutable Object
Who cares!

¯_(ツ)_/¯
Very useful in multithreaded
environments
When you’re sure nothing will change this object, it helps
making assumptions about the code
Still helps reasoning about the code
function main() {
const foo = new Foo();
const bar = calculateBar(foo);
// You know that `calculateBar` would never
// change internals of foo
}
Performance is better
Caching is simpler, you can cache more
class SomeClass {
get someSeriousNumber() {
if (this._someSeriousNumber == null) {
this._someSeriousNumber = this.heavyCalculation();
}
return this._someSeriousNumber;
}
}
Performance is better
Reusable parts of nested existing objects
make it fast and memory efficient to clone
{
project: {
pages: [
{id: 1, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
{id: 2, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
{id: 3, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
{id: 4, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
{id: 5, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
]
}
}
Performance is better
Reusable parts of nested existing objects
make it fast and memory efficient to clone
{
project: {
pages: [
{id: 1, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
{id: 2, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
{id: 3, page_items: [{type: "sticker", bounds: [1,1,30,40]}]},
{id: 4, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
{id: 5, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
]
}
}
Performance is better
Reusable parts of nested existing objects
make it fast and memory efficient to clone
{
project: {
pages: [
{id: 1, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
{id: 2, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
{id: 3, page_items: [{type: "sticker", bounds: [1,1,30,40]}]},
{id: 4, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
{id: 5, page_items: [{type: "sticker", bounds: [1,1,3,4]}]},
]
}
}
Performance is better
Equality is faster
foo.hashCode();
// => 3247253721
foo.hashCode() === bar.hashCode();
// if false - they are not equal
// if true - ¯_(ツ)_/¯
Performance is better
Equality is faster
1 function equals(a, b) {
2 if (a === b) {
3 return true;
4 } else if (a != null) {
5 if (isHashable(a) && isHashable(b) && a.hashCode() !== b.hashCode()) {
6 return false;
7 } else if (isEquatable(a)) {
8 return a.equals(b);
9 } else if (a instanceof Array && b instanceof Array) {
10 return areArraysEqual(a, b);
11 } else if (a instanceof Map && b instanceof Map) {
12 return areMapsEqual(a, b);
13 } else if (a instanceof Set && b instanceof Set) {
14 return areSetsEqual(a, b);
15 } else if (isPlainObject(a) && isPlainObject(b)) {
16 return arePlainObjectsEqual(a, b);
17 } else {
18 return _.isEqual(a, b);
19 }
20 } else {
21 return _.isEqual(a, b);
22 }
23 }
You can control the level of uniqueness of your hashcodes
Usually you recursively go through all
the children of an object to calculate a
hash code
Sometimes you could just use some
model id
Performance is better
Equality is faster
Object.freeze
How to make an
immutable object?
1 const obj = Object.freeze({a: "1"});
2 obj.a = "8";
3 obj.a;
4 // => 1
5 // => or throws, if in strict mode
Value Object
1 class Entity {
2 constructor(data) {
3 this._data = Object.freeze(data);
4 }
5
6 update(data) {
7 const newData = {...this._data, ...data};
8 return new this.constructor(newData);
9 }
10
11 equals(other) {
12 if (other instanceof this.constructor) {
13 return equals(this._data, other._data);
14 } else {
15 return false;
16 }
17 }
18
19 hashCode() {
20 if (this._hashCode == null) {
21 this._hashCode = hash(this._data);
22 }
23 return this._hashCode;
24 }
25 }
26
const foo = new Foo({a: 1});
const foo2 = new Foo({a: 1});
foo === foo2;
// false => equality by identity
foo.equals(foo2);
// true => equality by value
Value Object
1 class Entity {
2 constructor(data) {
3 this._data = Object.freeze(data);
4 }
5
6 update(data) {
7 const newData = {...this._data, ...data};
8 return new this.constructor(newData);
9 }
10
11 equals(other) {
12 if (other instanceof this.constructor) {
13 return equals(this._data, other._data);
14 } else {
15 return false;
16 }
17 }
18
19 hashCode() {
20 if (this._hashCode == null) {
21 this._hashCode = hash(this._data);
22 }
23 return this._hashCode;
24 }
25 }
26
1 class Email extends Entity {
2 get from() {
3 return this._data.from;
4 }
5
6 get to() {
7 return this._data.to;
8 }
9
10 get subject() {
11 return this._data.subject;
12 }
13 }
14
15 const email = new Email({
16 from: "anton.astashov@gmail.com",
17 to: "tcook@apple.com",
18 subject: "New Macbook Pro feedback"
19 });
20
21 const email2 = email.update({
22 from: "jive@apple.com"
23 })
24
25 console.log(email.equals(email2));
26 // => false
There’s Record in Immutable JS

Though `equals` there doesn’t use hash codes

unless you already have them calculated and cached.
Value Object
1 class ABClass extends Record({a: 1, b: 2}) {
2 constructor(...rest) {
3 super(...rest);
4 this.hashCode();
5 }
6 // ...
7 }
Collection
Most objects in an application
Value Object
or
Collections
Implement Persistent
Data Structures
Just build immutable interface, but use
regular mutable collections under the hood
Very efficient updates, inserts and deletions
Persistent Data Structures
Very efficient updates, inserts and deletions
Persistent Data Structures
80 elements - only 3 nodes to recreate,

33 refs to recreate.
1000000 elements - 5 nodes to recreate

81 refs to recreate
Usually used parent-to-child ratio of 16
Persistent Data Structures
Even on very big collections (billions of
records), updating is only ~10-20x times
slower than updating a mutable
collection
Memory efficient
Persistent Data Structures
Mori Immutable JS
• Global state is a huge Immutable.JS object

• Very fast checks for changes in subtree
allows to write super-fast
shouldComponentUpdate checks
It plays especially
nice with Redux
Immutability FTW
Caveats
Some algorithms are harder to implement in immutable
data structures
Sometimes the performance of updates is actually
a show stopper

Immutable.JS offers a shortcut - withMutations()
const list = List.of(1, 2, 3);
const list2 = list.withMutations(mutableList => {
mutableList.push(4);
mutableList.push(5);
});
Updates are harder
{project: {
name: "Project",
pages: [{
author: "Me",
posts: [{
content: "Content"
}]
}]
}}
1 // Mutable approach
2 project.pages[0].posts[0].content = "New one";
1 // Naive approach
2 const newPosts = project
3 .get("pages").get(0).get("posts")
4 .update(0, () => Immutable.Map({content: "New one"}));
5 const newPages = project
6 .get("pages")
7 .update(0, (v) => v.set("posts", newPosts);
8 const newProject = project.set("pages", newPages);
1 // Using updateIn - not type safe approach
2 const newProject = project.updateIn(
3 ["project", "pages", 0, "posts", 0, "content"],
4 () => "New one"
5 );
1 // Typesafe and flexible, but verbose approach
2 const newProject = pagesLens(0)
3 .then(postsLens(0))
4 .modify(
5 projects,
6 (oldValue) => oldValue.update({content: "New one"}));
Using wrong reference
Piping:
function main() {
let result = "hello"
|> doubleSay
|> capitalize
|> exclaim;
// => "Hello, hello!"
}
1 function main() {
2 const result = "hello";
3 const result2 = capitalize(result);
4 const result3 = doubleSay(result);
5 const result4 = exclaim(result3);
6 // => "hello, hello!"
7 }
Using wrong reference
1 class Page {
2 // ...
3 doStuff() {
4 let post = this.posts.get(0);
5 post = post.update({content: "New content"});
6 const author = this.postsToAuthors.get(post);
7 notifyAuthor(author);
8 // author is null, because it's totally different post now
9 return post;
10 }
11 }
12
I think it’d be cool, if JS’ Array, Map and Set
would be persistent collections
I still use immutable objects
by default in my projects
Never gonna happen tho
Thanks!

More Related Content

What's hot

Oop lecture9 13
Oop lecture9 13Oop lecture9 13
Oop lecture9 13
Shahriar Robbani
 
Machine Learning Live
Machine Learning LiveMachine Learning Live
Machine Learning Live
Mike Anderson
 
Everything is composable
Everything is composableEverything is composable
Everything is composable
Victor Igor
 
Lecture06 methods for-making_data_structures_v2
Lecture06 methods for-making_data_structures_v2Lecture06 methods for-making_data_structures_v2
Lecture06 methods for-making_data_structures_v2
Hariz Mustafa
 
Clojure for Data Science
Clojure for Data ScienceClojure for Data Science
Clojure for Data Science
Mike Anderson
 
Python lec5
Python lec5Python lec5
Python lec5
Swarup Ghosh
 
Why Haskell
Why HaskellWhy Haskell
Why Haskell
Susan Potter
 
Clojure: The Art of Abstraction
Clojure: The Art of AbstractionClojure: The Art of Abstraction
Clojure: The Art of Abstraction
Alex Miller
 
Building a website in Haskell coming from Node.js
Building a website in Haskell coming from Node.jsBuilding a website in Haskell coming from Node.js
Building a website in Haskell coming from Node.js
Nicolas Hery
 
Algorithms devised for a google interview
Algorithms devised for a google interviewAlgorithms devised for a google interview
Algorithms devised for a google interview
Russell Childs
 
Python lec4
Python lec4Python lec4
Python lec4
Swarup Ghosh
 
Aplikasi rawat-inap-vbnet
Aplikasi rawat-inap-vbnetAplikasi rawat-inap-vbnet
Aplikasi rawat-inap-vbnet
Diaz Alfahrezy
 
Tutorial matlab
Tutorial matlabTutorial matlab
Tutorial matlab
Kavin Patel
 
Lecture07 the linked-list_as_a_data_structure_v3
Lecture07 the linked-list_as_a_data_structure_v3Lecture07 the linked-list_as_a_data_structure_v3
Lecture07 the linked-list_as_a_data_structure_v3
Hariz Mustafa
 
JavaScript Functions
JavaScript Functions JavaScript Functions
JavaScript Functions
Reem Alattas
 
MongoDB and Indexes - MUG Denver - 20160329
MongoDB and Indexes - MUG Denver - 20160329MongoDB and Indexes - MUG Denver - 20160329
MongoDB and Indexes - MUG Denver - 20160329
Douglas Duncan
 
String in .net
String in .netString in .net
String in .net
Larry Nung
 
Fast querying indexing for performance (4)
Fast querying   indexing for performance (4)Fast querying   indexing for performance (4)
Fast querying indexing for performance (4)
MongoDB
 
Javascript built in String Functions
Javascript built in String FunctionsJavascript built in String Functions
Javascript built in String Functions
Avanitrambadiya
 
JavaScript Objects
JavaScript ObjectsJavaScript Objects
JavaScript Objects
Reem Alattas
 

What's hot (20)

Oop lecture9 13
Oop lecture9 13Oop lecture9 13
Oop lecture9 13
 
Machine Learning Live
Machine Learning LiveMachine Learning Live
Machine Learning Live
 
Everything is composable
Everything is composableEverything is composable
Everything is composable
 
Lecture06 methods for-making_data_structures_v2
Lecture06 methods for-making_data_structures_v2Lecture06 methods for-making_data_structures_v2
Lecture06 methods for-making_data_structures_v2
 
Clojure for Data Science
Clojure for Data ScienceClojure for Data Science
Clojure for Data Science
 
Python lec5
Python lec5Python lec5
Python lec5
 
Why Haskell
Why HaskellWhy Haskell
Why Haskell
 
Clojure: The Art of Abstraction
Clojure: The Art of AbstractionClojure: The Art of Abstraction
Clojure: The Art of Abstraction
 
Building a website in Haskell coming from Node.js
Building a website in Haskell coming from Node.jsBuilding a website in Haskell coming from Node.js
Building a website in Haskell coming from Node.js
 
Algorithms devised for a google interview
Algorithms devised for a google interviewAlgorithms devised for a google interview
Algorithms devised for a google interview
 
Python lec4
Python lec4Python lec4
Python lec4
 
Aplikasi rawat-inap-vbnet
Aplikasi rawat-inap-vbnetAplikasi rawat-inap-vbnet
Aplikasi rawat-inap-vbnet
 
Tutorial matlab
Tutorial matlabTutorial matlab
Tutorial matlab
 
Lecture07 the linked-list_as_a_data_structure_v3
Lecture07 the linked-list_as_a_data_structure_v3Lecture07 the linked-list_as_a_data_structure_v3
Lecture07 the linked-list_as_a_data_structure_v3
 
JavaScript Functions
JavaScript Functions JavaScript Functions
JavaScript Functions
 
MongoDB and Indexes - MUG Denver - 20160329
MongoDB and Indexes - MUG Denver - 20160329MongoDB and Indexes - MUG Denver - 20160329
MongoDB and Indexes - MUG Denver - 20160329
 
String in .net
String in .netString in .net
String in .net
 
Fast querying indexing for performance (4)
Fast querying   indexing for performance (4)Fast querying   indexing for performance (4)
Fast querying indexing for performance (4)
 
Javascript built in String Functions
Javascript built in String FunctionsJavascript built in String Functions
Javascript built in String Functions
 
JavaScript Objects
JavaScript ObjectsJavaScript Objects
JavaScript Objects
 

Similar to Immutability, and how to do it in JavaScripts

Advanced JavaScript
Advanced JavaScript Advanced JavaScript
Advanced JavaScript
Zsolt Mészárovics
 
2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScript2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScript
Johannes Hoppe
 
2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScript2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScript
Johannes Hoppe
 
Es6 hackathon
Es6 hackathonEs6 hackathon
Es6 hackathon
Justin Alexander
 
Intro to Javascript
Intro to JavascriptIntro to Javascript
Intro to Javascript
Anjan Banda
 
ES6 and AngularAMD
ES6 and AngularAMDES6 and AngularAMD
ES6 and AngularAMD
dhaval10690
 
1. George Shevtsov - Functional JavaScript
1. George Shevtsov - Functional JavaScript1. George Shevtsov - Functional JavaScript
1. George Shevtsov - Functional JavaScript
Innovecs
 
FunctionalJS - George Shevtsov
FunctionalJS - George ShevtsovFunctionalJS - George Shevtsov
FunctionalJS - George Shevtsov
Georgiy Shevtsov
 
Ajax and JavaScript Bootcamp
Ajax and JavaScript BootcampAjax and JavaScript Bootcamp
Ajax and JavaScript Bootcamp
AndreCharland
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
stasimus
 
Wakanday JS201 Best Practices
Wakanday JS201 Best PracticesWakanday JS201 Best Practices
Wakanday JS201 Best Practices
Juergen Fesslmeier
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of Javascript
Tarek Yehia
 
Internal workshop es6_2015
Internal workshop es6_2015Internal workshop es6_2015
Internal workshop es6_2015
Miguel Ruiz Rodriguez
 
Stuff you didn't know about action script
Stuff you didn't know about action scriptStuff you didn't know about action script
Stuff you didn't know about action script
Christophe Herreman
 
Javascript variables and datatypes
Javascript variables and datatypesJavascript variables and datatypes
Javascript variables and datatypes
Varun C M
 
Typescript barcelona
Typescript barcelonaTypescript barcelona
Typescript barcelona
Christoffer Noring
 
Latinoware
LatinowareLatinoware
Latinoware
kchodorow
 
Introduction to Client-Side Javascript
Introduction to Client-Side JavascriptIntroduction to Client-Side Javascript
Introduction to Client-Side Javascript
Julie Iskander
 
Real life-coffeescript
Real life-coffeescriptReal life-coffeescript
Real life-coffeescript
David Furber
 
Functional programming basics
Functional programming basicsFunctional programming basics
Functional programming basics
openbala
 

Similar to Immutability, and how to do it in JavaScripts (20)

Advanced JavaScript
Advanced JavaScript Advanced JavaScript
Advanced JavaScript
 
2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScript2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScript
 
2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScript2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScript
 
Es6 hackathon
Es6 hackathonEs6 hackathon
Es6 hackathon
 
Intro to Javascript
Intro to JavascriptIntro to Javascript
Intro to Javascript
 
ES6 and AngularAMD
ES6 and AngularAMDES6 and AngularAMD
ES6 and AngularAMD
 
1. George Shevtsov - Functional JavaScript
1. George Shevtsov - Functional JavaScript1. George Shevtsov - Functional JavaScript
1. George Shevtsov - Functional JavaScript
 
FunctionalJS - George Shevtsov
FunctionalJS - George ShevtsovFunctionalJS - George Shevtsov
FunctionalJS - George Shevtsov
 
Ajax and JavaScript Bootcamp
Ajax and JavaScript BootcampAjax and JavaScript Bootcamp
Ajax and JavaScript Bootcamp
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
 
Wakanday JS201 Best Practices
Wakanday JS201 Best PracticesWakanday JS201 Best Practices
Wakanday JS201 Best Practices
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of Javascript
 
Internal workshop es6_2015
Internal workshop es6_2015Internal workshop es6_2015
Internal workshop es6_2015
 
Stuff you didn't know about action script
Stuff you didn't know about action scriptStuff you didn't know about action script
Stuff you didn't know about action script
 
Javascript variables and datatypes
Javascript variables and datatypesJavascript variables and datatypes
Javascript variables and datatypes
 
Typescript barcelona
Typescript barcelonaTypescript barcelona
Typescript barcelona
 
Latinoware
LatinowareLatinoware
Latinoware
 
Introduction to Client-Side Javascript
Introduction to Client-Side JavascriptIntroduction to Client-Side Javascript
Introduction to Client-Side Javascript
 
Real life-coffeescript
Real life-coffeescriptReal life-coffeescript
Real life-coffeescript
 
Functional programming basics
Functional programming basicsFunctional programming basics
Functional programming basics
 

Recently uploaded

Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
Remote DBA Services
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
dakas1
 
Preparing Non - Technical Founders for Engaging a Tech Agency
Preparing Non - Technical Founders for Engaging  a  Tech AgencyPreparing Non - Technical Founders for Engaging  a  Tech Agency
Preparing Non - Technical Founders for Engaging a Tech Agency
ISH Technologies
 
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabhQuarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
aisafed42
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
Peter Muessig
 
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
XfilesPro
 
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
The Third Creative Media
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
gapen1
 
Kubernetes at Scale: Going Multi-Cluster with Istio
Kubernetes at Scale:  Going Multi-Cluster  with IstioKubernetes at Scale:  Going Multi-Cluster  with Istio
Kubernetes at Scale: Going Multi-Cluster with Istio
Severalnines
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
Karya Keeper
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
sjcobrien
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
rodomar2
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
Peter Muessig
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Peter Caitens
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
Sven Peters
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
Maitrey Patel
 

Recently uploaded (20)

Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
 
Preparing Non - Technical Founders for Engaging a Tech Agency
Preparing Non - Technical Founders for Engaging  a  Tech AgencyPreparing Non - Technical Founders for Engaging  a  Tech Agency
Preparing Non - Technical Founders for Engaging a Tech Agency
 
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabhQuarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
 
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
 
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
Unlock the Secrets to Effortless Video Creation with Invideo: Your Ultimate G...
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
 
Kubernetes at Scale: Going Multi-Cluster with Istio
Kubernetes at Scale:  Going Multi-Cluster  with IstioKubernetes at Scale:  Going Multi-Cluster  with Istio
Kubernetes at Scale: Going Multi-Cluster with Istio
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
 

Immutability, and how to do it in JavaScripts

  • 1. Immutability And how I do it in JavaScripts
  • 2. Shameless self-promotion CrossHub Chrome Extension Go to Declaration and “Find Usages” for TypeScript projects on Github textik.com ASCII diagrams drawer
  • 3. I’m not going to talk about let vs const vs var const is for immutable bindings const foo = 1; foo = 2; // nope const someObject = {}; someObject["foo"] = "bar"; // yup
  • 4. It’s an object, that cannot be modified after it’s creation Immutable Object
  • 5. Who cares! ¯_(ツ)_/¯ Very useful in multithreaded environments
  • 6. When you’re sure nothing will change this object, it helps making assumptions about the code Still helps reasoning about the code function main() { const foo = new Foo(); const bar = calculateBar(foo); // You know that `calculateBar` would never // change internals of foo }
  • 7. Performance is better Caching is simpler, you can cache more class SomeClass { get someSeriousNumber() { if (this._someSeriousNumber == null) { this._someSeriousNumber = this.heavyCalculation(); } return this._someSeriousNumber; } }
  • 8. Performance is better Reusable parts of nested existing objects make it fast and memory efficient to clone { project: { pages: [ {id: 1, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, {id: 2, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, {id: 3, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, {id: 4, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, {id: 5, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, ] } }
  • 9. Performance is better Reusable parts of nested existing objects make it fast and memory efficient to clone { project: { pages: [ {id: 1, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, {id: 2, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, {id: 3, page_items: [{type: "sticker", bounds: [1,1,30,40]}]}, {id: 4, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, {id: 5, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, ] } }
  • 10. Performance is better Reusable parts of nested existing objects make it fast and memory efficient to clone { project: { pages: [ {id: 1, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, {id: 2, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, {id: 3, page_items: [{type: "sticker", bounds: [1,1,30,40]}]}, {id: 4, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, {id: 5, page_items: [{type: "sticker", bounds: [1,1,3,4]}]}, ] } }
  • 11. Performance is better Equality is faster foo.hashCode(); // => 3247253721 foo.hashCode() === bar.hashCode(); // if false - they are not equal // if true - ¯_(ツ)_/¯
  • 12. Performance is better Equality is faster 1 function equals(a, b) { 2 if (a === b) { 3 return true; 4 } else if (a != null) { 5 if (isHashable(a) && isHashable(b) && a.hashCode() !== b.hashCode()) { 6 return false; 7 } else if (isEquatable(a)) { 8 return a.equals(b); 9 } else if (a instanceof Array && b instanceof Array) { 10 return areArraysEqual(a, b); 11 } else if (a instanceof Map && b instanceof Map) { 12 return areMapsEqual(a, b); 13 } else if (a instanceof Set && b instanceof Set) { 14 return areSetsEqual(a, b); 15 } else if (isPlainObject(a) && isPlainObject(b)) { 16 return arePlainObjectsEqual(a, b); 17 } else { 18 return _.isEqual(a, b); 19 } 20 } else { 21 return _.isEqual(a, b); 22 } 23 }
  • 13. You can control the level of uniqueness of your hashcodes Usually you recursively go through all the children of an object to calculate a hash code Sometimes you could just use some model id Performance is better Equality is faster
  • 14. Object.freeze How to make an immutable object? 1 const obj = Object.freeze({a: "1"}); 2 obj.a = "8"; 3 obj.a; 4 // => 1 5 // => or throws, if in strict mode
  • 15. Value Object 1 class Entity { 2 constructor(data) { 3 this._data = Object.freeze(data); 4 } 5 6 update(data) { 7 const newData = {...this._data, ...data}; 8 return new this.constructor(newData); 9 } 10 11 equals(other) { 12 if (other instanceof this.constructor) { 13 return equals(this._data, other._data); 14 } else { 15 return false; 16 } 17 } 18 19 hashCode() { 20 if (this._hashCode == null) { 21 this._hashCode = hash(this._data); 22 } 23 return this._hashCode; 24 } 25 } 26 const foo = new Foo({a: 1}); const foo2 = new Foo({a: 1}); foo === foo2; // false => equality by identity foo.equals(foo2); // true => equality by value
  • 16. Value Object 1 class Entity { 2 constructor(data) { 3 this._data = Object.freeze(data); 4 } 5 6 update(data) { 7 const newData = {...this._data, ...data}; 8 return new this.constructor(newData); 9 } 10 11 equals(other) { 12 if (other instanceof this.constructor) { 13 return equals(this._data, other._data); 14 } else { 15 return false; 16 } 17 } 18 19 hashCode() { 20 if (this._hashCode == null) { 21 this._hashCode = hash(this._data); 22 } 23 return this._hashCode; 24 } 25 } 26 1 class Email extends Entity { 2 get from() { 3 return this._data.from; 4 } 5 6 get to() { 7 return this._data.to; 8 } 9 10 get subject() { 11 return this._data.subject; 12 } 13 } 14 15 const email = new Email({ 16 from: "anton.astashov@gmail.com", 17 to: "tcook@apple.com", 18 subject: "New Macbook Pro feedback" 19 }); 20 21 const email2 = email.update({ 22 from: "jive@apple.com" 23 }) 24 25 console.log(email.equals(email2)); 26 // => false
  • 17. There’s Record in Immutable JS Though `equals` there doesn’t use hash codes unless you already have them calculated and cached. Value Object 1 class ABClass extends Record({a: 1, b: 2}) { 2 constructor(...rest) { 3 super(...rest); 4 this.hashCode(); 5 } 6 // ... 7 }
  • 18. Collection Most objects in an application Value Object or
  • 19. Collections Implement Persistent Data Structures Just build immutable interface, but use regular mutable collections under the hood
  • 20. Very efficient updates, inserts and deletions Persistent Data Structures
  • 21. Very efficient updates, inserts and deletions Persistent Data Structures 80 elements - only 3 nodes to recreate, 33 refs to recreate. 1000000 elements - 5 nodes to recreate 81 refs to recreate
  • 22. Usually used parent-to-child ratio of 16 Persistent Data Structures Even on very big collections (billions of records), updating is only ~10-20x times slower than updating a mutable collection Memory efficient
  • 24. • Global state is a huge Immutable.JS object • Very fast checks for changes in subtree allows to write super-fast shouldComponentUpdate checks It plays especially nice with Redux
  • 26. Caveats Some algorithms are harder to implement in immutable data structures Sometimes the performance of updates is actually a show stopper Immutable.JS offers a shortcut - withMutations() const list = List.of(1, 2, 3); const list2 = list.withMutations(mutableList => { mutableList.push(4); mutableList.push(5); });
  • 27. Updates are harder {project: { name: "Project", pages: [{ author: "Me", posts: [{ content: "Content" }] }] }} 1 // Mutable approach 2 project.pages[0].posts[0].content = "New one"; 1 // Naive approach 2 const newPosts = project 3 .get("pages").get(0).get("posts") 4 .update(0, () => Immutable.Map({content: "New one"})); 5 const newPages = project 6 .get("pages") 7 .update(0, (v) => v.set("posts", newPosts); 8 const newProject = project.set("pages", newPages); 1 // Using updateIn - not type safe approach 2 const newProject = project.updateIn( 3 ["project", "pages", 0, "posts", 0, "content"], 4 () => "New one" 5 ); 1 // Typesafe and flexible, but verbose approach 2 const newProject = pagesLens(0) 3 .then(postsLens(0)) 4 .modify( 5 projects, 6 (oldValue) => oldValue.update({content: "New one"}));
  • 28. Using wrong reference Piping: function main() { let result = "hello" |> doubleSay |> capitalize |> exclaim; // => "Hello, hello!" } 1 function main() { 2 const result = "hello"; 3 const result2 = capitalize(result); 4 const result3 = doubleSay(result); 5 const result4 = exclaim(result3); 6 // => "hello, hello!" 7 }
  • 29. Using wrong reference 1 class Page { 2 // ... 3 doStuff() { 4 let post = this.posts.get(0); 5 post = post.update({content: "New content"}); 6 const author = this.postsToAuthors.get(post); 7 notifyAuthor(author); 8 // author is null, because it's totally different post now 9 return post; 10 } 11 } 12
  • 30. I think it’d be cool, if JS’ Array, Map and Set would be persistent collections I still use immutable objects by default in my projects Never gonna happen tho