SlideShare une entreprise Scribd logo
1  sur  25
Télécharger pour lire hors ligne
Records & Tuples
Bien plus que l'immuabilité
1 @sebastienlorber
Sébastien Lorber
• Twitter: @sebastienlorber
• Blog: sebastienlorber.com
• 2014: CTO, dev React / Scala
• 2017: expert React freelance
• 2020: open-source lead dev Facebook / Docusaurus
2 @sebastienlorber
• React Hebdo: sebastienlorber.com/newsletter
• Chat React Hebdo: sebastienlorber.com/chat
3 @sebastienlorber
Records & Tuples
• Proposition comité TC 39
• Stage 2
• Structures immuables en JavaScript
• Comportement primitive composée: sous-évalué
4 @sebastienlorber
Records & Tuples 101
Les bases
5 @sebastienlorber
Record: sorte d'objet immuable
const record = #{a: 1, b: 2};
console.log(record);
// #{a: 1, b: 2}
console.log(record.a);
// 1
record.b = 3;
// throws TypeError
const recordUpdated = #{...record, b: 3}
console.log(recordUpdated);
// #{a: 1, b: 3}
6 @sebastienlorber
Tuple: sorte de tableau immuable
const tuple = #[1, 5, 2, 3, 4];
console.log(tuple);
// #[1, 5, 2, 3, 4]
console.log(tuple[1]);
// 5
tuple[1] = 3;
// throws TypeError
console.log(tuple.filter(num => num > 2))
// #[5, 3, 4];
const tupleUpdated = #[...record, 7]
console.log(recordUpdated);
// #[1, 5, 2, 3, 4, 7]
7 @sebastienlorber
Syntaxe: # = raccourci
const record1 = #{a: 1, b: 2};
const record2 = Record({a: 1, b: 2});
const record3 = Record.fromEntries([#["a", 1], #["b", 2]]);
const tuple1 = #[1, 5, 2, 3, 4];
const tuple2 = Tuple(1, 5, 2, 3, 4);
const tuple3 = Tuple.from([1, 5, 2, 3, 4]);
8 @sebastienlorber
Imbrication: comme objets / tableaux
const data = #{
a: 1,
b: #[
3,
4,
#{c: "hello"}
],
};
9 @sebastienlorber
Types non primitifs: interdits
const record1 = #{
a: {regular: 'object'},
};
// throws TypeError, un objet n'est pas une primitive
const record2 = #{
b: new Date(),
};
// throws TypeError, Date n'est pas une primitive
const record3 = #{
c: new MyClass(),
};
// throws TypeError, MyClass n'est pas une primitive
const record4 = #{
d: function () { alert('forbidden'); },
};
// throws TypeError, une fonction n'est pas une primitive
10 @sebastienlorber
Types primitifs: autorisés
• string, number, boolean, bigint, symbol
• undefined, null
• Record, Tuple
11 @sebastienlorber
Identité des objets/tableaux:
const object1 = {a: 1, b: [3, 4]};
const object2 = {a: 1, b: [3, 4]};
console.log(object1 === object2);
// false
console.log(object1.a === object2.a);
// true
console.log(object1.b === object2.b);
// false
12 @sebastienlorber
Identité des records/tuples: primitives composées !!!
const record1 = #{a: 1, b: #[3, 4]};
const record2 = #{a: 1, b: #[3, 4]};
console.log(record1 === record2);
// true !!!
console.log(record1.a === record2.a);
// true (normal)
console.log(record1.b === record2.b);
// true !!!
13 @sebastienlorber
Intéropérabilité:
• très bonne avec JSON (types primitifs)
• correcte avec objects/tableaux
const record = JSON.parseImmutable('{a: 1, b: [2, 3]}');
// #{a: 1, b: #[2, 3]}
JSON.stringify(record);
// '{a: 1, b: [2, 3]}'
const record2 = Record({ a: 1, b: Tuple(2, 3) });
// #{a: 1, b: #[2, 3]}
const record3 = Record({ a: 1, b: new Date()});
// throws TypeError, Date n'est pas une primitive
14 @sebastienlorber
Updates immuables: toujours besoin de Lodash.set, ImmerJS...
const state = #{
user: #{
firstName: "Sebastien",
lastName: "Lorber"
age: 34,
}
company: #{
name: "Lambda Scale",
}
};
const updatedState = #{
...state,
user: #{
...state.user,
age: state.user.age + 1,
},
company: #{
...state.company,
name: 'Freelance',
},
};
15 @sebastienlorber
Updates immuables v2: proposition deep-path-properties-for-record
const state = #{
user: #{
firstName: "Sebastien",
lastName: "Lorber"
age: 34,
}
company: #{
name: "Lambda Scale",
}
};
const updatedState = #{
...state,
user.age: state.user.age + 1,
company.name: 'Freelance',
};
16 @sebastienlorber
Records & Tuples pour React
Plusieurs intérêts:
• Sécurité
• Comportement
• Performance
• Surface API explicite
17 @sebastienlorber
Sécurité: impossible de modifier les props ou le state
const Hello = ({ profile }) => {
profile.name = 'Sebastien updated';
// throws TypeError
return <p>Hello {profile.name}</p>;
};
function App() {
const [profile, setProfile] = React.useState(Record({name: 'Sebastien'}));
profile.name = 'Sebastien updated';
// throws TypeError
return <Hello profile={profile} />;
}
18 @sebastienlorber
Comportement: moins de ré-execution de useEffect
function UserAndCompanyPage() {
const [data, setData] = useState(null);
const apiFilters = Record({ userFilter, companyFilter });
useEffect(() => {
fetchUserAndCompanyData(apiFilters).then(setData);
}, [apiFilters]);
return <div>...</div>;
}
Empêche les boucles infinies
19 @sebastienlorber
Performance: React.memo plus efficace, useMemo "automatique"
const UserAndCompanyView = React.memo(({userAndCompany}) {
return <div>...</div>;
}
const App = () => {
const user = useUser();
const company = useCompany();
const userAndCompany = Record({user, company})
return <UserAndCompanyView userAndCompany={userAndCompany} />
}
20 @sebastienlorber
API surface:
• explicite grâce à TypeScript
• exprimer le besoin d'identités stable
type User = ImmutableRecord<{id: string, firstName: string, lastName: string}>
type Company = ImmutableRecord<{id: string, name: string}>
type MyComponentProps = {
userAndCompany: ImmutableRecord<{
user: User,
company: Company,
}>
}
21 @sebastienlorber
DemoCas vie réelle: refetch api backend periodique
Code
22 @sebastienlorber
Records & Tuples: tradeoffs
• Compléxifie JavaScript
• Stockage de types non primitifs: références
• Détails d'implémentation non spécifiés
• Benchmarks à venir
• Record TypeScript: conflict
23 @sebastienlorber
Conclusion
• Facile à prendre en main
• Immuabilité: cool
• Primitive composée: impact significatif
24 @sebastienlorber
Merci
Des questions ?
• Twitter: @sebastienlorber
• Email: lorber.sebastien@gmail.com
Resources:
• sebastienlorber.com/records-and-tuples-for-react
• 2ality.com/2020/05/records-tuples-first-look.html
• github.com/tc39/proposal-record-tuple
25 @sebastienlorber

Contenu connexe

Tendances

Introduction à JavaScript
Introduction à JavaScriptIntroduction à JavaScript
Introduction à JavaScriptMicrosoft
 
Les Langages Dédiés (DSL) au secours du Français ?
Les Langages Dédiés (DSL) au secours du Français ?Les Langages Dédiés (DSL) au secours du Français ?
Les Langages Dédiés (DSL) au secours du Français ?Damien Fourret
 
Notions de base de JavaScript
Notions de base de JavaScriptNotions de base de JavaScript
Notions de base de JavaScriptKristen Le Liboux
 
Javascript un langage supérieur
Javascript un langage supérieurJavascript un langage supérieur
Javascript un langage supérieurFredy Fadel
 

Tendances (6)

Introduction à JavaScript
Introduction à JavaScriptIntroduction à JavaScript
Introduction à JavaScript
 
Les Langages Dédiés (DSL) au secours du Français ?
Les Langages Dédiés (DSL) au secours du Français ?Les Langages Dédiés (DSL) au secours du Français ?
Les Langages Dédiés (DSL) au secours du Français ?
 
Notions de base de JavaScript
Notions de base de JavaScriptNotions de base de JavaScript
Notions de base de JavaScript
 
Javascript un langage supérieur
Javascript un langage supérieurJavascript un langage supérieur
Javascript un langage supérieur
 
Cours javascript v1
Cours javascript v1Cours javascript v1
Cours javascript v1
 
Playing With PHP 5.3
Playing With PHP 5.3Playing With PHP 5.3
Playing With PHP 5.3
 

Similaire à Records and Tuples, proposition pour JavaScript

Future of java script web version
Future of java script web versionFuture of java script web version
Future of java script web versionSébastien Pertus
 
Tout sur PHP 7.3 et ses RFC
Tout sur PHP 7.3 et ses RFCTout sur PHP 7.3 et ses RFC
Tout sur PHP 7.3 et ses RFCDamien Seguy
 
Php 7.3 et ses RFC (AFUP Toulouse)
Php 7.3 et ses RFC  (AFUP Toulouse)Php 7.3 et ses RFC  (AFUP Toulouse)
Php 7.3 et ses RFC (AFUP Toulouse)Damien Seguy
 
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009Coat::Persistent at FPW2009
Coat::Persistent at FPW2009Alexis Sukrieh
 
Retour d'expérience technique Go, gRPC, Kubernetes
Retour d'expérience technique Go, gRPC, KubernetesRetour d'expérience technique Go, gRPC, Kubernetes
Retour d'expérience technique Go, gRPC, KubernetesVincent Composieux
 
Hands on lab Elasticsearch
Hands on lab ElasticsearchHands on lab Elasticsearch
Hands on lab ElasticsearchDavid Pilato
 
SSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQLSSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQLHervé Leclerc
 
Partie1 TypeScript
Partie1 TypeScriptPartie1 TypeScript
Partie1 TypeScriptHabib Ayad
 
201303 - Java8
201303 - Java8201303 - Java8
201303 - Java8lyonjug
 
Programmation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationProgrammation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationECAM Brussels Engineering School
 
Cours de C++ / Tronc commun deuxième année ISIMA
Cours de C++ / Tronc commun deuxième année ISIMACours de C++ / Tronc commun deuxième année ISIMA
Cours de C++ / Tronc commun deuxième année ISIMALoic Yon
 
Softshake 2013 Apiness SA l'envers du décor
Softshake 2013 Apiness SA l'envers du décorSoftshake 2013 Apiness SA l'envers du décor
Softshake 2013 Apiness SA l'envers du décormichaelmiguel2013
 
Softshake apiness l'envers du décor
Softshake apiness l'envers du décorSoftshake apiness l'envers du décor
Softshake apiness l'envers du décorApinessSA
 
Android Optimisations Greendroid
Android Optimisations GreendroidAndroid Optimisations Greendroid
Android Optimisations GreendroidGDG Nantes
 

Similaire à Records and Tuples, proposition pour JavaScript (20)

Future of java script web version
Future of java script web versionFuture of java script web version
Future of java script web version
 
Tout sur PHP 7.3 et ses RFC
Tout sur PHP 7.3 et ses RFCTout sur PHP 7.3 et ses RFC
Tout sur PHP 7.3 et ses RFC
 
Php 7.3 et ses RFC (AFUP Toulouse)
Php 7.3 et ses RFC  (AFUP Toulouse)Php 7.3 et ses RFC  (AFUP Toulouse)
Php 7.3 et ses RFC (AFUP Toulouse)
 
Coat::Persistent at FPW2009
Coat::Persistent at FPW2009Coat::Persistent at FPW2009
Coat::Persistent at FPW2009
 
Retour d'expérience technique Go, gRPC, Kubernetes
Retour d'expérience technique Go, gRPC, KubernetesRetour d'expérience technique Go, gRPC, Kubernetes
Retour d'expérience technique Go, gRPC, Kubernetes
 
Hands on lab Elasticsearch
Hands on lab ElasticsearchHands on lab Elasticsearch
Hands on lab Elasticsearch
 
SSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQLSSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQL
 
Partie1 TypeScript
Partie1 TypeScriptPartie1 TypeScript
Partie1 TypeScript
 
Paris RailsCamp 2009
Paris RailsCamp 2009Paris RailsCamp 2009
Paris RailsCamp 2009
 
201303 - Java8
201303 - Java8201303 - Java8
201303 - Java8
 
Programmation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationProgrammation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulation
 
Android ORMLite
Android   ORMLiteAndroid   ORMLite
Android ORMLite
 
Salesforce Tooling API
Salesforce Tooling APISalesforce Tooling API
Salesforce Tooling API
 
C# 7 - Nouveautés
C# 7 - NouveautésC# 7 - Nouveautés
C# 7 - Nouveautés
 
Cours de C++ / Tronc commun deuxième année ISIMA
Cours de C++ / Tronc commun deuxième année ISIMACours de C++ / Tronc commun deuxième année ISIMA
Cours de C++ / Tronc commun deuxième année ISIMA
 
Cours Ynov JS B1_1
Cours Ynov JS B1_1Cours Ynov JS B1_1
Cours Ynov JS B1_1
 
Softshake 2013 Apiness SA l'envers du décor
Softshake 2013 Apiness SA l'envers du décorSoftshake 2013 Apiness SA l'envers du décor
Softshake 2013 Apiness SA l'envers du décor
 
Softshake apiness l'envers du décor
Softshake apiness l'envers du décorSoftshake apiness l'envers du décor
Softshake apiness l'envers du décor
 
Android Optimisations Greendroid
Android Optimisations GreendroidAndroid Optimisations Greendroid
Android Optimisations Greendroid
 
Spring 3.0
Spring 3.0Spring 3.0
Spring 3.0
 

Records and Tuples, proposition pour JavaScript

  • 1. Records & Tuples Bien plus que l'immuabilité 1 @sebastienlorber
  • 2. Sébastien Lorber • Twitter: @sebastienlorber • Blog: sebastienlorber.com • 2014: CTO, dev React / Scala • 2017: expert React freelance • 2020: open-source lead dev Facebook / Docusaurus 2 @sebastienlorber
  • 3. • React Hebdo: sebastienlorber.com/newsletter • Chat React Hebdo: sebastienlorber.com/chat 3 @sebastienlorber
  • 4. Records & Tuples • Proposition comité TC 39 • Stage 2 • Structures immuables en JavaScript • Comportement primitive composée: sous-évalué 4 @sebastienlorber
  • 5. Records & Tuples 101 Les bases 5 @sebastienlorber
  • 6. Record: sorte d'objet immuable const record = #{a: 1, b: 2}; console.log(record); // #{a: 1, b: 2} console.log(record.a); // 1 record.b = 3; // throws TypeError const recordUpdated = #{...record, b: 3} console.log(recordUpdated); // #{a: 1, b: 3} 6 @sebastienlorber
  • 7. Tuple: sorte de tableau immuable const tuple = #[1, 5, 2, 3, 4]; console.log(tuple); // #[1, 5, 2, 3, 4] console.log(tuple[1]); // 5 tuple[1] = 3; // throws TypeError console.log(tuple.filter(num => num > 2)) // #[5, 3, 4]; const tupleUpdated = #[...record, 7] console.log(recordUpdated); // #[1, 5, 2, 3, 4, 7] 7 @sebastienlorber
  • 8. Syntaxe: # = raccourci const record1 = #{a: 1, b: 2}; const record2 = Record({a: 1, b: 2}); const record3 = Record.fromEntries([#["a", 1], #["b", 2]]); const tuple1 = #[1, 5, 2, 3, 4]; const tuple2 = Tuple(1, 5, 2, 3, 4); const tuple3 = Tuple.from([1, 5, 2, 3, 4]); 8 @sebastienlorber
  • 9. Imbrication: comme objets / tableaux const data = #{ a: 1, b: #[ 3, 4, #{c: "hello"} ], }; 9 @sebastienlorber
  • 10. Types non primitifs: interdits const record1 = #{ a: {regular: 'object'}, }; // throws TypeError, un objet n'est pas une primitive const record2 = #{ b: new Date(), }; // throws TypeError, Date n'est pas une primitive const record3 = #{ c: new MyClass(), }; // throws TypeError, MyClass n'est pas une primitive const record4 = #{ d: function () { alert('forbidden'); }, }; // throws TypeError, une fonction n'est pas une primitive 10 @sebastienlorber
  • 11. Types primitifs: autorisés • string, number, boolean, bigint, symbol • undefined, null • Record, Tuple 11 @sebastienlorber
  • 12. Identité des objets/tableaux: const object1 = {a: 1, b: [3, 4]}; const object2 = {a: 1, b: [3, 4]}; console.log(object1 === object2); // false console.log(object1.a === object2.a); // true console.log(object1.b === object2.b); // false 12 @sebastienlorber
  • 13. Identité des records/tuples: primitives composées !!! const record1 = #{a: 1, b: #[3, 4]}; const record2 = #{a: 1, b: #[3, 4]}; console.log(record1 === record2); // true !!! console.log(record1.a === record2.a); // true (normal) console.log(record1.b === record2.b); // true !!! 13 @sebastienlorber
  • 14. Intéropérabilité: • très bonne avec JSON (types primitifs) • correcte avec objects/tableaux const record = JSON.parseImmutable('{a: 1, b: [2, 3]}'); // #{a: 1, b: #[2, 3]} JSON.stringify(record); // '{a: 1, b: [2, 3]}' const record2 = Record({ a: 1, b: Tuple(2, 3) }); // #{a: 1, b: #[2, 3]} const record3 = Record({ a: 1, b: new Date()}); // throws TypeError, Date n'est pas une primitive 14 @sebastienlorber
  • 15. Updates immuables: toujours besoin de Lodash.set, ImmerJS... const state = #{ user: #{ firstName: "Sebastien", lastName: "Lorber" age: 34, } company: #{ name: "Lambda Scale", } }; const updatedState = #{ ...state, user: #{ ...state.user, age: state.user.age + 1, }, company: #{ ...state.company, name: 'Freelance', }, }; 15 @sebastienlorber
  • 16. Updates immuables v2: proposition deep-path-properties-for-record const state = #{ user: #{ firstName: "Sebastien", lastName: "Lorber" age: 34, } company: #{ name: "Lambda Scale", } }; const updatedState = #{ ...state, user.age: state.user.age + 1, company.name: 'Freelance', }; 16 @sebastienlorber
  • 17. Records & Tuples pour React Plusieurs intérêts: • Sécurité • Comportement • Performance • Surface API explicite 17 @sebastienlorber
  • 18. Sécurité: impossible de modifier les props ou le state const Hello = ({ profile }) => { profile.name = 'Sebastien updated'; // throws TypeError return <p>Hello {profile.name}</p>; }; function App() { const [profile, setProfile] = React.useState(Record({name: 'Sebastien'})); profile.name = 'Sebastien updated'; // throws TypeError return <Hello profile={profile} />; } 18 @sebastienlorber
  • 19. Comportement: moins de ré-execution de useEffect function UserAndCompanyPage() { const [data, setData] = useState(null); const apiFilters = Record({ userFilter, companyFilter }); useEffect(() => { fetchUserAndCompanyData(apiFilters).then(setData); }, [apiFilters]); return <div>...</div>; } Empêche les boucles infinies 19 @sebastienlorber
  • 20. Performance: React.memo plus efficace, useMemo "automatique" const UserAndCompanyView = React.memo(({userAndCompany}) { return <div>...</div>; } const App = () => { const user = useUser(); const company = useCompany(); const userAndCompany = Record({user, company}) return <UserAndCompanyView userAndCompany={userAndCompany} /> } 20 @sebastienlorber
  • 21. API surface: • explicite grâce à TypeScript • exprimer le besoin d'identités stable type User = ImmutableRecord<{id: string, firstName: string, lastName: string}> type Company = ImmutableRecord<{id: string, name: string}> type MyComponentProps = { userAndCompany: ImmutableRecord<{ user: User, company: Company, }> } 21 @sebastienlorber
  • 22. DemoCas vie réelle: refetch api backend periodique Code 22 @sebastienlorber
  • 23. Records & Tuples: tradeoffs • Compléxifie JavaScript • Stockage de types non primitifs: références • Détails d'implémentation non spécifiés • Benchmarks à venir • Record TypeScript: conflict 23 @sebastienlorber
  • 24. Conclusion • Facile à prendre en main • Immuabilité: cool • Primitive composée: impact significatif 24 @sebastienlorber
  • 25. Merci Des questions ? • Twitter: @sebastienlorber • Email: lorber.sebastien@gmail.com Resources: • sebastienlorber.com/records-and-tuples-for-react • 2ality.com/2020/05/records-tuples-first-look.html • github.com/tc39/proposal-record-tuple 25 @sebastienlorber