SlideShare une entreprise Scribd logo
1  sur  40
Télécharger pour lire hors ligne
D E S L E G O S A U X
C O M P O S A N T S W E B
F R A N Ç O I S Z A N I N O T T O - M A R M E L A B - B L E N D W E B M I X 2 0 1 8
Bonjour à tous, c’est un grand plaisir pour moi de venir pour la troisième fois à
BlendWebMix. Je suis François Zaninotto, je dirige une entreprise qui s’appelle
marmelab, et j’ai une confession à vous faire.
I L E G O S
J’adore les legos. Pour moi, c’est la plus grande invention du 20è siècle, devant :

- les antibiotiques,

- le transistor,

- le walkman, et

- le minitel.
En plus c’est une invention super simple : des picots ronds séparés de 8 mm en
haut, une base creuse pour enficher les picots, un plastique dur et lisse. C'est tout.
Et pourtant, il a fallu pas mal de temps à son inventeur pour arriver autant de
simplicité.
Son inventeur, c’est lui: Ole Kirk Christiansen, un charpentier danois. Il n’a pas l’air
sur cette photo, mais c’était un sacré déconneur. En 1932, Ole crée les premiers
legos… en bois. Ce n’était pas un très bon choix, parce que ses pièces ne tenaient
pas bien longtemps. C’est l'invention des matières plastiques dures qui va
révolutionner le concept, et faire que les Legos deviennent vraiment faciles à
emboiter. C'était en 1958. 1932-1958, Il lui aura donc fallu 25 ans pour affiner le
concept. 25 ans. Comme quoi, une idée simple ça peut prendre du temps.
Dans ma famille, on est tous des fans de legos. Voici ma fille Nina avec une
maquette du Flatiron Building à New York, 471 pièces, 2h30 de montage.
Voici mon fils Samuel avec le chasseur tie qu’il a construit, 355 pièces, 1h30 de
montage.
Le petit dernier, Sacha, qui met déjà les mains dedans, 3 pièces, 3 minutes de
montage.
Et ça, c’est moi, avec ma dernière création. Je l’ai appelée Revolution 9. Un projet
ambitieux, spectaculaire. 63 pièces. 3 jours de montage. J’espère le proposer
bientôt au Centre Pompidou à Montauban.
Pour tout vous dire, je suis ce qu'on appelle un AFOL, un Adult Fan Of Lego. [clic]
Des AFOL, il y en a beaucoup. Il y en a peut-être dans cette salle. Votre voisin,
votre voisine, regardez-le bien. C'est peut-être aussi un AFOL. La preuve que c’est
un phénomène de société, c’est qu’il y a des émissions de télé dessus.

Les AFOL sont souvent des inventeurs, des bâtisseurs, ils assemblent des briques
sans plan, sans boite, guidés par leur seule imagination.
Vous ne trouverez pas de boite ou de plan pour ces assemblages, ils sont uniques.
Ils sont nés dans l’imagination de leurs créateurs
ils peuvent nécessiter un travail considérable, et certains montages sont tellement
remarquables…
… qu’ils s’exposent dans des musées, comme cet assemblage de Nathan
Sawaya, exposé cet été au Parc de la Villette à Paris. Tout ça pour vous dire que
les legos ce n’est pas que pour les enfants…
…c’est aussi pour les adultes.
Alors, si vous êtes dans cette salle, c’est probablement parce que vous préférez
jouer avec des ordis plutôt qu’avec des legos. Mais l’idée simple des legos, on la
retrouve aussi dans certains jeux vidéos. Le plus proche, évidemment, c’est
Minecraft. Il y a sans doute dans cette salle des AFOM, des Adultes Fans of
Minecraft. Levez la main pour voir ?
Le principe de Minecraft est encore plus radical que celui des legos, puisqu’il n’y a
qu’une taille de bloc, mais il présente un avantage considérable, c'est qu'on peut
collaborer par centaines sur une même création, et travailler en 3x8. Donc ça
donne des créations encore plus grandioses qu'en Lego, comme cette recréation
de l’univers de Harry Potter qui fourmille de détails.
Bref, avec des petits composants standardisés, qui offrent une intéropérabilité
simple, on peut tout construire. La maitrise des composants fait de nous des
maitres bâtisseurs, en quelque sorte, des dieux. En Lego comme en Minecraft. Et
ça, c’est vraiment génial.
Il y a juste un problème. Avec les legos, construire des ensembles très complexes,
c’est très très long, aussi long que bâtir une cathédrale. Comme on ne manipule
que des briques élémentaires, ça prend des plombes. Même en Minecraft c’est
lourd: les mods de construction disponibles permettent de façonner des terrains et
de faire du copier coller de structures, mais une grosse partie de l’assemblage se
fait quand même bloc par bloc.
Je vous donne un exemple concret : Un des derniers assemblages de mon fils est
la Cabane du Pêcheur, un ensemble de plus de 2000 pièces. Samuel a mis 10
heures à la monter. 10 heures d'affilée, et il n'a que 8 ans. La dernière fois qu'il a
passé 10 heures d'affilée concentré sur quelque chose, c'était pour sortir du ventre
de ma femme. C’est vous dire si c’était un effort considérable.
Et puis cet ensemble, qui est au bureau pour que les enfants du personnel
puissent y jouer quand un des collaborateur n'a pas de solution de garde,
commence à nécessiter des réparations. Un bout de toit est parti, la rambarde a
perdu un barreau. On a bizarrement des pièces en trop, et la réparation s’avère…
compliquée.
Il faut retrouver, dans le manuel de 252 pages, l'étape où on construit cette partie,
identifier les pièces, les commander sur le site Lego.com, démonter la rambarde,
la remonter avec la nouvelle pièce, et la remettre.
Macro Components
Pour moi, vous voyez, monter la cabane du pêcheur, c’était drôle la première fois
avec mon fils, mais pas au point de le refaire. En bon informaticien, je me dis que
si je fais la même chose deux fois, c’est un peu un constat d’échec. Je suis plutôt
un adepte du copier collé, vous voyez ? Du coup, pour réparer la cabane du
pêcheur, j’aimerais bien pouvoir commander des blocs entiers plutôt que des
pièces à l’unité. Un toit, une tour. Appelons-ça des macro-composants.
J’ai cherché, eh bien figurez-vous que personne ne vend ça. On ne trouve que des
boites de pièces non assemblées, ou bien des maquettes complètes. Il semble
que personne n’ai jamais eu besoin d’acheter des macro composants. C’est peut-
être qu’il n’y a pas assez d’informaticiens qui jouent aux legos. Ou peut-être que je
ne suis pas un vrai AFOL.
AFOLA D U LT FA N O F L E G O
FAKE
Un vrai AFOL n’hésiterait jamais à tout détruire pour remonter un ensemble à
nouveau brique par brique. Ca fait de moi un faux AFOL. Mais avant de vous
moquer de moi, mettez-vous à ma place. Si votre métier, c’était de construire des
grands ensembles à partir de toutes petites briques, ça vous ennuierait sans doute
assez vite, non ?
Eh mais attendez, je dis ça, mais en fait votre métier c’est exactement la même
chose ! Vous construisez des applis web complexes en assemblant de touts petits
blocs - les éléments HTML. Et les éléments HTML, ce sont des composants tout
comme les briques de Lego.
Et grâce à HMTL, vous pouvez construire toutes sortes de choses merveilleuses,
comme cette page d’accueil de la Pizzeria Ostorea 3, qui est un assemblage
savant d’éléments H1, DIV, IMG… et MARQUEE.
Mais dès qu’on essaie de construire de grosses applications dotées d’une logique
métier importante avec de touts petits éléments HTML, on se retrouve avec le
même problème qu’avec les legos. Ca prend beaucoup de temps, et du coup, ça
coute cher. Très cher .L’interface que je vous montre ici a été achetée par
Microsoft pour 26 milliards de dollars. C’est vraiment un très cher assemblage
d’éléments HTML, et à mon avis ça prouve qu’il y a un problème.

En bon informaticien, si on me demandait de construire cette page, j’aimerais bien
assembler des gros ensembles plutôt que des petites balises HTML, comme en
legos. Mais alors, qu’est-ce qui correspond à un mur, un toit, ou une rambarde sur
topbar
profile
main
recommend
ations
On peut imaginer un macro-composant pour la barre de navigation, un autre pour
le profil, un pour le contenu principal, et encore un pour les recommandations. Ces
macro-composants eux-mêmes pourraient être découpés en plus petits macro-
composants,
topbar
profile
main
recommend
ations
bio
stats
postform
updates
search navigation
comme un moteur de recherche, un menu de navigation, une bio, etc. Et on peut
continuer à découper pour arriver à des composants assez élémentaires. Et si
chacun de ces composants avait une représentation HTML,
<homepage>
<topbar>
<logo />
<search />
<navigation>
<avatar src="./fzaninotto.jpg" />
</navigation>
</topbar>
<advertisement />
<div style="display:flex">
<profile userId="45758" style="width:200px">
<bio />
<stats>
</profile>
<main style="flex:auto">
<postform/>
<updates sortBy="date">
<post authorId="23525">
I see less and less value

in using LinkedIn, too superficial
</post>
</updates>
</main>
<recommendations style="width:300px" />
</div>
</homepage>
On pourrait les assembler avec d’autres éléments HTML… Imaginez des
composants « métier », comme <navigation>, <profile>, <recommendations>, avec
chacun des propriétés liées à leur contenu, leur style et leur comportement. Ca
serait ce qu’on appelle un DSL, un Domain Specific Language. Si on avait des
macro-composants comme ça, créer des applis web irait beaucoup, beaucoup
plus vite, non ?
Ces macro-composants, s’ils existaient, il simplifient tellement le développement
de sites web qu’on pourrait confier le travail non pas à des développeurs, qui
sentent fort et qui ont la barbe mal taillée, mais à des intégrateurs, qui en général
sont mieux de leur personne, et en plus bien moins chers. D’où un double bénéfice
financier et olfactif.

<SubscribeButton onClick={subscribe} icon="mail">
Subscribe to the newsletter
</SubscribeButton>
<a role="button" class="btn" id="1234">
<img src="/path/to/email.png" />
Subscribe to the newsletter
</a>
<style>
.btn {
padding: 8px;
color: #3f51b5;
border-radius: 4px;
text-transform: uppercase;
vertical-align: middle;
text-decoration: none;
}
.btn:hover {
background-color: rgba(63, 81, 181, 0.08);
}
.btn img {
padding-right: 5px;
}
</style>
<script>
document
.getElementById("1234")
.onClick(subscribe);
</script>
Alors, à quoi ça ressemblerait un macro-composant ? Imaginez un composant non
standard, comme ici SubscribeButton, qui utilisé dans un document HTML, se
transformerait d’un coup de baguette magique en un ensemble complexe de
composants élémentaires - une balise <a>, une balise <img>, une balise <style>,
une balise <script>. 

Ca ressemble à du templating, mais en fait c’est plus que ça, puisqu’il faut que
ces macro-composants métiers soient composables avec les éléments du HTML.
Web Components Polymer.js
Eh bien figurez-vous que d’autres personnes ont eu la même idée. Le standard
HTML contient une spécification qui s’appelle les Web Components, et ça
ressemble beaucoup à ce que je viens de vous montrer. Malheureusement les Web
Components ne sont bien supportés que sur Chrome. Et puis l’API des web
components est super lourde, au point qu’elle est inutilisable sans une surcouche.
Polymer.js est justement une surcouche open-source qui rend les Web
Components utilisables.
React.js Vue.js Angular
Alors pour une plus grande compatibilité, il faut se tourner vers aussi des
implémentations en JavaScript pur de moteurs de composants, comme les
frameworks open-source React, Vue et Angular.
Notez que je ne mentionne pas jQuery - eh oui, le papi des frameworks JS ne
permet pas de faire des composants. Si vous l’utilisez, il va falloir songer à le
mettre à la retraite.
HTML in JS JS in HTML
<template>
<div class="field">
<label class="label">Employer</label>
<div class="control">
<input
class="input"
type="text"
v-model="employer"
/>
</div>
</div>
</template>
<script>
export default {
data() {
return {
employer: "Marmelab"
};
},
};
</script>
import React, { Component } from 'react';
export default class FormSample extends Component {
state = {
employer: 'Marmelab'
};
handleEmployerChange = e => {
this.setState({ employer: e.target.value });
};
render() {
return (
<div className="field">
<label className="label">Employer</label>
<div className="control">
<input
className="input"
type="text"
onChange={this.handleEmployerChange}
value={this.state.employer}
/>
</div>
</div>
);
}
}
Ce qui distingue React, Vue et Angular, c’est principalement la façon dont ils
entremêlent le HTML et le JavaScript. A gauche, vous avez un exemple de
composant en React, qui met du HTML dans son JS avec une syntaxe spéciale
nommée JSX. A droite, vous voyez un template HTML Vue.js avec des directives
spéciales comme v-model, qui simulent du JavaScript dans le HTML. Y a-t-il une
syntaxe meilleure que l’autre ? Non, c’est une affaire de goût. Chaque approche a
ses avantages et ses inconvénients. Et de toutes façons, mêler deux langages,
c’est toujours bizarre, mais c’est obligatoire pour faire du templating.
R E A C T. J S V U E . J S A N G U L A R
L I F E C Y C L E M E T H O D S
✓ ✓ ✓
L O C A L S TAT E
✓ ✓ ✓
O N E - WAY D ATA B I N D I N G
✓ ✓ ✓
FA S T I N P R O D U C T I O N
✓ ✓ ✓
L A R G E U S E R B A S E
✓ ✓ ✓
G R E AT D O C U M E N TAT I O N
✓ ✓ ✓
E V E N T S H A N D L I N G
✓ ✓ ✓
I D E I N T E G R AT I O N
✓ ✓ ✓
E S 6 S U P P O R T
✓ ✓ ✓
T Y P E S C R I P T S U P P O R T
✓ ✓ ✓
U N I T T E S TA B L E
✓ ✓ ✓
Et puis ces librairies ont vraiment beaucoup en commun. Alors évidemment elles
ont des différences, chacune va briller un peu plus que l’autre dans certaines
situations. Mais globalement elles sont toutes très bonnes, et vous ne ferez pas un
mauvais choix en prenant l’une ou l’autre.
Malheureusement, vous rencontrerez beaucoup gens très dogmatiques qui
prétendent que telle librairie est la seule bonne, et qui sont prêts à en découdre si
vous dites le contraire. Pour moi, la librairie que vous choisirez importe moins que
le fait d’utiliser une approche par composants, et c’est là-dessus que je vais
insister.

Bon, pour la suite de cette présentation, j’utiliserai React, qui est la librairie que je
maîtrise le mieux, mais tout ce que je vais vous dire est aussi valable pour Polymer,
Vue, et Angular.

Donc je résume, toutes ces librairies sont bonnes, mais React est la meilleure.
<SubscribeButton onClick={subscribe} icon="mail">
Subscribe to the newsletter
</SubscribeButton>
const styles = {
button: {
padding: 8,
color: '#3f51b5',
borderRadius: 4,
textTransform: 'uppercase',
verticalAlign: 'middle',
textDecoration: 'none',
},
icon: {
paddingRight: 5,
},
};
const SubscribeButton = ({ onClick, icon, children }) => (
<a role="button" style={styles.button} onClick={onClick}>
<img src={`/path/to/${icon}.png`} style={styles.icon} />
{children}
</a>
);
export default StyledButton;
Definition
Usage
Un framework de composants comme React.js fournit le mécanisme pour
assembler des éléments HTML et publier des composants plus gros. Vous voyez
ici comment React permet de créer le composant SubscribeButton de tout à
l’heure. Donc, le problème est réglé ? 

Oui mais non. En fait, ça ne répond pas à mon besoin. Souvenez-vous, moi je ne
veux pas un système pour assembler des briques élémentaires - j’ai déjà mon fils
pour ça. Ce que je cherche, ce sont des gros composants tout faits. Il n’y a que
comme ça que mon développement web pourra se faire à une vitesse
supportable.
Figurez-vous que d’autres personnes ont eu la même idée. Il existe pléthore de
bibliothèques de composants React pour faire des boutons, des onglets, des
barres de navigation, des fils d’ariane. En plus, elles ont le bon goût de ne pas
réinventer le design, elles se basent sur des styles éprouvés comme Bootstrap,
Material design ou Semantic UI. Voici par exemple une librairie qui s’appelle
semantic ui react, et qui propose des jolis boutons stylés à la semantic ui.
Voici une autre librairie, react-bootstrap, qui propose des jolis boutons stylés à la
Bootstrap.
Voici enfin une librairie qui s’appelle material-ui, et qui propose des jolis boutons
stylés à la Material Design.

(…)

En fait, je vous avoue que je suis un peu dubitatif. C’est sûr, ces bibliothèques sont
très utiles. Elles me permettent de gagner du temps pour arriver à un résultat joli.
Mais je devrai quand même assembler de petits composants. En fait, ces
bibliothèques proposent juste des versions plus jolies des éléments de base du
HTML, comme l’élément button.
Pour moi, ces bibliothèques de composants sont un peu comme les boites de
legos issues d’une licence, comme Lego Star Wars. Je les vois comme des boites
de pièces plus stylées, mais les pièces ne sont toujours pas assemblées. Et à
nouveau, si je dois faire des Faucons Milleniums toute la journée, ça va me soûler
d’assembler autant de pièces qu’un y a de boutons sur le visage de Mark Hamill -
c’est à dire, excusez du peu, 1414.

Et puis je vais vous citer un autre défaut de ces boites de lego jolis : elles ne
servent à rien. C’est vrai. Je ne peux pas trouver du travail avec, je ne peux pas
appeler ma tante avec, je ne peux pas trouver l’âme soeur avec. Je ne peux faire
qu’une maquette, à la rigueur pour la mettre sur mon étagère. Et pourquoi ces
ensembles ne servent à rien ? Parce qu’ils sont statiques.
De la même façon, une page web construite en assemblant des composants stylés
sera elle aussi statique. Alors oui, elle sera plus jolie que la page de la pizzeria, de
tout à l’heure, mais ca restera une page. Or, ce que demandent nos clients
aujourd’hui, ce ne sont pas des pages web, mais des applications web, qui leur
permettent de réaliser des tâches complexes comme trouver du travail, appeler
leur tante ou trouver l’âme soeur.
Alors, vous allez me dire: Et Lego Technics ? Et Lego Mindstorms? C’est vrai. Dans
le monde des legos, il existe des composants qui permettent d’animer les
maquettes. Des contrôleurs, des chaines de transmission, des engrenages. Et
avec ces pièces là, les amateurs fabriquent des assemblages qui servent
effectivement à quelque chose, comme cette machine à poser des ponts en legos.
Vous avouerez qu’avec de tels montages, on a dépassé le stade de la maquette, et
on peut commencer à imaginer gagner sa vie avec des legos. La question que je
me pose en voyant ça, c’est : et pour nous les développeurs web, quand on utilise
un framework de composants, c’est quoi l’équivalent de ces pièces dynamiques ?
U S A G E L I B R A RY
Routing React-Router
State Redux, Mobx
Api Fetching Fetch, Apollo, Urql
Form Handling Redux-Form
Side Effects Saga, Redux-Observables
I18N I18Next, React-Intl
Transitions React-Transition-Group
Ce sont des librairies spécialisées dans la gestion du routing, des formulaires ou
de l’internationalisation. Une tuyauterie sophistiquée qui permet de gérer des
interactions complexes avec les utilisateurs. Le plus beau est que ces mécanismes
sont fournis sous la forme de composants, qui sont faciles à assembler avec des
composants stylés.
Macro Components
=
React
+ React UI Kit
+ State management
+ Side effects management
+ Form management
Cela me permet d’affiner la définition d’un macro-composant : c’est donc un
composant qui sera dynamique et par défaut joli. Il devra s’appuyer à la fois sur
des UI Kits et sur la quincaillerie dont je viens de parler. Si quelqu’un faisait ce
genre de composants, ça accélèrerait vraiment le développement.
Figurez-vous que d’autres personnes ont eu la même idée. Mais pas beaucoup.
On trouve quelques macro-composants dynamiques en React, comme ici React
Table, qui fournit les fonctionnalités d’une table de données avec tri, filtrage, et
pagination.

Le souci, c’est que l’écosystème React est encore trop jeune. Il n’y a pas de
consensus sur la bonne façon de gérer l’état, ou les transitions, ou le look and feel.
Du coup, si on trouve des macro-composants individuels (pour faire une datagrid,
un menu hamburger, ou une select box), leurs APIs diffèrent, et il faut pas mal de
travail pour les faire communiquer.
A L I B R A RY O F
M A C R O C O M P O N E N T S
Donc en fait, le saint graal, ce n’est pas un macro-composant, c’est un ensemble
cohérent de macro-composants, conçus pour être utilisés les uns avec les autres.

Est-ce que quelqu’un a déjà eu cette idée ?
Eh bien, j’ai cherché, et je n’ai pas trouvé. C’est un peu normal, si le graal était si
facile à trouver, on serait tous immortels. Et si les hommes étaient immortels, le
monde aurait d’autres problèmes à gérer que faire des sites web, comme par
exemple :
à quoi sert la prison puisqu’en étant immortel, on en sortira toujours vivant, ou
encore
pourquoi interdire les drogues puisqu’on n’en mourra pas, ou enfin
quand est-ce qu’on touche sa retraite quand on est immortel ? Mais je m’égare.
Ces problèmes ne se posent pas encore, also revenons à un problème actuel :
pourquoi ça n’existe pas, une bibliothèque de macro-composants ?
topbar
profile
main
recommend
ations
A bien y réfléchir, c’est un peu normal que ça n’existe pas. C’est que ces macro-
composants répondent à un besoin complexe, donc spécifique. Qui d’autre que
LinkedIn pourrait utiliser une bibliothèque avec des macro-composants Profil ou
Recommandations ?
<connection>
<skills>
<company>
<trip>
<driver>
<car>
<restaurant>
<menu>
<opening-time>
<coloscopy>
<suppository>
<treatment-form>
Si vous-mêmes créez des macro-composants, vous le ferez pour le domaine sur
lequel vous travaillez. Vous voyez ici le genre de composants que pourraient
développer les équipes de LinkedIn, BlablaCar, La Fourchette, ou Doctissimo. On
voit que certains on plus de chance que d’autres.

Mais surtout, vous voyez que ces composants ne sont pas réutilisable dans un
autre contexte. Un restaurant chez votre toubib ? Des horaires d’ouvertures pour
un contact sur LinkedIn ?
Une coloscopie dans un restaurant ? Mais bien sûr madame, vous la voulez à
rosée ou à point ?
A moins que… Il existe un domaine, un domaine spécifique, mais somme toute
très commun. C’est le domaine des back-offices, que j’appellerai des admins
parce que ça évite la confusion avec le terme « backend », qui désigne autre
chose, et avec le terme « backroom », qui désigne… encore autre chose.
Rassurez-vous, je n’ai pas d’image pour illustrer ce terme.

Vous voyez, LinkedIn, LaFourchette, BlablaCar et Doctolib ont tous besoin d’une
interface pour les administrateurs, ces super-utilisateurs qui doivent avoir accès à
toutes les données, en lecture et en écriture. L’interface d’admin, tous les projets
sur lesquels j’ai travaillé ces 10 dernières années en avaient besoin d’une.
Dans sa plus simple expression, une admin c’est une interface crud devant une
base de données - à la phpMyAdmin. Sauf que si vous mettez ça dans les mains
d’un opérationnel, c’est très vite la catastrophe - j’ai l’impression que c’est déjà
arrivé à certains d’entre vous. En général, les entreprises développent leur propre
admin sur mesure. Les plus riches appellent ça un ERP, mais le principe est le
même. Donc les administrations, voilà un besoin suffisamment générique pour
créer des macro-composants qui auront une chance d’être réutilisés souvent.
marmelab/react-admin
A specialised admin framework for React
React

+ material-ui

+ redux

+ redux-form

+ saga

+ reselect
Il n’y avait pas de bibliothèque de macro-composants pour faire des
administration, alors on l’a fait. Ma société développe depuis plus de 2 ans une
librairie open-source qui s’appelle React-admin, et qui est exactement le saint
graal dont je vous ai parlé depuis tout à l’heure. Pour que vous compreniez ce dont
il s’agit, en voici une démo rapide.
React-admin a permis de créer cette appli web, qui est l’administration d’une
boutique de posters fictive. Le propriétaire de cette boutique peut y gérer ses
clients, faire des statistiques sur leurs visites, gérer son catalogue de posters, il
peut rechercher une commandes avec une recherche multi-critères et la marquer
comme expédiée, il peut même aller jusqu’à modérer des commentaires. C’est un
bon cas d’école pour un framework d’admin générique, et vous voyez ici comment
react-admin s’en tire.
Avec plus de 5,000 stars sur Github, react-admin est un projet déjà assez
populaire pour que les conseils que je vais énoncer aujourd’hui s’appliquent à
d’autres. Parce que, en concevant une bibliothèque de macro-composants
d’administration, on a découvert des pratiques pas forcément intuitives, mais qui
sont cruciales pour bien réussir ses propres macro-composants.
Ces secrets de fabrication, c’est un peu comme ce qu’a découvert Ole Kirk
Christiansen après 25 ans d’expérimentation. Sauf qu’avec la technologie
moderne, on n’a mis que 2 ans à découvrir ce qui fait que des macro-composants
s’assemblent, ce qui fait qu’ils tiennent ensemble, ce qui fait qu’ils vibrent
ensemble, et pour tout dire, ce qui fait qu’on les aime.
Je réalise que ma dernière phrase serait une super introduction pour une émission
télé-réalité du genre « le Bachelor La finale: Marco va-t-il choisir Naëlle la belle
rousse ou Mimi la petite blonde ? La révélation, c’est juste après la pub. ». J’ai
peut-être raté ma vocation après tout.
7 T E C H N I Q U E S P O U R R É U S S I R
S E S M A C R O - C O M P O S A N T S
1. Divisez pour mieux régner
2. Pour étendre, décorez !
3. Laissez vos enfants tranquilles
4. Ayez le don de double vue
5. Cultivez l’isolation
6. Explusez les effets de bord
7. Mettez du style dans votre comportement
Bref, je vais à présent vous révéler les leçons qu’on a apprises à la dure. 7 conseils
assez techniques, et aux nom mystérieux parce que, en bon fan de Joséphine
Ange Gardien, j’ai le goût du mystère.
et pour tout vous dire c’est la partie de ma présentation pendant laquelle les non-
développeurs peuvent dormir. Installez-vous confortablement, c’est promis, on ne
fera pas trop de bruit.
C O N S E I L # 1
~
D I V I S E Z P O U R M I E U X R É G N E R
Bien. Tout d’abord, divisez le travail pour que chaque composant ne fasse plus
qu’une seule chose - mais bien. Si un composant fait plusieurs choses, découpez-
le en plus petits composants. Je vous donne un exemple.
List
Filters
Datagrid Field
Dans toute admin, il y a des tableaux de données. Ici, vous voyez une liste
d’articles avec pour chacun un titre, une date de publication, un nombre de vues,
un auteur. Mais pour afficher cette page à partir d’un composant de liste
générique, il faut définir un certain nombre d’options, comme par exemple les
filtres, les champs, la pagination, etc.
import React, { Component } from 'react';
import { List } from 'react-admin';
const filterConfig = {
q: { type: 'text', label: 'Search' },
};
const fieldsConfig = {
id: { type: 'text' },
title: { type: 'text' },
publishedAt: { type: 'date', label: 'publishedAt' },
views: { type: 'number' },
authorId: {
type: 'reference',
reference: 'authors',
referenceField: 'lastName'
}
}
const PostList = props => (
<List
resource="posts"
filters={filterConfig}
fields={fieldsConfig}
props={...props}
/>
);
Dans sa première version, le composant de liste de react-admin prenait en
paramètre des objets de configuration pour les filtres et les colonnes à afficher. 

Le problème, c’est que ce macro-composant List, il faisait beaucoup, beaucoup
trop de choses : requêter la route posts pour récupérer les données, afficher les
filtres et gérer leur formulaire, afficher un tableau de données et gérer le tri par
colonnes, afficher les données elles-mêmes en adaptant la mise en forme au type
du champ… Ce macro-composant List comptait facilement plusieurs centaines,
voir plusieurs milliers de lignes de code. C’est trop pour garantir une bonne lisibilité
et une bonne maintenabilité. Quand je parle de macro-composant, pour moi le
En matière de composants, c’est beau quand c’est petit. Et avec react-admin, on a
trouvé un moyen d’éviter que les macro composants aient trop de code.
import React, { Component } from 'react';
import {
List, Datagrid, TextField, DateField,
NumberField, ReferenceField, EditButton
} from 'react-admin';
import PostFilter from './PostFilter';
const PostList = props => (
<List
resource="posts"
display={<Datagrid />}
fields={[
<TextField source="id" />,
<TextField source="title" />,
<DateField source="publishedAt" />,
<NumberField source="views" />,
<ReferenceField source="authorId" reference="author">
<TextField source="lastName" />
</ReferenceField>,
]}
filters={<PostFilter />}
props={...props}
/>
);
Ca consiste à diviser un gros composant en composants élémentaires ayant une
seule responsabilité. 

Voilà comment ça s’est traduit dans le cas de la liste d’articles. Le nouveau
composant List s’occupe de récupérer les données (ici, une liste de publications)
mais pas de les afficher. Il passe les données à un sous-composant display défini
dans ses propriétés, qui a la responsabilité de les afficher. En l’occurrence, ici c’est
un composant Datagrid, qui affiche les données dans une table. Mais ce n’est pas
lui qui s’occupe de savoir quels colonnes afficher dans cette table, ce sont les
composants définis dans la propriété fields. Pareil pour le composant filters, qui a
import React, { Component } from 'react';
import {
List, Datagrid, TextField, DateField,
NumberField, ReferenceField, EditButton
} from 'react-admin';
import PostFilter from './PostFilter';
const PostList = props => (
<List
resource="posts"
filters={<PostFilter />}
props={...props}
>
<Datagrid>
<TextField source="id" />
<TextField source="title" />
<DateField source="publishedAt" />
<NumberField source="views" />
<ReferenceField source="authorId" reference="author">
<TextField source="lastName" />
</ReferenceField>
<EditButton />
</Datagrid>
</List>
);
Et on peut même aller encore un peu plus loin en choisissant une propriété de la
list, ici la propriété display, et la renommer en children. Ca permet d’écrire du code
bien plus lisible.
import React, { Component } from 'react';
import {
List, Datagrid, TextField, DateField,
NumberField, ReferenceField, EditButton
} from 'react-admin';
import PostFilter from './PostFilter';
const PostList = props => (
<List
resource="posts"
filters={<PostFilter />}
props={...props}
>
<Datagrid>
<TextField source="id" />
<TextField source="title" />
<DateField source="publishedAt" />
<NumberField source="views" />
<ReferenceField source="authorId" reference="author">
<TextField source="lastName" />
</ReferenceField>
<EditButton />
</Datagrid>
</List>
);
import React, { Component } from 'react';
import {
List, CardList, TextField, DateField,
NumberField, ReferenceField, EditButton
} from 'react-admin';
import InlinePostFilter from ‘./InlinePostFilter';
import HumanReadableDateField from ‘./Fields';
const PostList = props => (
<List
resource="posts"
filters={<InlinePostFilter />}
props={…props}
>
<CardList>
<TextField source="id" />
<TextField source="title" />
<HumanReadableDateField source="publishedAt" />
<NumberField source="views" />
<ReferenceField source="authorId" reference="author">
<TextField source="lastName" />
</ReferenceField>
<EditButton />
</CardList>
</List>
);
Enorme avantage: je peux échanger chacun de ces composants par un autre. Si
j’ai besoin d’afficher les données dans un autre format qu’une datagrid, je peux
réutiliser toute la logique du composant List, qui est commune, et juste changer
son fils. Je peux fournir ma propre implémentation des filtres, voire créer un type
de champ spécialisé pour afficher les dates sous la forme « il y a tant de jours ».
Comme tout est composant, la modification d’un composant se fait par la
composition avec un autre composant. C’est hyper puissant.
Cette méthode consistant à remplacer un élément par un autre, Staline ne l’aurait
pas reniée. Il était un des précurseurs dans la manipulation d’image, comme ici sur
une photo avec Nikolaï Yejov, retouchée après sa condamnation à mort en 1940.
Mais s’il avait connu les composants, Staline aurait pu aller un cran plus loin et
remplacer Nikolaï par son nouvel ami Brad.
// in charge of fetching the data and handling state
import ListController from './ListController';
// in charge of displaying the list view
import ListView from './ListView';
const List = props => (
<ListController {...props}>
<ListView />
</ListController>
);
export default List;
Je vous ai montré comment remplacer de la configuration par des sous-
composants, mais on pourrait même appliquer la séparation des responsabilités
à chaque composant, en mettant d’un côté la logique de préparation des
données, appelons-la le contrôleur, et de l’autre la logique de présentation,
appelons-la vue. Si ça vous rappelle le pattern MVC, ce n’est pas un hasard.
L’avantage, c’est que chaque composant est testable indépendamment, et que
vous pouvez facilement surcharger la partie présentation sans recopier toute la
partie logique.

Pour séparer la logique de la présentation, le composant parent peut, comme sur
// in charge of fetching the data and handling state
import ListController from './ListController';
// in charge of displaying the list view
import ListView from './ListView';
const List = props => (
<ListController {...props}>
{controllerProps => <ListView {...props, ...controllerProps} />}
</ListController>
);
export default List;
Un autre pattern très à la mode, celui des render props, évite le clonage du
composant fils, en forçant les développeurs à fournir une fonction comme fils et
non un composant. Les deux approches ont leurs bénéfices et inconvénients, et
react-admin utilise les deux. Ca nous notamment permis d’extraire la partie UI, ce
qui rend possible une skin react-admin pour Bootstrap ou Semantic UI.

Ce qu’il faut retenir c’est que plus vous réduirez les responsabilités de chaque
composant, plus votre code sera modulaire et facile à tester. Un bon moyen
mnémotechnique, c’est de se dire que si un composant fait plus de 100 lignes de
code, il est peut-être nécessaire de le découper en un parent et un enfant.

Stanley Kubrick qui, dans Shining, a compris qu’en découpant parents et enfants,
on appliquait au mieux la séparation des responsabilités. Diviser pour mieux
régner, souvenez-vous de cette formule, ou de cette image, elle est bien aussi.
C O N S E I L # 2
~
P O U R E T E N D R E , D É C O R E Z !
Deuxième conseil, qui a l’air tout simple mais qui est étonnamment puissant :
utilisez la décoration pour étendre un composant. J’utilise ici le terme
« décoration » pour parler de wrapper un composant autour d’un autre, et le terme
« étendre » dans le sens de l’héritage. En fait je devrais dire « spécialiser » plutôt
qu’« étendre ». Vous savez, dans l’héritage, on dit que la classe Chien étend la
classe Animal, mais en fait elle la spécialise.

Voilà comment ça s’applique aux composants.
const Input = ({ type, name, value, placeholder }) => (
<div className="form-group">
<label htmlFor={name}>{humanize(name)}</label>
<input
type={type}
id={name}
name={name}
value={value}
className="form-control"
placeholder={placeholder}
/>
</div>
);
const TextInput = props => <Input {...props} type="text" />
const NumberInput = props => <Input {...props} type="number" />
const DateInput = props => <Input {...props} type="date" />
Imaginons que vous avez développé un composant Input pour afficher un champ
de formulaire. Ce composant accepte notamment une propriété type, pour
spécifier le type de champ à afficher.

Eh bien, pour spécialiser ce composant, par exemple pour faire un champ
TextInput ou NumberInput, la bonne pratique consiste à réutiliser le composant
Input initial en le décorant, c’est-à-dire que le composant TextInput va déléguer
sa logique au composant Input, mais en fixer une ou plusieurs propriétés.

La plupart des langages utilisent l’héritage pour implémenter la spécialisation.
Avec un moteur de composants, on utilise plutôt la décoration, qui est une forme
Layout
AppBar
Sidebar
Là où ça devient vraiment intéressant, c’est quand on combine cette décoration
avec le conseil précédent. 

Par exemple, dans react-admin, on a un composant Layout qui affiche les
éléments d’interface courants, comme la barre supérieure ou le menu de
navigation.
const Layout = ({
logo,
title,
userMenuContent,
menuItems,
sidebarWidth,
}) => ( /* ... */ );
const MyLayout = props =>
<Layout
logo={<AcmeLogo />}
title="Acme Admin"
userMenu={<AcmeUser />}
menu={<AcmeMenu />}
sidebarWidth={200}
{...props}
/>;
Definition Usage
Pour configurer ces éléments, au départ le composant Layout exposait des
propriétés comme logo, title, ou menuItems. Tellement de propriétés qu’en fait, ce
composant Layout devenait difficile à utiliser et à maintenir.

const AppBar = ({
logo,
title,
userMenuContent,
}) => ( /* ... */ );
const Sidebar = ({
menuItems,
width,
}) => ( /* ... */ );
const Layout = ({
appBar = <AppBar />,
sidebar = <Sidebar />,
}) => ( /* ... */ );
const MyAppBar = props =>
<AppBar
logo={<AcmeLogo />}
title="Acme Admin"
userMenu={<AcmeUser />}
{...props}
/>;
const MySidebar = props =>
<Layout
menu={<AcmeMenu />}
sidebar={200}
{...props}
/>;
const MyLayout = props =>
<Layout
appBar={<MyAppBar />}
sidebar={<MySidebar />}
{...props}
/>;
Definition Usage
On a appliqué le premier conseil, et décomposé Layout en plus petits composants,
comme AppBar ou Sidebar. Layout utilise à présent ces sous-composants dans
son rendu, et l’utilisateur peut les surcharger via les propriétés de Layout.

Maintenant, si j’utilise la décoration sur ces sous-composants, [clic] ça me permet
de personnaliser le logo en décorant le composant AppBar en MyAppBar, ou de
personnaliser le menu en décorant le composant Sidebar en MySidebar. Il ne me
reste plus qu’à injecter ces deux composants décorés dans le layout, pour obtenir
un composant MyLayout lui aussi décoré.
Ou, pour utiliser une analogie facile, pour décorer un appartement, il faut décorer
chacun des meubles de l’appartement.

La décoration de sous-composants permet de présenter des composants simples,
puissants, testables et configurables.
C O N S E I L # 3
~
L A I S S E Z V O S E N FA N T S
T R A N Q U I L L E S
Ce qui m’amène à mon troisième conseil: un composant ne doit pas regarder ce
que font ses enfants ni décider ce qu’il doit faire en fonction de ses enfants.
C’est une erreur très courante, mais qui crée plein de problèmes. Je vous explique.
const PostList = props => (
<List props={...props} filters={<PostFilter />}>
<Datagrid>
<TextField source="id" />
<TextField source="title" />
<DateField source="publishedAt" />
<NumberField source="views" />
<ReferenceField source="authorId" reference="author">
<TextField source="lastName" />
</ReferenceField>
<EditButton />
</Datagrid>
</List>
);
Revenons à la liste de contenus et à sa Datagrid. Dans cet exemple, comment la
Datagrid va faire pour afficher les en-têtes de colonnes ? Le titre de chaque
colonne vient de la propriété source des enfants de Datagrid, comme id, title, ou
publishedAt.
import { Children, cloneElement } from 'react';
const Datagrid = ({ records, children }) => (
<table>
<thead>
<tr>
{Children.map(children, child =>
<th>{humanize(child.props.source)}</th>
)}
</tr>
</thead>
<tbody>
{records.map(record =>
<tr>
{Children.map(children, child =>
<td>{cloneElement(child, { record })}</td>
)}
</tr>
)}
</tbody>
</table>
);
La première idée qui vient à l’esprit est que le composant Datagrid itère sur tous
ses composants enfants, lise leur propriété source, et l’affiche dans un header. Et
ça marche. Mais…
const TitleField = props =>
<TextField source="title" style={{ color: 'grey' }} />
const PostList = props => (
<List props={...props} filters={<PostFilter />}>
<Datagrid>
<TextField source="id" />
<TitleField />
<DateField source="publishedAt" />
<NumberField source="views" />
<ReferenceField source="authorId" reference="author">
<TextField source="lastName" />
</ReferenceField>
<EditButton />
</Datagrid>
</List>
);
Si l’un des composants fils de Datagrid n’a pas de prop source - par exemple si on
veut le décorer avec un autre composant pour lui donner un style particulier - eh
bien cette approche ne marche plus. En fait, regarder ce que font ses enfants est
une violation de la séparation des responsabilités. C’est le composant field qui
devrait avoir la responsabilité d’afficher le titre ET le contenu d’une colonne, pas la
datagrid. 

Donc il ne faut jamais qu’un composant inspecte ses enfants et prenne des
décisions en fonction de leur nature ou de leurs propriétés. Au contraire, il doit
déléguer le plus possible à ses enfants et les laisser faire.

Vos enfants devront se débrouiller eux-mêmes, et vous ne pourrez pas l’empêcher
- autant s’y habituer tout de suite.

Mais revenons aux composants. Comment un composant peut-il afficher plusieurs
choses différentes, comme une en-tête de colonne et le contenu d’une colonne
dans l’exemple précédent ?
C O N S E I L # 4
~
AY E Z L E D O N
D E D O U B L E V U E
C’est mon quatrième conseil: il faut faire des composants qui savent se rendre
plusieurs fois. C’est un pattern que nous utilisons régulièrement dans react-admin,
et qui consiste à donner à un composant une double responsabilité.
const Datagrid = ({ records, children }) => (
<table>
<thead>
<tr>
{Children.map(children, child =>
<th>{cloneElement(child, { intent: 'header' })}</th>
)}
</tr>
</thead>
<tbody>
{records.map(record =>
<tr>
{Children.map(children, child =>
<td>
{cloneElement(child, { record, intent: 'content' })}
</td>
)}
</tr>
)}
</tbody>
</table>
);
const TextField = ({ intent, record, source }) => {
if (intent == 'header') {
return <span>{humanize(source)}</span>;
}
if (intent == 'content') {
return <span>{record[source]}</span>
}
}
Voilà comment ça marche. La Datagrid clone ses enfants deux fois, une fois pour
le header, une fois pour le contenu, sans les inspecter. Pour le header, elle passe
une intention « header », qui est un message qui dit à son enfant: dessine-toi dans
le cadre du header. Pour le contenu, elle lui passe une intention « content », qui est
un message qui dit à son enfant: « dessine-toi en dans le cadre du contenu ». 

En bas, vous voyez l’implémentation multi-intention du composant TextField. Et s’il
est décoré, ça marche aussi, puisque la data grid ne regarde pas les props de ses
enfants.
const VisitorFilter = props => (
<Filter {...props}>
<TextInput label="pos.search" source="q" alwaysOn />
<DateInput source="last_seen_gte" />
<NullableBooleanInput source="has_ordered" />
<NullableBooleanInput source="has_newsletter" defaultValue />
<SegmentInput />
</Filter>
);
Dans react-admin, on utilise cette technique pour les filtres. Les filtres, c’est un
composant qui définit les champs qui serviront à la recherche. Mais ces filtres
doivent pouvoir apparaitre sous deux formes: lorsqu’ils sont activés, sous forme
de champ de recherche, et lorsqu’ils ne sont pas activés, sous forme d’entrée
dans une liste de filtres supplémentaires.

Pour faire ça, le composant Filter clone lui aussi ses enfants deux fois, avec deux
« intentions » différents. Ca lui permet d’éviter toute supposition quant aux
capacités de ses enfants.

Alors attention à ne pas abuser de cette technique, parce que parfois, cloner pour
ce n’est pas rendre service. Certaines vérités ne doivent pas être montrées à tout
prix.
C O N S E I L # 5
~
C U LT I V E Z L’ I S O L AT I O N
Ces conseils permettent de faire des composants bien découpés, mais pas
forcément bien découplés. C’est à l’usage que l’on se rend compte si l’API d’un
composant, c’est-à-dire les propriétés qu’il s’attend à recevoir, sont pratiques. Et
le meilleur moyen de s’en rendre compte, c’est de se forcer à utiliser chaque
composant indépendamment des autres.
import React from 'react';
import { shallow } from 'enzyme';
import { Pagination } from './Pagination';
describe('<Pagination />', () => {
it('should display a limit when there is no result', () => {
const wrapper = shallow(<Pagination total={0} />);
expect(wrapper.find(‘pure(translate(PaginationLimit))'))
.toHaveLength(1);
});
it('should not display a limit when there are results', () => {
const wrapper = shallow(<Pagination total={1} ids={[1]} />);
expect(wrapper.find(‘pure(translate(PaginationLimit))'))
.toHaveLength(0);
});
});
C’est ce qu’on fait naturellement en faisant des tests unitaires. L’équivalent du
test unitaire dans un framework de composants, ça passe par le shallow
rendering: on ne fait pas un rendu complet, mais juste celui d’un composant, en
mockant ses props et ses enfants. Ici, vous voyez le test unitaire d’un composant
de pagination de react-admin, qui est normalement passé en fils d’un composant
`<List>`. 

Ecrire des tests avec du shallow rendering, c’est donc un bon moyen de valider
comment un composant se comporte en isolation.
Un deuxième moyen, plus visuel celui-là, de tester des composants en isolation,
c’est de les intégrer dans un storybook. Storybook, c’est le nom d’une librairie
open-source qui permet de publier une liste de composants documentés de façon
vivante, en utilisant le code qu’elle documente. Ici, vous voyez le storybook d’une
librairie de composants de graphiques de données, qui permet de jouer avec les
propriétés pour varier l’aspect ou le comportement. Storybook, c’est un super outil
pour les équipes qui développent une librairie de composants, et pour les
intégrateurs qui doivent utiliser ces composants.
L’étape d’après, c’est d’intégrer cette bibliothèque de composants dans un éditeur
visuel. L’outil que vous voyez ici s’appelle Framer X, et il utilise des bibliothèques
de composants React. Quand je vous disais qu’un intégrateur pourrait utiliser des
composants aussi bien qu’un développeur, c’est à ça que je pensais.
Un dernier moyen de développer ses composants en isolation, c’est de monter
une cage de faraday autour de votre bureau. Seul inconvénient : vous risquez de
ne plus avoir accès à StackOverflow. Mais c’est quand même une solution à
considérer, spécialement si vous préférez l’isolation des développeurs à celle des
composants.
C O N S E I L # 6
~
E X P U L S E Z
L E S E F F E T S D E B O R D
Un jour ou l’autre, vos composants vont avoir des effets de bord, c’est-à-dire des
effets qui sortent du périmètre du composant. Par exemple, dans une datagrid, le
clic sur un intitulé de colonne peut déclencher un appel API pour récupérer les
données triées selon le champ correspondant. Un bouton d’envoi de formulaire
peut montrer une notification si le formulaire est invalide. Et si le formulaire est
valide, l’effet peut être de changer de page pour aller sur la liste. Appels HTTP,
notifications, redirections sont des exemples d’effets de bords, ou side effects en
anglais. Et si vous gérez vos effets de bord directement dans le composant, adieu
la portabilité.
class Validate extends Component {
state = {
loading: false,
}
handleClick() {
this.setState({ loading: true })
fetch(`/validate?content=${this.props.content}`)
.then(() => this.setState({ loading: false }))
}
render() {
<button onClick={this.handleClick} >
{this.state.loading
? <SpinnerIcon />
: <ValidateIcon />
}
Validate
</button>
}
}
export default Validate;
Regardez sur cet exemple: un composant Validate permet de valider un contenu
coté serveur en appellant une url « /validate » sur une API. 

Ici, l’effet de bord (c’est l’appel http via fetch()) est hardcodé dans le composant.
Maintenant, imaginez si l’API exige que les appels soient authentifiés par un cookie
JWT, ou si les routes sont en français… Dans ce cas, impossible de réutiliser le
composant Validate.

class Validate extends Component {
handleClick() {
this.props.fetchAPI(‘validate');
}
render() {
<button onClick={this.handleClick} >
{this.props.loading
? <SpinnerIcon />
: <ValidateIcon />
}
Validate
</button>
}
}
function mapStateToProps(state) {
return { loading: state.loading }
}
function mapDispatchToProps() {
return { fetchAPI }
}
export default connect(mapStateToProps, mapDispatchToProps)
(Validate)
La solution consiste à ne pas laisser un composants lancer des effets de bord. Au
lieu de ça, les composants peuvent appeler des fonctions que leur passe leur
parent pour envoyer des évènements à l’extérieur. on dit aussi dispatcher des
actions (c’est ce que fait ici la fonction fetchAPI). Ca implique que vous utilisiez
une librairie de gestion d’actions et d’état (ici, c’est Redux), et une librairie d’effets
de bords compatible (pour Redux, ça peut être redux-thunk, redux-saga, ou redux-
observables). La librairie de gestion d’effets de bord réagira à certaines actions
pour déclencher des effets ailleurs dans l’application, et ces effets pourront être
modifiés par le développeur (par exemple pour modifier l’URL à appeler). Mais tout
Cette solution, c’est un peu celle qu’a adoptée Pablo Escobar, ici à gauche, pour
diriger le Cartel de Medellin en 1991, alors qu’il était officiellement emprisonné par
le gouvernement Colombien. Isolé dans un palais qu’il avait lui-même construit, il
continuait à diriger le plus grand trafic de cocaine de tous les temps, en envoyant
des messages…par fax. C’est son équipe qui s’occupait des effets de bord,
comme le transport de drogue, la corruption, et les meurtres. C’est un bon
exemple pour nous, les développeurs web: il faut faire des composants comme
Pablo Escobar faisait du trafic de drogue : en déléguant les effets de bord.
C O N S E I L # 7
~
M E T T E Z D U S T Y L E
D A N S V O T R E C O M P O R T E M E N T
Dernier conseil - et celui-ci est plus controversé, puisqu’on parle de CSS in JS. Si
vous stylez vos composants en leur mettant des classes qui font référence à une
feuille de style globale, vous n’avez pas compris le principe des composants.
Parce qu’il s’agit de pouvoir encapsuler à la fois logique et présentation dans un
module autonome, réutilisable.
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/
bootstrap.min.css"
integrity="sha384-MCw98/
SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
crossorigin="anonymous"
>
const ListButton = ({ resource }) => (
<Button className="btn btn-large">
<ListIcon />
Liste de {resource}s
</Button>
)
export default ListButton;
Tenez, ici, avec cette approche, pour afficher un bouton à bords arrondis, je dois
charger la feuille de style de bootstrap, qui me fournit les classes btn et btn-large.
Donc non seulement le composant n’est pas utilisable sans la feuille de style, mais
surtout j’oblige les utilisateurs à télécharger 141 kilos octets de CSS, dont 99% qui
ne les concerne pas.

C’est un peu comme si, pour réserver une table dans un restaurant, j’étais obligé
de signer un contrat de 20 pages écrites dans un jargon juridique
incompréhensible, dans lequel une clause écrite en Arial 6 garantit que les restes
de mon repas seront conservés pour examen ADN en cas de non versement du
pourboire. Je ne sais pas si vous vous acceptez ce genre de choses, mais moi
non.

Alors quand je fais des composants, c’est pareil: j’essaie de faire que chaque
composant puisse être utilisé complètement indépendamment - y compris des
feuilles de style.
const ListButton = ({ resource, classes }) => {
<Button style={{
display: 'inline-block',
fontWeight: 400,
textAlign: 'center',
verticalAlign: 'middle',
borderRadius: '.3rem',
color: '#007bff',
}}>
<ListIcon />
Liste de {resource}s
</Button>
}
export default Button;
Dans sa plus simple expression, le CSS-in-JS consiste à mettre les styles
directement dans le code des composants, comme ici en utilisant la propriété
style. Là, on ne peut pas dire, c’est bien encapsulé. C’est aussi affreusement laid,
et si vous avez vomi en voyant ça, sachez que ce n’est pas la solution que je
préconise. Eh oui, parce que pour surcharger ce style-là, il va falloir mettre des !
important partout, et en plus les styles sont dupliqués à chaque utilisation du
composant.
import { withStyles } from '@material-ui/core/styles';
const styles = {
button: {
display: 'inline-block',
fontWeight: 400,
textAlign: 'center',
verticalAlign: 'middle',
borderRadius: ‘.3rem',
color: '#007bff',
}
};
const ListButton = ({ resource, classes }) => {
<Button className={classes.button}>
<ListIcon />
Liste de {resource}s
</Button>
}
export default withStyles(styles)(Button);
Quand je dis CSS in JS, je pense plutôt à des librairies spécialisées, qui vous
permettent d’éviter les styles inline. Ici, j’écrit le CSS dans le fichier du
composant, mais in fine, les styles se retrouveront bien dans une feuille de style
commune - recomposée par la librairie de CSS in JS au moment du build.

Dans cet exemple, j’utilise JSS, qui est une librairie de CSS-in-JS intégrée à
material-ui. Elle transforme des styles écrits en JS en classes CSS qui sont
injectées dans le document HTML. Mon composant ne récupère que les noms de
ces classes générées, qu’il peut utiliser dans son markup.

Il existe plein d’autres solutions de CSS-in-JS alternatives à JSS: styled-
import { withStyles } from '@material-ui/core/styles';
const styles = theme => ({
button: {
display: 'inline-block',
fontWeight: 400,
textAlign: 'center',
verticalAlign: 'middle',
borderRadius: '.3rem',
color: theme.colors.primary,
}
});
const ListButton = ({ resource, classes }) => {
<Button className={classes.button}>
<ListIcon />
Liste de {resource}s
</Button>
}
export default withStyles(styles)(Button);
Juste un exemple de ces fonctionnalités avancées : le theming. Ici, avec JSS, je
choisis que la couleur du bouton n’est pas bleue, comme sur la page précédente,
mais la couleur primaire du thème. Un développeur pourra, sans retoucher le code
de ce composant, changer sa couleur en fournissant plus haut dans la chaine un
thème personnalisé.

Les librairies de CSS in JS s’occupent des préfixes vendor-specific, elles
supportent les media queries, et permettent d’extraire les styles dans une feuille
CSS externe à la compilation. Comme ça, les utilisateurs ne souffrent pas en
termes de performance.
Quand on découvre le CSS in JS, quand on goûte au style dans les composants,
c’est un peu comme quand on regarde pour la première fois de sa vie une comédie
musicale. Après ça, on n’arrive plus à voir un film où personne ne danse ni ne
chante. C’est vrai, moi quand je regarde un film de Spiderman, j’attends le moment
où Peter Parker va chausser ses claquettes pour montrer au Gobelin vert qu’avec
quelques rimes et un peu d’amour, tous les problèmes se résolvent d’eux-mêmes.
Et ça conclut ma liste de 7 conseils pour réussir ses composants. Avec les
techniques que je viens de vous exposer, on a créé des composants domain-
specific qui couvrent la plupart des besoins des applications d’administration. Le
résultat, c’est qu’on développe des interfaces d’administration méga vite.

React-admin est tellement rapide qu’il nous sert d’outil de prototypage: au lieu de
faire des mockups sur Sketch, on les fait en React. Sauf qu’à la fin du prototypage,
l’application est finie. 

Je me la pête, mais en même temps je viens de vous donner la recette pour faire la
même chose, pour créer votre propre DSL avec des composants. Vous aussi, vous
ou grâce à WinDev, mais c’est l’objet d’une autre conférence
Age de l’application
sans composants avec composants
TEMPS D’IMPLÉMENTATION

D’UNE FONCTIONNALITÉ
Et au-delà du prototypage, le gros avantage des composants, c’est qu’ils offrent
une productivité constante, quelle que soit la complexité de l’application, comme
on le voit sur ce graphique totalement pas basé sur des données réelles. Avec
n’importe quelle autre solution, plus une application est grosse, plus une évolution
prend du temps à implémenter. Avec une approche par composant, ce n’est plus
le cas. Les développeurs ont toujours la même vitesse de développement, au
démarrage comme après 3 ans sur un projet.
Et je ne le répèterai jamais assez, le gros avantage d’un composant, c’est que
vous pouvez le remplacer par un autre de même forme. Tout comme vous pouvez
utiliser une imprimante 3d pour créer vos propres formes de lego, dans une
application construite avec une bibliothèque de composants comme react-admin,
vous pouvez remplacer n’importe quel composant par le vôtre. A l’inverse d’un
framework, une bibliothèque de composants ne vous limite jamais.
- F R A N Ç O I S C H O L L E T
« Good software makes
hard things easy »
Cette notion de composants est donc une bonne modélisation, puisqu’elle
simplifie le développement et qu’elle ouvre plein de nouvelles possibilités.
AFOCA D U LT FA N O F
C O M P O N E N T S
Voilà. Je pense que tout ça fait de moi officiellement un AFOC, un Adult fan of
Components, et non pas
AFOC
A C R O N Y M E F R A N Ç A I S
O U T R A G E U S E M E N T
C A P I L L O T R A C T É
un Acronyme Français Outrageusemnt Capillotracté. Non non, je suis bien un Adult
Fan of Components,
AFOCA D U LT FA N O F
C O M P O N E N T S
je suis bien un Adult Fan of Components,
Pour nous les AFOC, collaborer sur un projet avec des composants développés
comme ça, c’est un peu comme faire des legos en accéléré. C’est fun, rapide,
super réactif, ça facilite la collaboration et l’invention. En fait, on n’a pas
l’impression de travailler. Développer des applications web devient un jeu d’enfant.
Alors, je ne peux que vous conseiller d’en faire autant.
D É V E L O P P E Z
D E S C O M P O S A N T S
J O L I S
D Y N A M I Q U E S
A U T O N O M E S
Q U I N E F O N T Q U ’ U N E C H O S E
C O N F I G U R A B L E S PA R D ’ A U T R E S C O M P O S A N T S
S A N S E F F E T S D E B O R D
I N T E R O P É R A B L E S
En conclusion, si vous ne devez retenir qu’une slide de ma conférence, c’est celle-
ci. On y voit que j’ai parlé pendant 45 minutes pour pas grand chose en fait, mais
c’était un plaisir de partager ça avec vous.

Et si vous avez envie de jouer avec des composants qui sont déjà faits comme ça,
je suis sûr que vous aurez bientôt un back-office à développer qui vous permettra
d’essayer react-admin. Vous m’en direz des nouvelles !

François Zaninotto - @francoisz -
Merci !

Contenu connexe

Similaire à Vous aimez les legos ? React est fait pour vous !

Monorepo & Monomythe (@Volcamp 2023)
Monorepo & Monomythe (@Volcamp 2023)Monorepo & Monomythe (@Volcamp 2023)
Monorepo & Monomythe (@Volcamp 2023)François
 
wordcamp biarritz 2.pdf
wordcamp biarritz 2.pdfwordcamp biarritz 2.pdf
wordcamp biarritz 2.pdfbacile1
 
Studio remote pour les indies : comment j'ai appris à ne plus m'en faire et à...
Studio remote pour les indies : comment j'ai appris à ne plus m'en faire et à...Studio remote pour les indies : comment j'ai appris à ne plus m'en faire et à...
Studio remote pour les indies : comment j'ai appris à ne plus m'en faire et à...Game Camp France
 
Le_Bitcoin_pour_les_Nuls.pdf
Le_Bitcoin_pour_les_Nuls.pdfLe_Bitcoin_pour_les_Nuls.pdf
Le_Bitcoin_pour_les_Nuls.pdfOpenWorld
 
Conseils emarketing pour_professionnels
Conseils emarketing pour_professionnelsConseils emarketing pour_professionnels
Conseils emarketing pour_professionnelskhawla16
 
La veille de Red Guy du 05.02.14 - Le flat design
La veille de Red Guy du 05.02.14 - Le flat designLa veille de Red Guy du 05.02.14 - Le flat design
La veille de Red Guy du 05.02.14 - Le flat designRed Guy
 
Conférence Paris Web 2015 - Vers une bonne pratique du Pair Design
Conférence Paris Web 2015 - Vers une bonne pratique du Pair DesignConférence Paris Web 2015 - Vers une bonne pratique du Pair Design
Conférence Paris Web 2015 - Vers une bonne pratique du Pair DesignCatherine Verfaillie
 
Tutoriel protel99 se
Tutoriel protel99 seTutoriel protel99 se
Tutoriel protel99 seCLES-FACIL
 
SoBookmagazine Mongeot
SoBookmagazine MongeotSoBookmagazine Mongeot
SoBookmagazine MongeotMaxime Mongeot
 
Communiquer des idées avec des présentations qui n'endorment pas votre auditoire
Communiquer des idées avec des présentations qui n'endorment pas votre auditoireCommuniquer des idées avec des présentations qui n'endorment pas votre auditoire
Communiquer des idées avec des présentations qui n'endorment pas votre auditoireConcept Image
 
[Kit agile] Jeu Agiville
[Kit agile] Jeu Agiville[Kit agile] Jeu Agiville
[Kit agile] Jeu AgivilleFou Cha
 
Dictionnaire des idées reçues sur le monde digital #dictionnerd
Dictionnaire des idées reçues sur le monde digital #dictionnerdDictionnaire des idées reçues sur le monde digital #dictionnerd
Dictionnaire des idées reçues sur le monde digital #dictionnerdChoblab.com est mon terrain de jeu
 
Le jeu du prénom en mode multitâche
Le jeu du prénom en mode multitâcheLe jeu du prénom en mode multitâche
Le jeu du prénom en mode multitâcheFabrice Aimetti
 
Newsletter Soho Solo N°27 Décembre 09
Newsletter Soho Solo N°27 Décembre 09Newsletter Soho Solo N°27 Décembre 09
Newsletter Soho Solo N°27 Décembre 09Soho Solo Gers
 
Présentation des réalisations du FunLab de Tours à Outremer
Présentation des réalisations du FunLab de Tours à OutremerPrésentation des réalisations du FunLab de Tours à Outremer
Présentation des réalisations du FunLab de Tours à OutremerOutremerCo
 
Boîte à outils du 2.0 pour débutants motivés et curieux (2009)
Boîte à outils du 2.0 pour débutants motivés et curieux (2009)Boîte à outils du 2.0 pour débutants motivés et curieux (2009)
Boîte à outils du 2.0 pour débutants motivés et curieux (2009)Ardesi Midi-Pyrénées
 

Similaire à Vous aimez les legos ? React est fait pour vous ! (20)

Monorepo & Monomythe (@Volcamp 2023)
Monorepo & Monomythe (@Volcamp 2023)Monorepo & Monomythe (@Volcamp 2023)
Monorepo & Monomythe (@Volcamp 2023)
 
wordcamp biarritz 2.pdf
wordcamp biarritz 2.pdfwordcamp biarritz 2.pdf
wordcamp biarritz 2.pdf
 
Studio remote pour les indies : comment j'ai appris à ne plus m'en faire et à...
Studio remote pour les indies : comment j'ai appris à ne plus m'en faire et à...Studio remote pour les indies : comment j'ai appris à ne plus m'en faire et à...
Studio remote pour les indies : comment j'ai appris à ne plus m'en faire et à...
 
Le_Bitcoin_pour_les_Nuls.pdf
Le_Bitcoin_pour_les_Nuls.pdfLe_Bitcoin_pour_les_Nuls.pdf
Le_Bitcoin_pour_les_Nuls.pdf
 
Conseils emarketing pour_professionnels
Conseils emarketing pour_professionnelsConseils emarketing pour_professionnels
Conseils emarketing pour_professionnels
 
Travail du futur
Travail du futurTravail du futur
Travail du futur
 
La veille de Red Guy du 05.02.14 - Le flat design
La veille de Red Guy du 05.02.14 - Le flat designLa veille de Red Guy du 05.02.14 - Le flat design
La veille de Red Guy du 05.02.14 - Le flat design
 
Conférence Paris Web 2015 - Vers une bonne pratique du Pair Design
Conférence Paris Web 2015 - Vers une bonne pratique du Pair DesignConférence Paris Web 2015 - Vers une bonne pratique du Pair Design
Conférence Paris Web 2015 - Vers une bonne pratique du Pair Design
 
Tutoriel protel99 se
Tutoriel protel99 seTutoriel protel99 se
Tutoriel protel99 se
 
SoBookmagazine Mongeot
SoBookmagazine MongeotSoBookmagazine Mongeot
SoBookmagazine Mongeot
 
Communiquer des idées avec des présentations qui n'endorment pas votre auditoire
Communiquer des idées avec des présentations qui n'endorment pas votre auditoireCommuniquer des idées avec des présentations qui n'endorment pas votre auditoire
Communiquer des idées avec des présentations qui n'endorment pas votre auditoire
 
[Kit agile] Jeu Agiville
[Kit agile] Jeu Agiville[Kit agile] Jeu Agiville
[Kit agile] Jeu Agiville
 
Impression 3D en EPN
Impression 3D en EPNImpression 3D en EPN
Impression 3D en EPN
 
Comprendre Web 2.0
Comprendre Web 2.0Comprendre Web 2.0
Comprendre Web 2.0
 
Dictionnaire des idées reçues sur le monde digital #dictionnerd
Dictionnaire des idées reçues sur le monde digital #dictionnerdDictionnaire des idées reçues sur le monde digital #dictionnerd
Dictionnaire des idées reçues sur le monde digital #dictionnerd
 
Le jeu du prénom en mode multitâche
Le jeu du prénom en mode multitâcheLe jeu du prénom en mode multitâche
Le jeu du prénom en mode multitâche
 
Newsletter Soho Solo N°27 Décembre 09
Newsletter Soho Solo N°27 Décembre 09Newsletter Soho Solo N°27 Décembre 09
Newsletter Soho Solo N°27 Décembre 09
 
Présentation des réalisations du FunLab de Tours à Outremer
Présentation des réalisations du FunLab de Tours à OutremerPrésentation des réalisations du FunLab de Tours à Outremer
Présentation des réalisations du FunLab de Tours à Outremer
 
Boîte à outils du 2.0 pour débutants motivés et curieux (2009)
Boîte à outils du 2.0 pour débutants motivés et curieux (2009)Boîte à outils du 2.0 pour débutants motivés et curieux (2009)
Boîte à outils du 2.0 pour débutants motivés et curieux (2009)
 
Guide d'activités CUBELETS - Fréquence Écoles
Guide d'activités CUBELETS - Fréquence ÉcolesGuide d'activités CUBELETS - Fréquence Écoles
Guide d'activités CUBELETS - Fréquence Écoles
 

Plus de Francois Zaninotto

La blockchain, quand l'individu sert au collectif... malgré lui
La blockchain, quand l'individu sert au collectif... malgré luiLa blockchain, quand l'individu sert au collectif... malgré lui
La blockchain, quand l'individu sert au collectif... malgré luiFrancois Zaninotto
 
Le jeu vidéo à la rescousse du web
Le jeu vidéo à la rescousse du webLe jeu vidéo à la rescousse du web
Le jeu vidéo à la rescousse du webFrancois Zaninotto
 
Frameworks : A history of violence
Frameworks : A history of violenceFrameworks : A history of violence
Frameworks : A history of violenceFrancois Zaninotto
 
La migration continue vers Symfony
La migration continue vers SymfonyLa migration continue vers Symfony
La migration continue vers SymfonyFrancois Zaninotto
 
La programmation asynchrone... et les pates
La programmation asynchrone... et les patesLa programmation asynchrone... et les pates
La programmation asynchrone... et les patesFrancois Zaninotto
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
Simplify your professional web development with symfony
Simplify your professional web development with symfonySimplify your professional web development with symfony
Simplify your professional web development with symfonyFrancois Zaninotto
 

Plus de Francois Zaninotto (12)

GraphQL, l'avenir du REST ?
GraphQL, l'avenir du REST ?GraphQL, l'avenir du REST ?
GraphQL, l'avenir du REST ?
 
La blockchain, quand l'individu sert au collectif... malgré lui
La blockchain, quand l'individu sert au collectif... malgré luiLa blockchain, quand l'individu sert au collectif... malgré lui
La blockchain, quand l'individu sert au collectif... malgré lui
 
Le jeu vidéo à la rescousse du web
Le jeu vidéo à la rescousse du webLe jeu vidéo à la rescousse du web
Le jeu vidéo à la rescousse du web
 
Frameworks : A history of violence
Frameworks : A history of violenceFrameworks : A history of violence
Frameworks : A history of violence
 
Php 100k
Php 100kPhp 100k
Php 100k
 
La migration continue vers Symfony
La migration continue vers SymfonyLa migration continue vers Symfony
La migration continue vers Symfony
 
La programmation asynchrone... et les pates
La programmation asynchrone... et les patesLa programmation asynchrone... et les pates
La programmation asynchrone... et les pates
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Ce bon vieux propel
Ce bon vieux propelCe bon vieux propel
Ce bon vieux propel
 
Symfony2 meets propel 1.5
Symfony2 meets propel 1.5Symfony2 meets propel 1.5
Symfony2 meets propel 1.5
 
Developing for Developers
Developing for DevelopersDeveloping for Developers
Developing for Developers
 
Simplify your professional web development with symfony
Simplify your professional web development with symfonySimplify your professional web development with symfony
Simplify your professional web development with symfony
 

Vous aimez les legos ? React est fait pour vous !

  • 1. D E S L E G O S A U X C O M P O S A N T S W E B F R A N Ç O I S Z A N I N O T T O - M A R M E L A B - B L E N D W E B M I X 2 0 1 8 Bonjour à tous, c’est un grand plaisir pour moi de venir pour la troisième fois à BlendWebMix. Je suis François Zaninotto, je dirige une entreprise qui s’appelle marmelab, et j’ai une confession à vous faire. I L E G O S J’adore les legos. Pour moi, c’est la plus grande invention du 20è siècle, devant : - les antibiotiques, - le transistor, - le walkman, et - le minitel. En plus c’est une invention super simple : des picots ronds séparés de 8 mm en haut, une base creuse pour enficher les picots, un plastique dur et lisse. C'est tout. Et pourtant, il a fallu pas mal de temps à son inventeur pour arriver autant de simplicité.
  • 2. Son inventeur, c’est lui: Ole Kirk Christiansen, un charpentier danois. Il n’a pas l’air sur cette photo, mais c’était un sacré déconneur. En 1932, Ole crée les premiers legos… en bois. Ce n’était pas un très bon choix, parce que ses pièces ne tenaient pas bien longtemps. C’est l'invention des matières plastiques dures qui va révolutionner le concept, et faire que les Legos deviennent vraiment faciles à emboiter. C'était en 1958. 1932-1958, Il lui aura donc fallu 25 ans pour affiner le concept. 25 ans. Comme quoi, une idée simple ça peut prendre du temps. Dans ma famille, on est tous des fans de legos. Voici ma fille Nina avec une maquette du Flatiron Building à New York, 471 pièces, 2h30 de montage. Voici mon fils Samuel avec le chasseur tie qu’il a construit, 355 pièces, 1h30 de montage.
  • 3. Le petit dernier, Sacha, qui met déjà les mains dedans, 3 pièces, 3 minutes de montage. Et ça, c’est moi, avec ma dernière création. Je l’ai appelée Revolution 9. Un projet ambitieux, spectaculaire. 63 pièces. 3 jours de montage. J’espère le proposer bientôt au Centre Pompidou à Montauban. Pour tout vous dire, je suis ce qu'on appelle un AFOL, un Adult Fan Of Lego. [clic] Des AFOL, il y en a beaucoup. Il y en a peut-être dans cette salle. Votre voisin, votre voisine, regardez-le bien. C'est peut-être aussi un AFOL. La preuve que c’est un phénomène de société, c’est qu’il y a des émissions de télé dessus. Les AFOL sont souvent des inventeurs, des bâtisseurs, ils assemblent des briques sans plan, sans boite, guidés par leur seule imagination.
  • 4. Vous ne trouverez pas de boite ou de plan pour ces assemblages, ils sont uniques. Ils sont nés dans l’imagination de leurs créateurs ils peuvent nécessiter un travail considérable, et certains montages sont tellement remarquables…
  • 5. … qu’ils s’exposent dans des musées, comme cet assemblage de Nathan Sawaya, exposé cet été au Parc de la Villette à Paris. Tout ça pour vous dire que les legos ce n’est pas que pour les enfants… …c’est aussi pour les adultes. Alors, si vous êtes dans cette salle, c’est probablement parce que vous préférez jouer avec des ordis plutôt qu’avec des legos. Mais l’idée simple des legos, on la retrouve aussi dans certains jeux vidéos. Le plus proche, évidemment, c’est Minecraft. Il y a sans doute dans cette salle des AFOM, des Adultes Fans of Minecraft. Levez la main pour voir ?
  • 6. Le principe de Minecraft est encore plus radical que celui des legos, puisqu’il n’y a qu’une taille de bloc, mais il présente un avantage considérable, c'est qu'on peut collaborer par centaines sur une même création, et travailler en 3x8. Donc ça donne des créations encore plus grandioses qu'en Lego, comme cette recréation de l’univers de Harry Potter qui fourmille de détails. Bref, avec des petits composants standardisés, qui offrent une intéropérabilité simple, on peut tout construire. La maitrise des composants fait de nous des maitres bâtisseurs, en quelque sorte, des dieux. En Lego comme en Minecraft. Et ça, c’est vraiment génial. Il y a juste un problème. Avec les legos, construire des ensembles très complexes, c’est très très long, aussi long que bâtir une cathédrale. Comme on ne manipule que des briques élémentaires, ça prend des plombes. Même en Minecraft c’est lourd: les mods de construction disponibles permettent de façonner des terrains et de faire du copier coller de structures, mais une grosse partie de l’assemblage se fait quand même bloc par bloc.
  • 7. Je vous donne un exemple concret : Un des derniers assemblages de mon fils est la Cabane du Pêcheur, un ensemble de plus de 2000 pièces. Samuel a mis 10 heures à la monter. 10 heures d'affilée, et il n'a que 8 ans. La dernière fois qu'il a passé 10 heures d'affilée concentré sur quelque chose, c'était pour sortir du ventre de ma femme. C’est vous dire si c’était un effort considérable. Et puis cet ensemble, qui est au bureau pour que les enfants du personnel puissent y jouer quand un des collaborateur n'a pas de solution de garde, commence à nécessiter des réparations. Un bout de toit est parti, la rambarde a perdu un barreau. On a bizarrement des pièces en trop, et la réparation s’avère… compliquée. Il faut retrouver, dans le manuel de 252 pages, l'étape où on construit cette partie, identifier les pièces, les commander sur le site Lego.com, démonter la rambarde, la remonter avec la nouvelle pièce, et la remettre.
  • 8. Macro Components Pour moi, vous voyez, monter la cabane du pêcheur, c’était drôle la première fois avec mon fils, mais pas au point de le refaire. En bon informaticien, je me dis que si je fais la même chose deux fois, c’est un peu un constat d’échec. Je suis plutôt un adepte du copier collé, vous voyez ? Du coup, pour réparer la cabane du pêcheur, j’aimerais bien pouvoir commander des blocs entiers plutôt que des pièces à l’unité. Un toit, une tour. Appelons-ça des macro-composants. J’ai cherché, eh bien figurez-vous que personne ne vend ça. On ne trouve que des boites de pièces non assemblées, ou bien des maquettes complètes. Il semble que personne n’ai jamais eu besoin d’acheter des macro composants. C’est peut- être qu’il n’y a pas assez d’informaticiens qui jouent aux legos. Ou peut-être que je ne suis pas un vrai AFOL. AFOLA D U LT FA N O F L E G O FAKE Un vrai AFOL n’hésiterait jamais à tout détruire pour remonter un ensemble à nouveau brique par brique. Ca fait de moi un faux AFOL. Mais avant de vous moquer de moi, mettez-vous à ma place. Si votre métier, c’était de construire des grands ensembles à partir de toutes petites briques, ça vous ennuierait sans doute assez vite, non ?
  • 9. Eh mais attendez, je dis ça, mais en fait votre métier c’est exactement la même chose ! Vous construisez des applis web complexes en assemblant de touts petits blocs - les éléments HTML. Et les éléments HTML, ce sont des composants tout comme les briques de Lego. Et grâce à HMTL, vous pouvez construire toutes sortes de choses merveilleuses, comme cette page d’accueil de la Pizzeria Ostorea 3, qui est un assemblage savant d’éléments H1, DIV, IMG… et MARQUEE. Mais dès qu’on essaie de construire de grosses applications dotées d’une logique métier importante avec de touts petits éléments HTML, on se retrouve avec le même problème qu’avec les legos. Ca prend beaucoup de temps, et du coup, ça coute cher. Très cher .L’interface que je vous montre ici a été achetée par Microsoft pour 26 milliards de dollars. C’est vraiment un très cher assemblage d’éléments HTML, et à mon avis ça prouve qu’il y a un problème. En bon informaticien, si on me demandait de construire cette page, j’aimerais bien assembler des gros ensembles plutôt que des petites balises HTML, comme en legos. Mais alors, qu’est-ce qui correspond à un mur, un toit, ou une rambarde sur
  • 10. topbar profile main recommend ations On peut imaginer un macro-composant pour la barre de navigation, un autre pour le profil, un pour le contenu principal, et encore un pour les recommandations. Ces macro-composants eux-mêmes pourraient être découpés en plus petits macro- composants, topbar profile main recommend ations bio stats postform updates search navigation comme un moteur de recherche, un menu de navigation, une bio, etc. Et on peut continuer à découper pour arriver à des composants assez élémentaires. Et si chacun de ces composants avait une représentation HTML, <homepage> <topbar> <logo /> <search /> <navigation> <avatar src="./fzaninotto.jpg" /> </navigation> </topbar> <advertisement /> <div style="display:flex"> <profile userId="45758" style="width:200px"> <bio /> <stats> </profile> <main style="flex:auto"> <postform/> <updates sortBy="date"> <post authorId="23525"> I see less and less value
 in using LinkedIn, too superficial </post> </updates> </main> <recommendations style="width:300px" /> </div> </homepage> On pourrait les assembler avec d’autres éléments HTML… Imaginez des composants « métier », comme <navigation>, <profile>, <recommendations>, avec chacun des propriétés liées à leur contenu, leur style et leur comportement. Ca serait ce qu’on appelle un DSL, un Domain Specific Language. Si on avait des macro-composants comme ça, créer des applis web irait beaucoup, beaucoup plus vite, non ?
  • 11. Ces macro-composants, s’ils existaient, il simplifient tellement le développement de sites web qu’on pourrait confier le travail non pas à des développeurs, qui sentent fort et qui ont la barbe mal taillée, mais à des intégrateurs, qui en général sont mieux de leur personne, et en plus bien moins chers. D’où un double bénéfice financier et olfactif. <SubscribeButton onClick={subscribe} icon="mail"> Subscribe to the newsletter </SubscribeButton> <a role="button" class="btn" id="1234"> <img src="/path/to/email.png" /> Subscribe to the newsletter </a> <style> .btn { padding: 8px; color: #3f51b5; border-radius: 4px; text-transform: uppercase; vertical-align: middle; text-decoration: none; } .btn:hover { background-color: rgba(63, 81, 181, 0.08); } .btn img { padding-right: 5px; } </style> <script> document .getElementById("1234") .onClick(subscribe); </script> Alors, à quoi ça ressemblerait un macro-composant ? Imaginez un composant non standard, comme ici SubscribeButton, qui utilisé dans un document HTML, se transformerait d’un coup de baguette magique en un ensemble complexe de composants élémentaires - une balise <a>, une balise <img>, une balise <style>, une balise <script>. Ca ressemble à du templating, mais en fait c’est plus que ça, puisqu’il faut que ces macro-composants métiers soient composables avec les éléments du HTML. Web Components Polymer.js Eh bien figurez-vous que d’autres personnes ont eu la même idée. Le standard HTML contient une spécification qui s’appelle les Web Components, et ça ressemble beaucoup à ce que je viens de vous montrer. Malheureusement les Web Components ne sont bien supportés que sur Chrome. Et puis l’API des web components est super lourde, au point qu’elle est inutilisable sans une surcouche. Polymer.js est justement une surcouche open-source qui rend les Web Components utilisables.
  • 12. React.js Vue.js Angular Alors pour une plus grande compatibilité, il faut se tourner vers aussi des implémentations en JavaScript pur de moteurs de composants, comme les frameworks open-source React, Vue et Angular. Notez que je ne mentionne pas jQuery - eh oui, le papi des frameworks JS ne permet pas de faire des composants. Si vous l’utilisez, il va falloir songer à le mettre à la retraite. HTML in JS JS in HTML <template> <div class="field"> <label class="label">Employer</label> <div class="control"> <input class="input" type="text" v-model="employer" /> </div> </div> </template> <script> export default { data() { return { employer: "Marmelab" }; }, }; </script> import React, { Component } from 'react'; export default class FormSample extends Component { state = { employer: 'Marmelab' }; handleEmployerChange = e => { this.setState({ employer: e.target.value }); }; render() { return ( <div className="field"> <label className="label">Employer</label> <div className="control"> <input className="input" type="text" onChange={this.handleEmployerChange} value={this.state.employer} /> </div> </div> ); } } Ce qui distingue React, Vue et Angular, c’est principalement la façon dont ils entremêlent le HTML et le JavaScript. A gauche, vous avez un exemple de composant en React, qui met du HTML dans son JS avec une syntaxe spéciale nommée JSX. A droite, vous voyez un template HTML Vue.js avec des directives spéciales comme v-model, qui simulent du JavaScript dans le HTML. Y a-t-il une syntaxe meilleure que l’autre ? Non, c’est une affaire de goût. Chaque approche a ses avantages et ses inconvénients. Et de toutes façons, mêler deux langages, c’est toujours bizarre, mais c’est obligatoire pour faire du templating.
  • 13. R E A C T. J S V U E . J S A N G U L A R L I F E C Y C L E M E T H O D S ✓ ✓ ✓ L O C A L S TAT E ✓ ✓ ✓ O N E - WAY D ATA B I N D I N G ✓ ✓ ✓ FA S T I N P R O D U C T I O N ✓ ✓ ✓ L A R G E U S E R B A S E ✓ ✓ ✓ G R E AT D O C U M E N TAT I O N ✓ ✓ ✓ E V E N T S H A N D L I N G ✓ ✓ ✓ I D E I N T E G R AT I O N ✓ ✓ ✓ E S 6 S U P P O R T ✓ ✓ ✓ T Y P E S C R I P T S U P P O R T ✓ ✓ ✓ U N I T T E S TA B L E ✓ ✓ ✓ Et puis ces librairies ont vraiment beaucoup en commun. Alors évidemment elles ont des différences, chacune va briller un peu plus que l’autre dans certaines situations. Mais globalement elles sont toutes très bonnes, et vous ne ferez pas un mauvais choix en prenant l’une ou l’autre. Malheureusement, vous rencontrerez beaucoup gens très dogmatiques qui prétendent que telle librairie est la seule bonne, et qui sont prêts à en découdre si vous dites le contraire. Pour moi, la librairie que vous choisirez importe moins que le fait d’utiliser une approche par composants, et c’est là-dessus que je vais insister. Bon, pour la suite de cette présentation, j’utiliserai React, qui est la librairie que je maîtrise le mieux, mais tout ce que je vais vous dire est aussi valable pour Polymer, Vue, et Angular. Donc je résume, toutes ces librairies sont bonnes, mais React est la meilleure. <SubscribeButton onClick={subscribe} icon="mail"> Subscribe to the newsletter </SubscribeButton> const styles = { button: { padding: 8, color: '#3f51b5', borderRadius: 4, textTransform: 'uppercase', verticalAlign: 'middle', textDecoration: 'none', }, icon: { paddingRight: 5, }, }; const SubscribeButton = ({ onClick, icon, children }) => ( <a role="button" style={styles.button} onClick={onClick}> <img src={`/path/to/${icon}.png`} style={styles.icon} /> {children} </a> ); export default StyledButton; Definition Usage Un framework de composants comme React.js fournit le mécanisme pour assembler des éléments HTML et publier des composants plus gros. Vous voyez ici comment React permet de créer le composant SubscribeButton de tout à l’heure. Donc, le problème est réglé ? Oui mais non. En fait, ça ne répond pas à mon besoin. Souvenez-vous, moi je ne veux pas un système pour assembler des briques élémentaires - j’ai déjà mon fils pour ça. Ce que je cherche, ce sont des gros composants tout faits. Il n’y a que comme ça que mon développement web pourra se faire à une vitesse supportable.
  • 14. Figurez-vous que d’autres personnes ont eu la même idée. Il existe pléthore de bibliothèques de composants React pour faire des boutons, des onglets, des barres de navigation, des fils d’ariane. En plus, elles ont le bon goût de ne pas réinventer le design, elles se basent sur des styles éprouvés comme Bootstrap, Material design ou Semantic UI. Voici par exemple une librairie qui s’appelle semantic ui react, et qui propose des jolis boutons stylés à la semantic ui. Voici une autre librairie, react-bootstrap, qui propose des jolis boutons stylés à la Bootstrap. Voici enfin une librairie qui s’appelle material-ui, et qui propose des jolis boutons stylés à la Material Design. (…) En fait, je vous avoue que je suis un peu dubitatif. C’est sûr, ces bibliothèques sont très utiles. Elles me permettent de gagner du temps pour arriver à un résultat joli. Mais je devrai quand même assembler de petits composants. En fait, ces bibliothèques proposent juste des versions plus jolies des éléments de base du HTML, comme l’élément button.
  • 15. Pour moi, ces bibliothèques de composants sont un peu comme les boites de legos issues d’une licence, comme Lego Star Wars. Je les vois comme des boites de pièces plus stylées, mais les pièces ne sont toujours pas assemblées. Et à nouveau, si je dois faire des Faucons Milleniums toute la journée, ça va me soûler d’assembler autant de pièces qu’un y a de boutons sur le visage de Mark Hamill - c’est à dire, excusez du peu, 1414. Et puis je vais vous citer un autre défaut de ces boites de lego jolis : elles ne servent à rien. C’est vrai. Je ne peux pas trouver du travail avec, je ne peux pas appeler ma tante avec, je ne peux pas trouver l’âme soeur avec. Je ne peux faire qu’une maquette, à la rigueur pour la mettre sur mon étagère. Et pourquoi ces ensembles ne servent à rien ? Parce qu’ils sont statiques. De la même façon, une page web construite en assemblant des composants stylés sera elle aussi statique. Alors oui, elle sera plus jolie que la page de la pizzeria, de tout à l’heure, mais ca restera une page. Or, ce que demandent nos clients aujourd’hui, ce ne sont pas des pages web, mais des applications web, qui leur permettent de réaliser des tâches complexes comme trouver du travail, appeler leur tante ou trouver l’âme soeur.
  • 16. Alors, vous allez me dire: Et Lego Technics ? Et Lego Mindstorms? C’est vrai. Dans le monde des legos, il existe des composants qui permettent d’animer les maquettes. Des contrôleurs, des chaines de transmission, des engrenages. Et avec ces pièces là, les amateurs fabriquent des assemblages qui servent effectivement à quelque chose, comme cette machine à poser des ponts en legos. Vous avouerez qu’avec de tels montages, on a dépassé le stade de la maquette, et on peut commencer à imaginer gagner sa vie avec des legos. La question que je me pose en voyant ça, c’est : et pour nous les développeurs web, quand on utilise un framework de composants, c’est quoi l’équivalent de ces pièces dynamiques ? U S A G E L I B R A RY Routing React-Router State Redux, Mobx Api Fetching Fetch, Apollo, Urql Form Handling Redux-Form Side Effects Saga, Redux-Observables I18N I18Next, React-Intl Transitions React-Transition-Group Ce sont des librairies spécialisées dans la gestion du routing, des formulaires ou de l’internationalisation. Une tuyauterie sophistiquée qui permet de gérer des interactions complexes avec les utilisateurs. Le plus beau est que ces mécanismes sont fournis sous la forme de composants, qui sont faciles à assembler avec des composants stylés.
  • 17. Macro Components = React + React UI Kit + State management + Side effects management + Form management Cela me permet d’affiner la définition d’un macro-composant : c’est donc un composant qui sera dynamique et par défaut joli. Il devra s’appuyer à la fois sur des UI Kits et sur la quincaillerie dont je viens de parler. Si quelqu’un faisait ce genre de composants, ça accélèrerait vraiment le développement. Figurez-vous que d’autres personnes ont eu la même idée. Mais pas beaucoup. On trouve quelques macro-composants dynamiques en React, comme ici React Table, qui fournit les fonctionnalités d’une table de données avec tri, filtrage, et pagination. Le souci, c’est que l’écosystème React est encore trop jeune. Il n’y a pas de consensus sur la bonne façon de gérer l’état, ou les transitions, ou le look and feel. Du coup, si on trouve des macro-composants individuels (pour faire une datagrid, un menu hamburger, ou une select box), leurs APIs diffèrent, et il faut pas mal de travail pour les faire communiquer. A L I B R A RY O F M A C R O C O M P O N E N T S Donc en fait, le saint graal, ce n’est pas un macro-composant, c’est un ensemble cohérent de macro-composants, conçus pour être utilisés les uns avec les autres. Est-ce que quelqu’un a déjà eu cette idée ?
  • 18. Eh bien, j’ai cherché, et je n’ai pas trouvé. C’est un peu normal, si le graal était si facile à trouver, on serait tous immortels. Et si les hommes étaient immortels, le monde aurait d’autres problèmes à gérer que faire des sites web, comme par exemple : à quoi sert la prison puisqu’en étant immortel, on en sortira toujours vivant, ou encore pourquoi interdire les drogues puisqu’on n’en mourra pas, ou enfin
  • 19. quand est-ce qu’on touche sa retraite quand on est immortel ? Mais je m’égare. Ces problèmes ne se posent pas encore, also revenons à un problème actuel : pourquoi ça n’existe pas, une bibliothèque de macro-composants ? topbar profile main recommend ations A bien y réfléchir, c’est un peu normal que ça n’existe pas. C’est que ces macro- composants répondent à un besoin complexe, donc spécifique. Qui d’autre que LinkedIn pourrait utiliser une bibliothèque avec des macro-composants Profil ou Recommandations ? <connection> <skills> <company> <trip> <driver> <car> <restaurant> <menu> <opening-time> <coloscopy> <suppository> <treatment-form> Si vous-mêmes créez des macro-composants, vous le ferez pour le domaine sur lequel vous travaillez. Vous voyez ici le genre de composants que pourraient développer les équipes de LinkedIn, BlablaCar, La Fourchette, ou Doctissimo. On voit que certains on plus de chance que d’autres. Mais surtout, vous voyez que ces composants ne sont pas réutilisable dans un autre contexte. Un restaurant chez votre toubib ? Des horaires d’ouvertures pour un contact sur LinkedIn ?
  • 20. Une coloscopie dans un restaurant ? Mais bien sûr madame, vous la voulez à rosée ou à point ? A moins que… Il existe un domaine, un domaine spécifique, mais somme toute très commun. C’est le domaine des back-offices, que j’appellerai des admins parce que ça évite la confusion avec le terme « backend », qui désigne autre chose, et avec le terme « backroom », qui désigne… encore autre chose. Rassurez-vous, je n’ai pas d’image pour illustrer ce terme. Vous voyez, LinkedIn, LaFourchette, BlablaCar et Doctolib ont tous besoin d’une interface pour les administrateurs, ces super-utilisateurs qui doivent avoir accès à toutes les données, en lecture et en écriture. L’interface d’admin, tous les projets sur lesquels j’ai travaillé ces 10 dernières années en avaient besoin d’une. Dans sa plus simple expression, une admin c’est une interface crud devant une base de données - à la phpMyAdmin. Sauf que si vous mettez ça dans les mains d’un opérationnel, c’est très vite la catastrophe - j’ai l’impression que c’est déjà arrivé à certains d’entre vous. En général, les entreprises développent leur propre admin sur mesure. Les plus riches appellent ça un ERP, mais le principe est le même. Donc les administrations, voilà un besoin suffisamment générique pour créer des macro-composants qui auront une chance d’être réutilisés souvent.
  • 21. marmelab/react-admin A specialised admin framework for React React + material-ui + redux + redux-form + saga + reselect Il n’y avait pas de bibliothèque de macro-composants pour faire des administration, alors on l’a fait. Ma société développe depuis plus de 2 ans une librairie open-source qui s’appelle React-admin, et qui est exactement le saint graal dont je vous ai parlé depuis tout à l’heure. Pour que vous compreniez ce dont il s’agit, en voici une démo rapide. React-admin a permis de créer cette appli web, qui est l’administration d’une boutique de posters fictive. Le propriétaire de cette boutique peut y gérer ses clients, faire des statistiques sur leurs visites, gérer son catalogue de posters, il peut rechercher une commandes avec une recherche multi-critères et la marquer comme expédiée, il peut même aller jusqu’à modérer des commentaires. C’est un bon cas d’école pour un framework d’admin générique, et vous voyez ici comment react-admin s’en tire. Avec plus de 5,000 stars sur Github, react-admin est un projet déjà assez populaire pour que les conseils que je vais énoncer aujourd’hui s’appliquent à d’autres. Parce que, en concevant une bibliothèque de macro-composants d’administration, on a découvert des pratiques pas forcément intuitives, mais qui sont cruciales pour bien réussir ses propres macro-composants.
  • 22. Ces secrets de fabrication, c’est un peu comme ce qu’a découvert Ole Kirk Christiansen après 25 ans d’expérimentation. Sauf qu’avec la technologie moderne, on n’a mis que 2 ans à découvrir ce qui fait que des macro-composants s’assemblent, ce qui fait qu’ils tiennent ensemble, ce qui fait qu’ils vibrent ensemble, et pour tout dire, ce qui fait qu’on les aime. Je réalise que ma dernière phrase serait une super introduction pour une émission télé-réalité du genre « le Bachelor La finale: Marco va-t-il choisir Naëlle la belle rousse ou Mimi la petite blonde ? La révélation, c’est juste après la pub. ». J’ai peut-être raté ma vocation après tout. 7 T E C H N I Q U E S P O U R R É U S S I R S E S M A C R O - C O M P O S A N T S 1. Divisez pour mieux régner 2. Pour étendre, décorez ! 3. Laissez vos enfants tranquilles 4. Ayez le don de double vue 5. Cultivez l’isolation 6. Explusez les effets de bord 7. Mettez du style dans votre comportement Bref, je vais à présent vous révéler les leçons qu’on a apprises à la dure. 7 conseils assez techniques, et aux nom mystérieux parce que, en bon fan de Joséphine Ange Gardien, j’ai le goût du mystère.
  • 23. et pour tout vous dire c’est la partie de ma présentation pendant laquelle les non- développeurs peuvent dormir. Installez-vous confortablement, c’est promis, on ne fera pas trop de bruit. C O N S E I L # 1 ~ D I V I S E Z P O U R M I E U X R É G N E R Bien. Tout d’abord, divisez le travail pour que chaque composant ne fasse plus qu’une seule chose - mais bien. Si un composant fait plusieurs choses, découpez- le en plus petits composants. Je vous donne un exemple. List Filters Datagrid Field Dans toute admin, il y a des tableaux de données. Ici, vous voyez une liste d’articles avec pour chacun un titre, une date de publication, un nombre de vues, un auteur. Mais pour afficher cette page à partir d’un composant de liste générique, il faut définir un certain nombre d’options, comme par exemple les filtres, les champs, la pagination, etc.
  • 24. import React, { Component } from 'react'; import { List } from 'react-admin'; const filterConfig = { q: { type: 'text', label: 'Search' }, }; const fieldsConfig = { id: { type: 'text' }, title: { type: 'text' }, publishedAt: { type: 'date', label: 'publishedAt' }, views: { type: 'number' }, authorId: { type: 'reference', reference: 'authors', referenceField: 'lastName' } } const PostList = props => ( <List resource="posts" filters={filterConfig} fields={fieldsConfig} props={...props} /> ); Dans sa première version, le composant de liste de react-admin prenait en paramètre des objets de configuration pour les filtres et les colonnes à afficher. Le problème, c’est que ce macro-composant List, il faisait beaucoup, beaucoup trop de choses : requêter la route posts pour récupérer les données, afficher les filtres et gérer leur formulaire, afficher un tableau de données et gérer le tri par colonnes, afficher les données elles-mêmes en adaptant la mise en forme au type du champ… Ce macro-composant List comptait facilement plusieurs centaines, voir plusieurs milliers de lignes de code. C’est trop pour garantir une bonne lisibilité et une bonne maintenabilité. Quand je parle de macro-composant, pour moi le En matière de composants, c’est beau quand c’est petit. Et avec react-admin, on a trouvé un moyen d’éviter que les macro composants aient trop de code. import React, { Component } from 'react'; import { List, Datagrid, TextField, DateField, NumberField, ReferenceField, EditButton } from 'react-admin'; import PostFilter from './PostFilter'; const PostList = props => ( <List resource="posts" display={<Datagrid />} fields={[ <TextField source="id" />, <TextField source="title" />, <DateField source="publishedAt" />, <NumberField source="views" />, <ReferenceField source="authorId" reference="author"> <TextField source="lastName" /> </ReferenceField>, ]} filters={<PostFilter />} props={...props} /> ); Ca consiste à diviser un gros composant en composants élémentaires ayant une seule responsabilité. Voilà comment ça s’est traduit dans le cas de la liste d’articles. Le nouveau composant List s’occupe de récupérer les données (ici, une liste de publications) mais pas de les afficher. Il passe les données à un sous-composant display défini dans ses propriétés, qui a la responsabilité de les afficher. En l’occurrence, ici c’est un composant Datagrid, qui affiche les données dans une table. Mais ce n’est pas lui qui s’occupe de savoir quels colonnes afficher dans cette table, ce sont les composants définis dans la propriété fields. Pareil pour le composant filters, qui a
  • 25. import React, { Component } from 'react'; import { List, Datagrid, TextField, DateField, NumberField, ReferenceField, EditButton } from 'react-admin'; import PostFilter from './PostFilter'; const PostList = props => ( <List resource="posts" filters={<PostFilter />} props={...props} > <Datagrid> <TextField source="id" /> <TextField source="title" /> <DateField source="publishedAt" /> <NumberField source="views" /> <ReferenceField source="authorId" reference="author"> <TextField source="lastName" /> </ReferenceField> <EditButton /> </Datagrid> </List> ); Et on peut même aller encore un peu plus loin en choisissant une propriété de la list, ici la propriété display, et la renommer en children. Ca permet d’écrire du code bien plus lisible. import React, { Component } from 'react'; import { List, Datagrid, TextField, DateField, NumberField, ReferenceField, EditButton } from 'react-admin'; import PostFilter from './PostFilter'; const PostList = props => ( <List resource="posts" filters={<PostFilter />} props={...props} > <Datagrid> <TextField source="id" /> <TextField source="title" /> <DateField source="publishedAt" /> <NumberField source="views" /> <ReferenceField source="authorId" reference="author"> <TextField source="lastName" /> </ReferenceField> <EditButton /> </Datagrid> </List> ); import React, { Component } from 'react'; import { List, CardList, TextField, DateField, NumberField, ReferenceField, EditButton } from 'react-admin'; import InlinePostFilter from ‘./InlinePostFilter'; import HumanReadableDateField from ‘./Fields'; const PostList = props => ( <List resource="posts" filters={<InlinePostFilter />} props={…props} > <CardList> <TextField source="id" /> <TextField source="title" /> <HumanReadableDateField source="publishedAt" /> <NumberField source="views" /> <ReferenceField source="authorId" reference="author"> <TextField source="lastName" /> </ReferenceField> <EditButton /> </CardList> </List> ); Enorme avantage: je peux échanger chacun de ces composants par un autre. Si j’ai besoin d’afficher les données dans un autre format qu’une datagrid, je peux réutiliser toute la logique du composant List, qui est commune, et juste changer son fils. Je peux fournir ma propre implémentation des filtres, voire créer un type de champ spécialisé pour afficher les dates sous la forme « il y a tant de jours ». Comme tout est composant, la modification d’un composant se fait par la composition avec un autre composant. C’est hyper puissant. Cette méthode consistant à remplacer un élément par un autre, Staline ne l’aurait pas reniée. Il était un des précurseurs dans la manipulation d’image, comme ici sur une photo avec Nikolaï Yejov, retouchée après sa condamnation à mort en 1940. Mais s’il avait connu les composants, Staline aurait pu aller un cran plus loin et remplacer Nikolaï par son nouvel ami Brad.
  • 26. // in charge of fetching the data and handling state import ListController from './ListController'; // in charge of displaying the list view import ListView from './ListView'; const List = props => ( <ListController {...props}> <ListView /> </ListController> ); export default List; Je vous ai montré comment remplacer de la configuration par des sous- composants, mais on pourrait même appliquer la séparation des responsabilités à chaque composant, en mettant d’un côté la logique de préparation des données, appelons-la le contrôleur, et de l’autre la logique de présentation, appelons-la vue. Si ça vous rappelle le pattern MVC, ce n’est pas un hasard. L’avantage, c’est que chaque composant est testable indépendamment, et que vous pouvez facilement surcharger la partie présentation sans recopier toute la partie logique. Pour séparer la logique de la présentation, le composant parent peut, comme sur // in charge of fetching the data and handling state import ListController from './ListController'; // in charge of displaying the list view import ListView from './ListView'; const List = props => ( <ListController {...props}> {controllerProps => <ListView {...props, ...controllerProps} />} </ListController> ); export default List; Un autre pattern très à la mode, celui des render props, évite le clonage du composant fils, en forçant les développeurs à fournir une fonction comme fils et non un composant. Les deux approches ont leurs bénéfices et inconvénients, et react-admin utilise les deux. Ca nous notamment permis d’extraire la partie UI, ce qui rend possible une skin react-admin pour Bootstrap ou Semantic UI. Ce qu’il faut retenir c’est que plus vous réduirez les responsabilités de chaque composant, plus votre code sera modulaire et facile à tester. Un bon moyen mnémotechnique, c’est de se dire que si un composant fait plus de 100 lignes de code, il est peut-être nécessaire de le découper en un parent et un enfant. Stanley Kubrick qui, dans Shining, a compris qu’en découpant parents et enfants, on appliquait au mieux la séparation des responsabilités. Diviser pour mieux régner, souvenez-vous de cette formule, ou de cette image, elle est bien aussi.
  • 27. C O N S E I L # 2 ~ P O U R E T E N D R E , D É C O R E Z ! Deuxième conseil, qui a l’air tout simple mais qui est étonnamment puissant : utilisez la décoration pour étendre un composant. J’utilise ici le terme « décoration » pour parler de wrapper un composant autour d’un autre, et le terme « étendre » dans le sens de l’héritage. En fait je devrais dire « spécialiser » plutôt qu’« étendre ». Vous savez, dans l’héritage, on dit que la classe Chien étend la classe Animal, mais en fait elle la spécialise. Voilà comment ça s’applique aux composants. const Input = ({ type, name, value, placeholder }) => ( <div className="form-group"> <label htmlFor={name}>{humanize(name)}</label> <input type={type} id={name} name={name} value={value} className="form-control" placeholder={placeholder} /> </div> ); const TextInput = props => <Input {...props} type="text" /> const NumberInput = props => <Input {...props} type="number" /> const DateInput = props => <Input {...props} type="date" /> Imaginons que vous avez développé un composant Input pour afficher un champ de formulaire. Ce composant accepte notamment une propriété type, pour spécifier le type de champ à afficher. Eh bien, pour spécialiser ce composant, par exemple pour faire un champ TextInput ou NumberInput, la bonne pratique consiste à réutiliser le composant Input initial en le décorant, c’est-à-dire que le composant TextInput va déléguer sa logique au composant Input, mais en fixer une ou plusieurs propriétés. La plupart des langages utilisent l’héritage pour implémenter la spécialisation. Avec un moteur de composants, on utilise plutôt la décoration, qui est une forme Layout AppBar Sidebar Là où ça devient vraiment intéressant, c’est quand on combine cette décoration avec le conseil précédent. Par exemple, dans react-admin, on a un composant Layout qui affiche les éléments d’interface courants, comme la barre supérieure ou le menu de navigation.
  • 28. const Layout = ({ logo, title, userMenuContent, menuItems, sidebarWidth, }) => ( /* ... */ ); const MyLayout = props => <Layout logo={<AcmeLogo />} title="Acme Admin" userMenu={<AcmeUser />} menu={<AcmeMenu />} sidebarWidth={200} {...props} />; Definition Usage Pour configurer ces éléments, au départ le composant Layout exposait des propriétés comme logo, title, ou menuItems. Tellement de propriétés qu’en fait, ce composant Layout devenait difficile à utiliser et à maintenir. const AppBar = ({ logo, title, userMenuContent, }) => ( /* ... */ ); const Sidebar = ({ menuItems, width, }) => ( /* ... */ ); const Layout = ({ appBar = <AppBar />, sidebar = <Sidebar />, }) => ( /* ... */ ); const MyAppBar = props => <AppBar logo={<AcmeLogo />} title="Acme Admin" userMenu={<AcmeUser />} {...props} />; const MySidebar = props => <Layout menu={<AcmeMenu />} sidebar={200} {...props} />; const MyLayout = props => <Layout appBar={<MyAppBar />} sidebar={<MySidebar />} {...props} />; Definition Usage On a appliqué le premier conseil, et décomposé Layout en plus petits composants, comme AppBar ou Sidebar. Layout utilise à présent ces sous-composants dans son rendu, et l’utilisateur peut les surcharger via les propriétés de Layout. Maintenant, si j’utilise la décoration sur ces sous-composants, [clic] ça me permet de personnaliser le logo en décorant le composant AppBar en MyAppBar, ou de personnaliser le menu en décorant le composant Sidebar en MySidebar. Il ne me reste plus qu’à injecter ces deux composants décorés dans le layout, pour obtenir un composant MyLayout lui aussi décoré. Ou, pour utiliser une analogie facile, pour décorer un appartement, il faut décorer chacun des meubles de l’appartement. La décoration de sous-composants permet de présenter des composants simples, puissants, testables et configurables.
  • 29. C O N S E I L # 3 ~ L A I S S E Z V O S E N FA N T S T R A N Q U I L L E S Ce qui m’amène à mon troisième conseil: un composant ne doit pas regarder ce que font ses enfants ni décider ce qu’il doit faire en fonction de ses enfants. C’est une erreur très courante, mais qui crée plein de problèmes. Je vous explique. const PostList = props => ( <List props={...props} filters={<PostFilter />}> <Datagrid> <TextField source="id" /> <TextField source="title" /> <DateField source="publishedAt" /> <NumberField source="views" /> <ReferenceField source="authorId" reference="author"> <TextField source="lastName" /> </ReferenceField> <EditButton /> </Datagrid> </List> ); Revenons à la liste de contenus et à sa Datagrid. Dans cet exemple, comment la Datagrid va faire pour afficher les en-têtes de colonnes ? Le titre de chaque colonne vient de la propriété source des enfants de Datagrid, comme id, title, ou publishedAt. import { Children, cloneElement } from 'react'; const Datagrid = ({ records, children }) => ( <table> <thead> <tr> {Children.map(children, child => <th>{humanize(child.props.source)}</th> )} </tr> </thead> <tbody> {records.map(record => <tr> {Children.map(children, child => <td>{cloneElement(child, { record })}</td> )} </tr> )} </tbody> </table> ); La première idée qui vient à l’esprit est que le composant Datagrid itère sur tous ses composants enfants, lise leur propriété source, et l’affiche dans un header. Et ça marche. Mais…
  • 30. const TitleField = props => <TextField source="title" style={{ color: 'grey' }} /> const PostList = props => ( <List props={...props} filters={<PostFilter />}> <Datagrid> <TextField source="id" /> <TitleField /> <DateField source="publishedAt" /> <NumberField source="views" /> <ReferenceField source="authorId" reference="author"> <TextField source="lastName" /> </ReferenceField> <EditButton /> </Datagrid> </List> ); Si l’un des composants fils de Datagrid n’a pas de prop source - par exemple si on veut le décorer avec un autre composant pour lui donner un style particulier - eh bien cette approche ne marche plus. En fait, regarder ce que font ses enfants est une violation de la séparation des responsabilités. C’est le composant field qui devrait avoir la responsabilité d’afficher le titre ET le contenu d’une colonne, pas la datagrid. Donc il ne faut jamais qu’un composant inspecte ses enfants et prenne des décisions en fonction de leur nature ou de leurs propriétés. Au contraire, il doit déléguer le plus possible à ses enfants et les laisser faire. Vos enfants devront se débrouiller eux-mêmes, et vous ne pourrez pas l’empêcher - autant s’y habituer tout de suite. Mais revenons aux composants. Comment un composant peut-il afficher plusieurs choses différentes, comme une en-tête de colonne et le contenu d’une colonne dans l’exemple précédent ? C O N S E I L # 4 ~ AY E Z L E D O N D E D O U B L E V U E C’est mon quatrième conseil: il faut faire des composants qui savent se rendre plusieurs fois. C’est un pattern que nous utilisons régulièrement dans react-admin, et qui consiste à donner à un composant une double responsabilité.
  • 31. const Datagrid = ({ records, children }) => ( <table> <thead> <tr> {Children.map(children, child => <th>{cloneElement(child, { intent: 'header' })}</th> )} </tr> </thead> <tbody> {records.map(record => <tr> {Children.map(children, child => <td> {cloneElement(child, { record, intent: 'content' })} </td> )} </tr> )} </tbody> </table> ); const TextField = ({ intent, record, source }) => { if (intent == 'header') { return <span>{humanize(source)}</span>; } if (intent == 'content') { return <span>{record[source]}</span> } } Voilà comment ça marche. La Datagrid clone ses enfants deux fois, une fois pour le header, une fois pour le contenu, sans les inspecter. Pour le header, elle passe une intention « header », qui est un message qui dit à son enfant: dessine-toi dans le cadre du header. Pour le contenu, elle lui passe une intention « content », qui est un message qui dit à son enfant: « dessine-toi en dans le cadre du contenu ». En bas, vous voyez l’implémentation multi-intention du composant TextField. Et s’il est décoré, ça marche aussi, puisque la data grid ne regarde pas les props de ses enfants. const VisitorFilter = props => ( <Filter {...props}> <TextInput label="pos.search" source="q" alwaysOn /> <DateInput source="last_seen_gte" /> <NullableBooleanInput source="has_ordered" /> <NullableBooleanInput source="has_newsletter" defaultValue /> <SegmentInput /> </Filter> ); Dans react-admin, on utilise cette technique pour les filtres. Les filtres, c’est un composant qui définit les champs qui serviront à la recherche. Mais ces filtres doivent pouvoir apparaitre sous deux formes: lorsqu’ils sont activés, sous forme de champ de recherche, et lorsqu’ils ne sont pas activés, sous forme d’entrée dans une liste de filtres supplémentaires. Pour faire ça, le composant Filter clone lui aussi ses enfants deux fois, avec deux « intentions » différents. Ca lui permet d’éviter toute supposition quant aux capacités de ses enfants. Alors attention à ne pas abuser de cette technique, parce que parfois, cloner pour ce n’est pas rendre service. Certaines vérités ne doivent pas être montrées à tout prix.
  • 32. C O N S E I L # 5 ~ C U LT I V E Z L’ I S O L AT I O N Ces conseils permettent de faire des composants bien découpés, mais pas forcément bien découplés. C’est à l’usage que l’on se rend compte si l’API d’un composant, c’est-à-dire les propriétés qu’il s’attend à recevoir, sont pratiques. Et le meilleur moyen de s’en rendre compte, c’est de se forcer à utiliser chaque composant indépendamment des autres. import React from 'react'; import { shallow } from 'enzyme'; import { Pagination } from './Pagination'; describe('<Pagination />', () => { it('should display a limit when there is no result', () => { const wrapper = shallow(<Pagination total={0} />); expect(wrapper.find(‘pure(translate(PaginationLimit))')) .toHaveLength(1); }); it('should not display a limit when there are results', () => { const wrapper = shallow(<Pagination total={1} ids={[1]} />); expect(wrapper.find(‘pure(translate(PaginationLimit))')) .toHaveLength(0); }); }); C’est ce qu’on fait naturellement en faisant des tests unitaires. L’équivalent du test unitaire dans un framework de composants, ça passe par le shallow rendering: on ne fait pas un rendu complet, mais juste celui d’un composant, en mockant ses props et ses enfants. Ici, vous voyez le test unitaire d’un composant de pagination de react-admin, qui est normalement passé en fils d’un composant `<List>`. Ecrire des tests avec du shallow rendering, c’est donc un bon moyen de valider comment un composant se comporte en isolation. Un deuxième moyen, plus visuel celui-là, de tester des composants en isolation, c’est de les intégrer dans un storybook. Storybook, c’est le nom d’une librairie open-source qui permet de publier une liste de composants documentés de façon vivante, en utilisant le code qu’elle documente. Ici, vous voyez le storybook d’une librairie de composants de graphiques de données, qui permet de jouer avec les propriétés pour varier l’aspect ou le comportement. Storybook, c’est un super outil pour les équipes qui développent une librairie de composants, et pour les intégrateurs qui doivent utiliser ces composants.
  • 33. L’étape d’après, c’est d’intégrer cette bibliothèque de composants dans un éditeur visuel. L’outil que vous voyez ici s’appelle Framer X, et il utilise des bibliothèques de composants React. Quand je vous disais qu’un intégrateur pourrait utiliser des composants aussi bien qu’un développeur, c’est à ça que je pensais. Un dernier moyen de développer ses composants en isolation, c’est de monter une cage de faraday autour de votre bureau. Seul inconvénient : vous risquez de ne plus avoir accès à StackOverflow. Mais c’est quand même une solution à considérer, spécialement si vous préférez l’isolation des développeurs à celle des composants. C O N S E I L # 6 ~ E X P U L S E Z L E S E F F E T S D E B O R D Un jour ou l’autre, vos composants vont avoir des effets de bord, c’est-à-dire des effets qui sortent du périmètre du composant. Par exemple, dans une datagrid, le clic sur un intitulé de colonne peut déclencher un appel API pour récupérer les données triées selon le champ correspondant. Un bouton d’envoi de formulaire peut montrer une notification si le formulaire est invalide. Et si le formulaire est valide, l’effet peut être de changer de page pour aller sur la liste. Appels HTTP, notifications, redirections sont des exemples d’effets de bords, ou side effects en anglais. Et si vous gérez vos effets de bord directement dans le composant, adieu la portabilité.
  • 34. class Validate extends Component { state = { loading: false, } handleClick() { this.setState({ loading: true }) fetch(`/validate?content=${this.props.content}`) .then(() => this.setState({ loading: false })) } render() { <button onClick={this.handleClick} > {this.state.loading ? <SpinnerIcon /> : <ValidateIcon /> } Validate </button> } } export default Validate; Regardez sur cet exemple: un composant Validate permet de valider un contenu coté serveur en appellant une url « /validate » sur une API. Ici, l’effet de bord (c’est l’appel http via fetch()) est hardcodé dans le composant. Maintenant, imaginez si l’API exige que les appels soient authentifiés par un cookie JWT, ou si les routes sont en français… Dans ce cas, impossible de réutiliser le composant Validate. class Validate extends Component { handleClick() { this.props.fetchAPI(‘validate'); } render() { <button onClick={this.handleClick} > {this.props.loading ? <SpinnerIcon /> : <ValidateIcon /> } Validate </button> } } function mapStateToProps(state) { return { loading: state.loading } } function mapDispatchToProps() { return { fetchAPI } } export default connect(mapStateToProps, mapDispatchToProps) (Validate) La solution consiste à ne pas laisser un composants lancer des effets de bord. Au lieu de ça, les composants peuvent appeler des fonctions que leur passe leur parent pour envoyer des évènements à l’extérieur. on dit aussi dispatcher des actions (c’est ce que fait ici la fonction fetchAPI). Ca implique que vous utilisiez une librairie de gestion d’actions et d’état (ici, c’est Redux), et une librairie d’effets de bords compatible (pour Redux, ça peut être redux-thunk, redux-saga, ou redux- observables). La librairie de gestion d’effets de bord réagira à certaines actions pour déclencher des effets ailleurs dans l’application, et ces effets pourront être modifiés par le développeur (par exemple pour modifier l’URL à appeler). Mais tout Cette solution, c’est un peu celle qu’a adoptée Pablo Escobar, ici à gauche, pour diriger le Cartel de Medellin en 1991, alors qu’il était officiellement emprisonné par le gouvernement Colombien. Isolé dans un palais qu’il avait lui-même construit, il continuait à diriger le plus grand trafic de cocaine de tous les temps, en envoyant des messages…par fax. C’est son équipe qui s’occupait des effets de bord, comme le transport de drogue, la corruption, et les meurtres. C’est un bon exemple pour nous, les développeurs web: il faut faire des composants comme Pablo Escobar faisait du trafic de drogue : en déléguant les effets de bord.
  • 35. C O N S E I L # 7 ~ M E T T E Z D U S T Y L E D A N S V O T R E C O M P O R T E M E N T Dernier conseil - et celui-ci est plus controversé, puisqu’on parle de CSS in JS. Si vous stylez vos composants en leur mettant des classes qui font référence à une feuille de style globale, vous n’avez pas compris le principe des composants. Parce qu’il s’agit de pouvoir encapsuler à la fois logique et présentation dans un module autonome, réutilisable. <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/ bootstrap.min.css" integrity="sha384-MCw98/ SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous" > const ListButton = ({ resource }) => ( <Button className="btn btn-large"> <ListIcon /> Liste de {resource}s </Button> ) export default ListButton; Tenez, ici, avec cette approche, pour afficher un bouton à bords arrondis, je dois charger la feuille de style de bootstrap, qui me fournit les classes btn et btn-large. Donc non seulement le composant n’est pas utilisable sans la feuille de style, mais surtout j’oblige les utilisateurs à télécharger 141 kilos octets de CSS, dont 99% qui ne les concerne pas. C’est un peu comme si, pour réserver une table dans un restaurant, j’étais obligé de signer un contrat de 20 pages écrites dans un jargon juridique incompréhensible, dans lequel une clause écrite en Arial 6 garantit que les restes de mon repas seront conservés pour examen ADN en cas de non versement du pourboire. Je ne sais pas si vous vous acceptez ce genre de choses, mais moi non. Alors quand je fais des composants, c’est pareil: j’essaie de faire que chaque composant puisse être utilisé complètement indépendamment - y compris des feuilles de style.
  • 36. const ListButton = ({ resource, classes }) => { <Button style={{ display: 'inline-block', fontWeight: 400, textAlign: 'center', verticalAlign: 'middle', borderRadius: '.3rem', color: '#007bff', }}> <ListIcon /> Liste de {resource}s </Button> } export default Button; Dans sa plus simple expression, le CSS-in-JS consiste à mettre les styles directement dans le code des composants, comme ici en utilisant la propriété style. Là, on ne peut pas dire, c’est bien encapsulé. C’est aussi affreusement laid, et si vous avez vomi en voyant ça, sachez que ce n’est pas la solution que je préconise. Eh oui, parce que pour surcharger ce style-là, il va falloir mettre des ! important partout, et en plus les styles sont dupliqués à chaque utilisation du composant. import { withStyles } from '@material-ui/core/styles'; const styles = { button: { display: 'inline-block', fontWeight: 400, textAlign: 'center', verticalAlign: 'middle', borderRadius: ‘.3rem', color: '#007bff', } }; const ListButton = ({ resource, classes }) => { <Button className={classes.button}> <ListIcon /> Liste de {resource}s </Button> } export default withStyles(styles)(Button); Quand je dis CSS in JS, je pense plutôt à des librairies spécialisées, qui vous permettent d’éviter les styles inline. Ici, j’écrit le CSS dans le fichier du composant, mais in fine, les styles se retrouveront bien dans une feuille de style commune - recomposée par la librairie de CSS in JS au moment du build. Dans cet exemple, j’utilise JSS, qui est une librairie de CSS-in-JS intégrée à material-ui. Elle transforme des styles écrits en JS en classes CSS qui sont injectées dans le document HTML. Mon composant ne récupère que les noms de ces classes générées, qu’il peut utiliser dans son markup. Il existe plein d’autres solutions de CSS-in-JS alternatives à JSS: styled- import { withStyles } from '@material-ui/core/styles'; const styles = theme => ({ button: { display: 'inline-block', fontWeight: 400, textAlign: 'center', verticalAlign: 'middle', borderRadius: '.3rem', color: theme.colors.primary, } }); const ListButton = ({ resource, classes }) => { <Button className={classes.button}> <ListIcon /> Liste de {resource}s </Button> } export default withStyles(styles)(Button); Juste un exemple de ces fonctionnalités avancées : le theming. Ici, avec JSS, je choisis que la couleur du bouton n’est pas bleue, comme sur la page précédente, mais la couleur primaire du thème. Un développeur pourra, sans retoucher le code de ce composant, changer sa couleur en fournissant plus haut dans la chaine un thème personnalisé. Les librairies de CSS in JS s’occupent des préfixes vendor-specific, elles supportent les media queries, et permettent d’extraire les styles dans une feuille CSS externe à la compilation. Comme ça, les utilisateurs ne souffrent pas en termes de performance.
  • 37. Quand on découvre le CSS in JS, quand on goûte au style dans les composants, c’est un peu comme quand on regarde pour la première fois de sa vie une comédie musicale. Après ça, on n’arrive plus à voir un film où personne ne danse ni ne chante. C’est vrai, moi quand je regarde un film de Spiderman, j’attends le moment où Peter Parker va chausser ses claquettes pour montrer au Gobelin vert qu’avec quelques rimes et un peu d’amour, tous les problèmes se résolvent d’eux-mêmes. Et ça conclut ma liste de 7 conseils pour réussir ses composants. Avec les techniques que je viens de vous exposer, on a créé des composants domain- specific qui couvrent la plupart des besoins des applications d’administration. Le résultat, c’est qu’on développe des interfaces d’administration méga vite. React-admin est tellement rapide qu’il nous sert d’outil de prototypage: au lieu de faire des mockups sur Sketch, on les fait en React. Sauf qu’à la fin du prototypage, l’application est finie. Je me la pête, mais en même temps je viens de vous donner la recette pour faire la même chose, pour créer votre propre DSL avec des composants. Vous aussi, vous ou grâce à WinDev, mais c’est l’objet d’une autre conférence
  • 38. Age de l’application sans composants avec composants TEMPS D’IMPLÉMENTATION
 D’UNE FONCTIONNALITÉ Et au-delà du prototypage, le gros avantage des composants, c’est qu’ils offrent une productivité constante, quelle que soit la complexité de l’application, comme on le voit sur ce graphique totalement pas basé sur des données réelles. Avec n’importe quelle autre solution, plus une application est grosse, plus une évolution prend du temps à implémenter. Avec une approche par composant, ce n’est plus le cas. Les développeurs ont toujours la même vitesse de développement, au démarrage comme après 3 ans sur un projet. Et je ne le répèterai jamais assez, le gros avantage d’un composant, c’est que vous pouvez le remplacer par un autre de même forme. Tout comme vous pouvez utiliser une imprimante 3d pour créer vos propres formes de lego, dans une application construite avec une bibliothèque de composants comme react-admin, vous pouvez remplacer n’importe quel composant par le vôtre. A l’inverse d’un framework, une bibliothèque de composants ne vous limite jamais. - F R A N Ç O I S C H O L L E T « Good software makes hard things easy » Cette notion de composants est donc une bonne modélisation, puisqu’elle simplifie le développement et qu’elle ouvre plein de nouvelles possibilités.
  • 39. AFOCA D U LT FA N O F C O M P O N E N T S Voilà. Je pense que tout ça fait de moi officiellement un AFOC, un Adult fan of Components, et non pas AFOC A C R O N Y M E F R A N Ç A I S O U T R A G E U S E M E N T C A P I L L O T R A C T É un Acronyme Français Outrageusemnt Capillotracté. Non non, je suis bien un Adult Fan of Components, AFOCA D U LT FA N O F C O M P O N E N T S je suis bien un Adult Fan of Components,
  • 40. Pour nous les AFOC, collaborer sur un projet avec des composants développés comme ça, c’est un peu comme faire des legos en accéléré. C’est fun, rapide, super réactif, ça facilite la collaboration et l’invention. En fait, on n’a pas l’impression de travailler. Développer des applications web devient un jeu d’enfant. Alors, je ne peux que vous conseiller d’en faire autant. D É V E L O P P E Z D E S C O M P O S A N T S J O L I S D Y N A M I Q U E S A U T O N O M E S Q U I N E F O N T Q U ’ U N E C H O S E C O N F I G U R A B L E S PA R D ’ A U T R E S C O M P O S A N T S S A N S E F F E T S D E B O R D I N T E R O P É R A B L E S En conclusion, si vous ne devez retenir qu’une slide de ma conférence, c’est celle- ci. On y voit que j’ai parlé pendant 45 minutes pour pas grand chose en fait, mais c’était un plaisir de partager ça avec vous. Et si vous avez envie de jouer avec des composants qui sont déjà faits comme ça, je suis sûr que vous aurez bientôt un back-office à développer qui vous permettra d’essayer react-admin. Vous m’en direz des nouvelles ! François Zaninotto - @francoisz - Merci !