Pour ce NodeJS Paris S02E02, nous avons eu le droit aux joli amphis de l'école 42, avec ses poufs multicolores (et inconfortables). Pas de dossier, donc pas très pratique de prendre des notes.
Comme d'hab, on rappelle le but du meetup (on parle de javascript en général, et de node en particulier). Présentation du site web, de comment proposer des talks, etc, etc.
Puis se sont enchainés plein de sponsors, beaucoup trop. Si encore il y en avait eu un ou deux, j'aurais pu écrire quelques mots sur chacun mais là il y en avait bien trop. Le meetup commençait officiellement à 19h, mais je pense que le premier orateur n'a pas du prendre la parole avant 20h au moins.
En vrac, Marceau Innovation (qui n'a pas beaucoup innové pour trouvé son nom) qui aide des français à partir s'installer à la Silicon Valley. Captain Dash (qui ont un très joli logo), qui font de la dataviz à partir des données des clients. Puis Digital & You dont je n'ai rien compris au pitch. Et puis je crois qu'il y avait encore d'autres sponsors ensuite mais franchement j'ai arreté de suivre.
On a quand même ensuite pu commencer les choses sérieuses, et tant mieux car le programme était très intéressant : Cassandra, Testing Asynchronously, Breaz.io et Freelance Academy.
Cassandra
Présentation de Duy Hai Doan, évangéliste chez Datastax, l'éditeur de Cassandra. Je ne connaissais pas grand chose à Cassandra mis à part que c'était une DB NoSQL. Je vais donc essayer de récapituler ce que j'en ai compris, parce que ça avait l'air bien !
Donc Cassandra, ou C* pour les intimes, a été créé chez Facebook avant d'être open-sourcée en 2008. C'est une base dont le point fort est la scalabilité linéaire : il suffit de rajouter des nœuds pour scaler. Ils visent un uptime de 100%, même pendant les upgrades. Elle est actuellement utilisée par Netflix et possède un principe de multidatacenter out of the box, avec des facilités pour déployer sur Amazon.
Autre avantage mis en avant : la simplicité opérationnelle. Il n'y a qu'un seul processus Java et un fichier de config.
On a eu ensuite droit à un exemple de fonctionnement. Imaginons que Cassandra tourne avec un cluster de X nœuds (8 étant le nombre utilisé dans l'exemple), alors chaque donnée est enregistrée sur un des X nœuds, grâce à un hash qui permet de toujours pointer vers le même nœud pour la même donnée. Si jamais notre charge augmente, on a juste besoin d'ajouter des nouveaux nœuds et les nouvelles données seront réparties sur plus de nœuds.
Pour assurer un bonne tolérance aux pannes des nœuds, la donnée de chaque nœud est répliquée sur les deux nœuds voisins. Ainsi, si un nœud tombe, sa donnée n'est pas perdue et peut être récupérée depuis les deux nœuds voisins. Pour assurer un maximum de cohérence, à chaque requete un nœud est dédié à une tâche de coordinateur, pour indiquer sur quel nœud la donnée peut être trouvée.
Il est possible de définir pour cela trois niveaux de cohérence : ONE, QUORUM ou ALL. Ces règles s'appliquent autant pour la lecture que pour l'écriture.
En mode ONE, on envoie l'écriture de la donnée aux trois nœuds qui peuvent la stocker et dès que l'un des trois l'a enregistré, on rends la main. Les deux autres nœuds l'enregistreront aussi, mais plus tard, et c'est le plus rapide qui rends la main.
En mode QUORUM, on attends qu'une majorité stricte ai validé l'enregistrement avant de rendre la main.
Et en ALL, on attends bien sur que tous les nœuds aient enregistré la donnée.
En lecture en ONE, on va aller lire sur le nœud le moins chargé au moment de la lecture (chaque nœud garde en local une table de statistique de temps de connexion aux autres nœuds, et celui qui a la latence la plus basse sera choisi en priorité).
En lecture QUORUM, on va lire depuis un des nœuds aléatoirement, mais les deux autres nœuds vont nous donner un hash de la donnée. Si les hashs concordent, on rends la main. Sinon le coordinateur var récupérer la bonne donnée sur le nœud qui l'a mise à jour le plus récemment, et va mettre à jour les deux autres nœuds.
Le langage de requête est très proche du SQL en terme de syntaxe, mais ce n'est pas du SQL, c'est du CQL. La primary key de chaque donnée sera son hash, ou clé de partition.
Oui mais tout ça c'est bien beau, mais c'est quoi le rapport avec NodeJS ? Ben juste qu'il existe un driver nodejs pour Cassandra.
Ce qui est couteux en Cassandra c'est l'ouverture des connexions à la base, du coup le driver va maintenir des pools de connections ouvertes sur chaque nœud (2 par nœud). Le driver est optimisé pour paralleliser les requêtes pour en lancer plusieurs sans avoir à attendre le retour de chacun.
Il est possible d'identifier un ensemble de requêtes par un unique streamID, et pouvoir ainsi récupérer toutes les réponses en même temps, de manière à faire de grosses économies en terme de latence. J'avoue que j'ai un peu moins bien suivi cette partie.
Le driver est au courant de la topologie du cluster (nombre de nœud, latence, etc). Des events sont lancés quand un nœud tombe ou revient à la vie. Il a des fonctionnalités de load-balancing entre plusieurs data-center par défaut. Il s'assure aussi que les connections vers les nœuds ne timeout pas. Si une connection part vers un nœud mais que celui-ci est tombé, alors plutot que de renvoyer une erreur le driver va réutiliser la même connection pour renvoyer la même requête vers un autre nœud porteur de la même donnée. La requête sera certes plus lente, mais elle ne sera jamais tombée en timeout.
Coté code, ça signifie créer un Cassandra.Client en lui donnant l'ip ou l'adresse de quelques nœuds du cluster, et il se chargera de découvrir tous les autres et dresser la topologie complète du cluster. On lui envoie ensuite nos requêtes en CQL, et on obtient un callback quand les données sont revenues. Comme souvent, pour économiser les temps de traitement, on donne notre requête sous forme de string avec des placeholders pour qu'elle soit optimisée derrière au moment de la jouer.
Vu qu'on est en node, le driver est aussi capable de streamer les résultats renvoyés. En interne il utilise un principe proche du cookie, pour se souvenir de sa place dans le stream et rejouer à partir de ce point. Dans les faits cela permet de continuer un stream même quand le nœud émetteur est tombé, on peut simplement continuer la même requête sur un autre nœud. Grâce au cookie, on reprends le flux au même endroit. Par contre, si on écrit plus vite dans les données qu'on est en train de les lire, le cookie ne nous permettra pas de voir tout.
Cassandra fournissant plus de types de donnée que ne le permet Javascript, le driver fourni aussi des helpers pour passer ces types complexes en Javascript.
Après ce long exposé très intéressant, on a eu le droit à quelques questions/réponses. Quelques limitations du driver actuel ont été soulevés comme par exemple le fait que les opérations comme des count ou des sommes sur la data ne peuvent pas être faite directement dans Cassandra. Il faut récupérer la donnée et effectuer cette opération dans le driver. Les prochaines versions du driver devraient corriger ce soucis.
Async is hard, test it harder
Après ça, Florent Jaby est venu nous parler de tests en NodeJS, et plus particulièrement de tests de code asynchrone.
Le sujet des tests en Javascript est assez bien documenté, mais quand on en vient à tester de l'asynchrone, il y a tout à coup beaucoup moins de littérature disponible.
Bon, on commence rapidement par rappeller les fondamentaux de pourquoi on teste : boucle de feedback plus rapide, non-regression et design émergent. Un bon test est isolable et reproductible.
Sauf que derrière tout ces beaux principes on a quelques soucis en Node. Il est difficile de savoir quand un test se termine vu que tout est asynchrone. Est-ce que mes requêtes sont pending ou est-ce qu'elles vont bientot arriver ? Est-ce que tout ce que j'ai lancé est bien revenu ? Est-ce que je termine mon test ou j'attends plus longtemps ?
Et puis surtout, on a un problème de stacktrace avec l'event loop de node. A chaque itération on est dans un contexte différent, du coup les mécanismes classiques de try/catch ne fonctionnent pas. On a plusieurs approches pour contourner ce problème.
On peut par exemple déclarer manuellement la fin du test comme le fait Tape ou NodeUnit. On appelle une méthode .end() pour signifier qu'on a assez attendu et qu'il est temps de terminer le test. Mocha propose aussi une méthode done à appeller quand le test est censé être terminé.
Une autre méthode est de planifier les assertions. On prévient qu'il va y avoir x assertions, et on les mets directement dans les callbacks. Du coup, le test s'arrete automatiquement dès que les x assertions sont sorties.
On peut aussi passer par des domaines, pour wrapper nos appels. On peut faire des try/catch dessus et donc attraper les exceptions et balancer un done quand ça arrive pour marquer la fin du test. Ca marche bien, ça nous donne les bons rapports d'erreurs sur les bons tests, mais c'est pas très lisible.
Un moyen un peu meta de rendre tout ça plus lisible est de modifier la méthode it pour qu'elle wrappe son contenu dans un trycatch/domain. Ca nous fait revenir à une syntaxe plus lisible.
La fin du talk était plus sur les outils annexes aux tests comme jshint ou istanbul. JSHint n'est plus à présenter et permet d'appliquer des règles configurables de standard de code à appliquer et de vérifier les erreurs de syntaxes et les pitfalls communs de Javascript.
Istanbul de son coté est un outil de couverture de code qui va nous sortir de beaux rapport indiquant les lignes de code qui sont parcourues quand on lance nos tests. On peut comme ça voir les parties du code qui ne sont pas testés. Ca permet de voir ce qu'il reste à tester, ou même parfois à identifier du code mort. Il calcule aussi la complexité cyclomatique du code, qui donne une estimation de la difficulté à le maintenir (globalement s'il n'est pas modulaire, avec des méthodes de 100+ lignes et des if imbriqués, c'est mauvais signe).
Finalement, Florent termine par un conseil à ceux qui testent des streams. Ne perdez pas de temps à tout tester, les streams sont très bien testés en interne dans NodeJs, inutile de le faire. Il n'est nécessaire que de tester la méthode pipe, ce qui rentre et ce qui sort. On mets tout dans un buffer et on test à la fin.
Breaz.io / Developers in tech
Je vous renvoie à mon compte-rendu des HumanTalks précédent, Jean-loup y a donné à peu près le même talk.
Freelance Academy
Et pour finir, Etienne Folio nous a parlé de la société de coaching de freelance qu'il vient de monter. Il est lui même passé freelance plus tôt dans l'année et peut se targuer d'avoir un TJM à 4 chiffres, tout en ne travaillant que 6 mois par an.
Il a monté Freelance Academy avec la promesse d'aider les développeurs qui veulent se lancer en freelance mais qui ont peur du légal, de l'administratif, de la compta, de trouver des clients, etc. Il propose un stage de coaching de quelques semaines, suivi d'une année complète de formations (quelques jours par mois). Tout ça gratuitement. Il s'engage même à payer la différence de revenu entre le freelance et le salariat pour ceux qui se lancent, assurant à chacun un revenu au moins égal à celui qu'il avait en CDI.
On a été plusieurs à se demander où était l'arnaque. En fait, c'est tout simplement que si jamais le nouveau freelance gagne plus que son ancien salaire, il repaye la différence à Freelance Academy. Il est assuré de toucher autant en un an que ce qu'il gagnait avant, mais l'excédent n'est pas pour lui pendant un an. Ensuite, libre à lui de continuer son activité de freelance avec son nouveau TJM.
L'idée est intéressante, et le freelance, bien fait, peut être très agréable. Néanmoins, le coté "je te donne un cadeau et oh, tu l'a accepté maintenant tu m'est redevable" me rebute dans son histoire. Mais pour en avoir discuté avec lui ensuite, il vise essentiellement les développeurs qui ont peur de se lancer, qui disent vouloir faire du freelance depuis des années mais qui n'ont jamais laché la facilité du CDI. Avec l'assurance du salaire qu'il propose, il espère pouvoir leur donner confiance.
En tout cas, ça m'a fait me rendre compte que je faisais du freelance n'importe comment quand j'en faisais :)
Hier soir, comme tous les deuxième mardis de chaque mois, c'était les HumanTalks. Cette fois, c'était Criteo qui accueillait l'évenement. On a eu le droit à 4 présentations, précédées d'une petite présentation de Criteo.
Criteo fait de la publicité, et sachant que c'est pas la chose qui excite le plus les développeurs, ils se présentent surtout comme une boite de techos, avec une stack de technos hétéroclite et sexy. Ils annoncent aussi très clairement qu'ils payent très bien, mais qu'ils ont un process de recrutement très difficile. C'était clair, c'était franc, et on a rapidement enchainé sur la première présentation.
Developers in tech
Présenté par Jean-loup Karst de breaz.io, un site de recherche d'emploi pour développeurs. Breaz "mets aux enchères" 7 à 10 développeurs par mois, dont les profils sont alors accessibles aux entreprises enregistrées. Les entreprises sont filtrées pour n'accepter que celles qui proposent de vrais produits techs (pas de SSII, pas d'agence, pas de gros comptes). Le développeur se fait alors contacter par les entreprises qui sont intéressées par son profil.
Du coup, breaz a pas mal de stats sur les technos qui sont actuellement le plus recherchées, en back-end comme en front-end, et a pu nous faire un état des lieux. Les statistiques énoncées représentent une sélection de 100 sociétés parisiennes, créées depuis 2008, qui produisent une produit tech, donc elles ne sont clairement pas représentatives du parc mondial des applications actuellement en production.
On remarque que c'est toujours PHP qui est demandé majoritairement, avec Python, Node et Rails ensuite. Rails a subi une explosion en 2010 avant de redescendre progressivement, alors que Node au contraire a connu une montée à la même période. Java était complétement absent du panel quand à lui.
Coté front-end, c'est sans surprise qu'on trouve Angular, Backbone et Ember majoritairement comme framework MVC. jQuery garde une place de choix dans la majorité des projets aussi.
A noter que si on compare ces statistiques aux chiffres mondiaux, englobant toutes les sociétés et tous les produits actuellement en production, on arrive à des données complétement différentes. Node, Ruby, Angular et Backbone, ici très bien représentés, ne parviennent même pas à 1% du parc mondial historique.
Dans les questions-réponses qui ont suivi, il ressort que les profils qui ont un Github actif sont plus contactés que les autres. Pour l'entreprise cela est synonyme de passion, de curiosité, et d'une facilité à apprendre rapidement des langages différents.
Convaincre en quelques secondes
Le talk suivant, de Richard Hanna, était intitulé "Comment convaincre en quelques secondes".
Il conseillait de ne pas faire confiance à l'adage comme quoi l'habit ne fait pas le moine. Pour lui, si on est mal habillé, notre interlocuteur va le remarquer, alors que si on est bien habillé, c'est notre personnalité qu'il va remarquer. On juge de manière inconsciente sur les vêtements, le costume.
Il nous propose ensuite de regarder ses interlocuteurs dans les yeux, et de sourire, afin de leur donner confiance. Se répeter mentalement 3 fois "Super, super, super" avant de prendre la parole pour être souriant.
Faire attention au langage corporel. Les bras fermés sur le torse est un signe de protection, on cherche à cacher quelque chose, ce qui peut donner à penser qu'on n'est pas honnête. Il faut chercher à avoir un langage corporel proche de celui de notre interlocuteur, de manière à le faire se sentir à l'aise. Il ne s'agit pas là de singer ses mouvements, mais de prendre la même posture sur une chaise par exemple.
Dans la formulation des idées, attention aux tournures négatives, préférer les tournures sans ambiguité. Par exemple, ne pas dire "C'est pas mauvais, il ne devrait pas y avoir de problème", mais préferer "C'est bien, tout va marcher parfaitement".
Gérez vos processus avec Kanban
Antoine Roux nous a fait un état des lieux et un retour d'expérience de la méthodologie Kanban, qu'il mets en pratique dans sa société depuis 4 ans.
En tant que développeur, notre métier est de produire des applications où chaque nouvelle feature va apporter quelque chose de plus à l'utilisateur. Du coup, il nous faut réussir à trouver un processus qui nous permette de nous concentrer sur cet apport de valeur, de l'optimiser, et d'avoir un moyen de répondre à la sempiternelle question "Pour quand est-ce que ça sera prêt ?".
Ces questions, elles ne sont pas spécifiques au monde du developement informatique. Toyota s'est déjà posé les mêmes questions, et a donc mis en place la méthodologie Kanban, qui lui a permis de devenir le premier constructeur auto. Les américains ont repris la technique sous un nom différent, le lean.
Le principe primordial est qu'on tire le flux du travail. Les phases en aval du processus vont tirer les phases amont. On ne commence rien tant qu'un n'a pas une demande client, et l'effet secondaire positif est qu'on ne crée pas de stock. On se concentre sur apporter de la valeur au client.
On a souvent dans nos projets des demandes qui n'avaient pas été prévues au démarrage. Dans le Kanban, ça fait partie intégrante du processus. On accepte ce changement et on le prends en compte, tout est tourné autour de ce principe.
Alors de manière concrète, comment est-ce qu'on mets ça en place ? C'est pas bien compliqué, il suffit d'avoir un mur, des post-its, du scotch et un marqueur. On créé trois colonnes sur le mur : Todo, Doing, Done.
Nos tâches sont forcément dans l'une de ces trois colonnes. Rien qu'avec ça on a une vue d'ensemble des tâches de notre projet. Tout ce qui n'est pas dans le Kanban n'est pas dans le process, et tout ce qui est dans le process est dans le Kanban. En un coup d'oeil on peut voir si on est sous l'eau ou si tout va bien. En utilisant un vrai mur physique plutot qu'une application, tout le monde voit le même mur, tout le temps.
À partir de là, on peut améliorer en ajoutant de nouvelles colonnes qui correspondent à de vraies étapes du processus de la société. Par exemple, des colonnes backlog, dev, code review, QA, deploy, done. Mettre une colonne est très importante. La QA c'est pas quelque chose à faire faire par une autre équipe, la qualité fait partie du processus. Ce qui est livré, donc arrivé dans la colonne done est fait avec qualité. La colonne deploy est aussi importante, pour forcer l'équipe à aller le plus loin possible vers les utilisateurs finaux.
Prochaine étape d'amélioration est d'ajouter les DOD (Definition of Done) entre les colonnes pour que les actions actions à réaliser pour passer d'une colonne à une autre soient claires. Les afficher sur le mur permet à tous les nouveaux arrivants de rapidement comprendre comment fonctionne le processus.
Mais là où on commence vraiment à faire du Kanban by the book, c'est quand on ajoute la notion de WIP (Work In Progress). On indique une limite au nombre d'éléments dans une colonne, et en aucun cas cette limite ne peut être déplacée. S'il n'y a pas la place pour passer un item, il faut alors concentrer tous les efforts pour faire baisser ce WIP, en tirant les tâches vers la droite pour les amener en done.
L'analogie qu'il donne est celle de l'autoroute. Si toutes les voitures de l'autoroute sont concentrées au même endroit, tout avance lentement. Au contraire, si elles sont espacées, elles peuvent toutes aller à leur vitesse maximum. En limitant le nombre de tâches possibles en parallele, on s'assure qu'elles soient terminées plus rapidement.
Afin d'isoler les possibles goulot d'étranglement, on fait un Stand-Up Meeting tous les matins pour voir les points de blocage et s'il y en a, on mets la priorité sur leur résolution avant toute autre chose.
Si toutes nos tâches ont environ la même complexité, on peut très facilement estimer la durée moyenne de résolution d'une tache et donc planifier une date d'atterrissage du projet. La difficulté arrive quand on a des tâches aux complexités très différentes. Le plus simple est de commencer par découper les grosses tâches en plusieurs tâches de taille plus petite. Les grosses tâches ont la facheuse tendance à rester bloquées en Code Review très longtemps parce que personne n'a envie de faire la Code Review d'un gros morceau de code.
Le gros avantage du Kanban est qu'il s'adapte à des processus existants, qu'il ne faut qu'un mur et quelques post-its pour commencer, et qu'on n'est pas obligé de tout prendre dès le début, on peut ajouter les éléments au fur et à mesure.
Très très bonne présentation, j'ai enfin compris ce qu'était réellement Kanban.
Des personnes dans l'assistance ont confirmé que cela fonctionnait très bien pour des équipes de support, ou de TMA, pour des listes de questions à répondre, etc.
JHipster
Dernière présentation à base de live-coding par Julien Dubois, créateur de JHipster.
JHipster est un générateur d'application Java/Angular, basé sur Yeoman. C'est open-source, y a plein d'étoiles et de forks sur GitHub et y a même des projets en production qui l'utilisent.
Le J de JHipster est pour Java, et il vient avec une base de Spring (Spring Boot, Spring Security, Spring Data JPA), du cache, du clustering, des websockets. Le Hipster, c'est pour Angular, Grunt, Bower, HTML5 boilerplate et Twitter Bootstrap qui font la couche de front.
L'une des force de JHipster est l'ensemble d'outils qui viennent avec. Coté Java on a le choix entre du Maven ou du Gradle et coté front c'est Grunt ou Gulp, au choix.
En termes pratiques, on lance un yo jhipster dans le terminal, on réponds à quelques questions (SQL/NoSQL, Gradle/Maven, Grunt/Gulp, Java 7/8, etc) et il nous prépare une application complète avec tout le tooling déjà configuré. pom.xml, Grunfile.js, package.json, bower.json, tests unitaires, tout est là.
On n'a plus qu'à lancer un petit coup de maven pour avoir un beau war executable qui contient tout le code back et front (minifié) prêt à être déployé. Il contient même tout un tas de fonctions de generator pour créer des tables dans la base de données et les classes qui vont bien avec, ainsi que les possibles relations entre les objets.
On a aussi accès à une interface d'administration qui nous donne toutes les fonctions de CRUD basiques pour opérer sur nos objets, ainsi qu'une page de monitoring de la JVM.
C'était vraiment bien pensé, ça m'a presque donné envie de faire du Java.
Conclusion
Comme d'habitude, une très bonne session HumanTalks suivie de discussions passionantes autour de pizzas et de sushis. Les HumanTalks c'est tous les deuxième mardis de chaque mois, dans plusieurs villes de France. S'il y en a près de chez vous, je vous invite à aller y faire un tour.
Pour Septembre, c'est Mozilla qui a bien voulu accueillir les HumanTalks. Au programme, 4 talks, dont le dernier par votre serviteur. On commence par une explication de la polémique "TDD is dead" de DHH, suivi d'une présentation d'un mode de développement type hackathon, puis une présentation de RxJava.
TDD is (not really) dead
Présenté par Nicolas Mérouze, qui nous parle de la fameuse phrase de DHH, "TDD is dead". Ce qu'il voulait dire par là c'est qu'il y a mieux que de faire du TDD (ie. des tests unitaires avant d'écrire le code), il est préférable de faire des tests d'acceptance avant d'écrire du code. Comme ça on ne teste pas les rouages internes de comment ça marche, mais on teste directement que ça marche.
Les tests d'acceptance sont des tests en black box, sans connaitre l'implémentation. On vérifie juste que le comportement attendu s'execute. On continue d'écrire nos tests avant le code, mais on fait des tests beaucoup plus génériques. On rajoute des tests unitaires quand la logique individuelle devient compliquée, mais cela devient l'exception et non la règle.
Les tests d'acceptance prennent des tables d'inputs en entrée et vérifient les outputs. On fait passer les mêmes tests, mais sur des jeux de donnée différents. Ca commence à attendre ses limites quand il y a plein de variations, on ne peut pas tout rejouer à chaque fois, il est alors plus intéressant de faire des tests plus spécifiques et donc de revenir aux tests unitaires.
Les tests d'acceptance n'autorisent pas non plus les mocks, on teste le système dans son ensemble. Là encore, si un mock est nécessaire, on retourne aux tests unitaires. Mais le propos principal était qu'il vaut mieux commencer par tester au plus large, et si vraiment le besoin s'en fait sentir redescendre aux tests unitaires, mais pas l'inverse, cela fait gagner du temps.
Globalement le propos de la présentation était un peu compliqué à comprendre. Il a fallu plusieurs questions de l'audience pour que je comprenne vraiment de quoi il retournait.
Coder en mode commando
Evan Genieur nous a parlé d'une méthode de travail qu'il est en train de tester. Il veut travailler uniquement avec des passionnés, sur des laps de temps courts, et dans des endroits sympathiques.
Pour ça il s'inspire du principe des (bons) hackathons, où pendant quelques jours une bande de passionés part de rien pour produire quelque chose. Pas besoin de penser à se faire à manger, ou de devoir rentrer chez soi, tout est fourni directement pour qu'on puisse se concentrer sur le projet à rendre.
Il propose donc aux entreprises, généralement des start-ups, ou pour des POC de plus grosses sociétés, de prendre 4 jours au vert avec 4-5 personnes dans des maisons louées sur AirBnB.
Les projets réussis sont fait par des gens qui sont passionnés par ce qu'ils produisent, qui croient en sa valeur, et qui le comprennent. Pour ça il faut améliorer la colocalisation, mettre les devs, les designers et les clients dans la même pièce pour itérer rapidement et obtenir du feedback. Rester travailler tous les jours au même endroit, avec les mêmes personnes n'aide pas à devenir créatif. Par contre créer une bulle d'efficacité autour du projet en le protégeant de toutes les interférences extérieures, et en lui donnant le maximum de potentiel permet d'obtenir des livrables très rapidement.
Il teste encore plusieurs compositions d'équipe, plusieurs durées, mais ce qui semble pas mal fonctionner actuellement ce sont des équipes de compétences diverses. Un développeur senior pour prendre les décisions techniques et profiter de son experience dans les choix, mais qui ne code pas forcément beaucoup. Un jeune développeur, qui généralement restera à travailler sur le projet après l'opération commando, qui va coder et prendre en main le projet. Et un développeur intérmédiaire, qui est là pour faire la liaison entre les deux, s'assurer de la qualité du code, servir de référent au junior. Un chef de projet, pas forcément technique, mais qui connait le métier doit impérativement aussi être là et être logé à la même enseigne que le reste du groupe.
Sur chaque run, il faut compter une demie-journée de brief au démarrage et une demie-journée de debrief à la fin. Le but n'est pas forcément d'avoir un produit fini à la fin du run, mais d'en avoir fait le maximum en un temps limité, pour profiter de cette bulle de compétence et de passion.
Deux jours, le format hackathon traditionnel est trop court. En deux jours on a le temps de faire un POC, mais pas de faire les finitions pour qu'il puisse évoluer. 5 jours, c'est à dire une semaine complète c'est trop long, on s'essoufle et on n'en fait pas plus en 5 jours qu'on ne puisse en faire en 4. La durée optimale pour le moment selon lui est de 4 jours, ce qui laisse 3 jours de dev complet et 1 journée de brief/debrief.
La règle d'or est le "No Bullshit". Tout le monde doit faire bien son job, être transparent sur ce qu'il fait et avoir une vision de ce que font tous les autres. On vit et on travaille au même endroit, cela crée des liens. Ce n'est pas adapté à tous les développeurs, certains ne peuvent pas travailler avec une piscine qui leur temps les bras à coté, d'autres apprécient de piquer une tête de temps en temps pour se rafraichir les idées et retourner bosser ensuite. Il faut trouver les profils qui s'épanouissent le plus dans ce genre d'atmosphère. Le but est de créer un moment unique, pas comme d'habitude, dépaysant, et d'être au maximum "in the zone".
J'ai beaucoup aimé cette manière de travailler. Je sais que je travaille mieux quand je suis dans un endroit étranger (ni chez moi, ni dans un bureau), et que je n'ai pas à m'occuper des événements annexes (téléphone, trajet retour, pause déjeuner, réunions, etc). Perso, j'aimerai beaucoup participer à ce genre d'initiative.
RxJava
On repasse sur quelque chose de moins funky, une présentation de Brice Dutheil et David Wurteisen sur RxJava.
Je m'excuse d'avance si je massacre le contenu de la présentation, mais ne faisant pas de Java (ni de reactive) les informations restaient assez abstraites pour moi.
RxJava est une implémentation en Java des reactive extensions. Initiées à la base par Microsoft, puis open-sourcées, elles ont ensuite été reprises par Netflix dans leurs systèmes.
L'idée principale est que la plupart de nos appareils aujourd'huis possèdent plusieurs cœurs, qui executent leurs traitement chacun dans leur coin mais qui doivent réussir à les faire communiquer d'une manière uniforme, comme si ces résultats venaient d'une seule et même source. Le même principe s'applique dans un réseau quand une réponse est en fait un aggrégat de réponses de plusieurs systèmes. La manière principale de communication dans un tel système est une communication par événement.
RxJava fournit une abstraction élégante, composable, flexible et puissante sur ce système. On peut manipuler des séquences d'évenement, quelque soit leur source (réseau, calcul, interaction UI de l'utilisateur) et les traiter comme s'il elle venaient toutes d'une même source et réagir sur leurs événements. RxJava permet de filtrer, merge, effectuer du map/reduce sur ces séquences.
Concatenate, Compress, Cache
Il est assez difficile de faire un compte-rendu de son propre talk, du coup je vous invite à regarder la vidéo ou consulter les slides.
Pour une fois, le compte-rendu n'est pas de moi car cette fois-ci j'étais de l'autre coté, en tant que speaker. Remerçions dont Benjamin Brabant pour ce superbe compte-rendu.
Timothée pour son premier talk en meetup nous a fait une super présentation, pratique, claire et abordable, des bonnes méthodes à suivre pour optimiser basiquement les performances de son application Web.
Pourquoi parler de performances ? D'après des études, la lenteur d'une application était ressentie au bout de 4 secondes en 2008, elle l'est au bout de 3 secondes en 2014 ce qui dénote bien les enjeux en termes de performances sur le web. La nouvelle génération née dans la ferveur technologique du 21ème siècle n'a pas connu les modems 56k contrairement à ses ainés. Elle est habituée à l'instantané et est donc bien moins patiente !
Serveur
Tout d'abord on évoque les optimisations que l'ont peut faire de manière générale du côté serveur. En trois mots :
Concatenate
Compress
Cache
Contatenate
Objectif : Télécharger le moins possible
Télécharger plus de fichiers engendre des coûts incompressibles qui entrainent un goulot d'étranglement dû à :
Latence DNS
TCP Slow-start
Overhead SSL
Nombre maximum de connections parallèles
Une simple inspection des flux réseau depuis son navigateur permet de voir rapidement ceux qui appliquent ces guidelines (ex: france.fr 18 CSS / github.com 2 CSS) !
Compression
Objectif : Télécharger des fichiers plus léger
GZip
GZip est un outil disponible sur tous les serveurs et compris par tous les navigateurs du marché (IE5.5+). Le gain de compression est de 66% en moyenne. Très simple à configurer sur les serveur (Apache, Lighttpd, nginx) qui ont des modules adéquats.
Techniquement, cela consiste dans le header à ajouter un encoding particulier qui va permettre aux navigateurs de savoir quoi faire
Minification
Une autre méthode consiste à minifier les fichiers. Cette méthode est spécifique au langage et consiste globalement à de la suppression, mutualisation, obfuscation du code. Quelques outils pour cela :
CSS : cleancss
JS : uglifyjs
HTML : html-minifier
Cache
Objectif : Télécharger moins souvent
Consiste à définir une date limite de consommation. Ainsi le navigateur ne renverra pas la requête au serveur si la fraîcheur est bonne et récupérera le résultat dans son cache. Deux headers :
Expires: Thu, 04 May 2014 20:00:00 GMT : ne pas utiliser car tous les clients vont invalider leur cache en même temps
Cache-Control: max-age=3600, must-revalidate : utiliser en priorité puisqu'on définit cette fois une durée
Validation
La validation consiste à vérifier que le client possède la dernière version :
Oui : 304 - Not Modified
Non : 200 - OK
Deux headers :
Last-Modifier: Mon, 04 May 2014 02:28:12 / Ìf-Modified-Since : A utiliser en priorité, fonctionne bien
ETag: "3e86-410-3596fbbc" / If-None-Match : Les serveurs se basent généralement sur le inode qui, si les ressources sont placées derrière un load balancer par exemple, va retourner un tag différent pour chaque serveur pour un fichier pourtant identique sur tous. Ce problème peut se résoudre en ajoutant quelques configuration supplémentaires pour le serveur
Invalidation
Pour invalider le cache, une méthode sûre consiste à renommer les fichiers assets à chaque modification en utilisant un tag dans le filename.
D'autres parts, le header de requête Pragma : no-cache permet de demander une version non cachée de la ressource. NB : Ce header dans la response du serveur ne sert à rien.
Images
Les images pèsent lourd sur une page web (plus de 50% du poids global) et font 800Ko en moyenne. Pour les sites web faisant un usage de photos intensif, suivre les quelques préconisations suivantes peuvent apporter un véritable gain en performance. Le premier conseil donné est d'utiliser essentiellement seulement les formats :
JPG pour photographie
PNG pour logo et éléments du template
SVG si besoin particuliers
Compress
Lossless
La première compression qui n'entraine pas de perte de qualité consiste à supprimer les métadonnées des images telles que :
Orientation, exposition, flash, focale
Date, GPS
Modèle appareil
Aperçu, historique
Tags, commentaires
L'outil exiftool permet de consulter et parfois manipuler les métadonnées pour un grand nombre de formats. L'outil jpegtran permet de manipuler les images JPG et notamment leurs métadonnées.
jpegtran -optimize-copy none
Lossy
Cette fois, la compression entraine une suppression d'informations de l'image en elle-même et donc une dégradation de la qualité. Généralement une compression à 80% est raisonnable.
jpegoptim -m80--strip-all
NB : L'option strip-all supprime également toutes les métadonnées.
Sprites
Les sprites (dont le nom provient de la technique utilisée pour l'animation des premiers jeux vidéo) consiste à regrouper plusieurs images (logos et icones généralement) sur la même image. On joue alors sur le background position pour afficher la bonne image.
La balise <script> lorsqu'elle est interprétée par le navigateur bloque complètement le parsing du reste du document. En effet, la fonction document.write, tombée en désuétude maintenant, permettait de modifier la page courante et obligeait donc le navigateur à charger les scripts tout de suite.
Solutions :
Mettre les balises <script> en bas de page
Attribut defer de la balise <script> qui permet de les définir en entête et de laisser le navigateur les placer à la fin pour nous. Malheureusement, IE ne suit pas la spécification et n'offre aucune garantie sur l'ordre d'exécution des scripts.
Attribut async permet de charger les scripts en arrière-plan n'offrant aucune garantie sur l'ordre d'exécution.
Une bonne méthode consiste également à essayer de séparer les scripts par priorité (un premier contenant les scripts liés aux éléments clés de la page, le second concernant par exemple la pub, le tracking, le sharing)
Il faut être bien conscient que JavaScript est un langage interprété. Le code écrit est donc celui qui va être téléchargé et exécuté. On a donc tout intérêt à le maintenir le plus petit possible pour des raisons de performance au chargement et à l'exécution. Par exemple, attention aux instructions que l'on va masquer par un attribut booléen DEBUG et qui vont être malgré tout interprétées par le navigateur. Dans la mesure du possible, supprimer tout code inutile en production.
Le site microjs.com se révèle être un bon outil pour trouver de très petites librairies (pour chacune le poids est clairement indiqué) répondant à nos besoins tout en ne surchargeant pas la page.
CSS
Les feuilles de style de dérogent pas à la règle d'optimisation. Il est nécessaire de comprendre certains mécanismes sous-jacents à l'application des styles pour être conscient de l'impact que cela peut avoir sur les performances.
La modification d'une propriété va déclencher l'une des deux opérations suivantes :
repaint : consiste à changer la couleur des pixels de l'écran.
reflow : entraine le recalcul complet de la page. Lorsqu'on redimensionne un bloc par exemple, ce mécanisme est inévitable.
Pour maximiser les performances, il faut limiter au maximum les reflow. Le site csstriggers.com permet de savoir pour chaque propriété si sa modification entraine un repaint ou un reflow.
Pour limiter les reflows, on peut suivre ces quelques guidelines :
CSS en haut de page
Insérer dans le DOM en "batch"
Taille des images indiquées dans le HTML permet d'éviter un reflow à chaque nouvelle image à afficher
Préférer le border transparent qui change de couleur plutôt que d'ajouter un border qui nécessite un reflow
Parseur
Le parseur CSS est contre intuitif. Lorsqu'il rencontre une balise, il va chercher dans les règles CSS les éléments qui matchent en regardant de droite à gauche chaque définition CSS. Le mieux est donc d'avoir les éléments de droite le plus spécifique possible.
Bonnes pratiques :
utiliser des classes plutôt que des Tags
pas plus de trois niveaux
pas de sélecteur universel .menu * (sauf tout seul)
pas d'expression régulière d'attribut a[href^="http://"]
ne pas négliger la lisibilité de son code CSS (sachant que les optimisations du CSS n'ont un réel impact qu'à partir de plusieurs milliers de propriétés)
Perception
La perception humaine de la vitesse d'une page et à prendre en compte absolument. Il consiste en règle général à utiliser quelques subterfuges donnant une sensation de rapidité à l'utilisateur et repose sur un affichage progressif des éléments de la page. Pour cela :
startRender rapide
Configurer les JPG en mode progressif avec jpegoptim
Utiliser des placeholders
LazyLoading pour n'afficher que ce qui se voit à l'écran
Les géants du web n'hésitent pas à "tricher" en utilisant des techniques faisant illusion que le chargement est rapide !
Feedback en avance (Instagram)
Illusion d'optique (Dans GMail, les pixels de début et fin de la barre de progression n'ont aucun lien avec l'avancement du chargement mais sont là pour faire illusion que ça avance)
Firefox entre ses releases a accéléré la vitesse de son spinner de chargement pour donner une impression de meilleures performances au fil des nouvelles versions
Facebook après un sondage s'est rendu compte que les utilisateurs qui avait le spinner iOS pour le chargement reportaient la faute de lenteur sur Apple contrairement à ceux qui avaient le spinner de chargement Facebook
Ce week-end il y avait une Gamejam organisée chez Mozilla. Je n'avais jamais fait de gamejam avant, vu que la plupart du temps il faut savoir coder sous Unity. Cette fois-ci, c'était différent et tout tournait autour d'un framework en javascript nommé redwire. En plus, les co-organisateurs sont des amis.
Toutes les conditions étaient donc réunies pour que je participe enfin à ma première gamejam.
Redwire est un système de programmation qui réplique le principe d'un circuit électronique, et qui fonctionne en mode drag'n'drop. On y manipule des if, des loops et un ensemble d'inputs et d'outputs. Pour être honnete, je n'ai pas réussi à rentrer dans le framework. J'avais envie d'écrire mon propre JS et CSS, pas de passer par les cases pré-établies du système.
Le créateur était là, et était d'une grande aide pour sauver les équipes qui étaient bloquées. Il était plus ou moins le seul à connaitre le système, sa logique, ses tweaks et ses bugs.
Redwire est quand même fondé sur un principe de modularité très intéressant. Idéalement il est possible de récupérer des briques de gameplay d'un jeu pour les incorporer dans un autre. On a donc divisé notre week-end en une phase d'apprentissage du framework, la construction de briques individuelles, et l'assemblage de ces briques pour en faire des jeux complets.
Afin d'éviter de partir dans trop de directions, on a limité le nombre de types de jeux à trois : text-based, shooter et puzzle game.
Les jeux finaux qui en sont sortis étaient bourrés de bonnes idées, malheureusement leur réalisation était assez pauvre. Même si j'ai passé plus de temps à coder le site que vous êtes actuellement en train de lire plutot que d'essayer Redwire, j'ai quand même passé un bon moment.
Ci-dessous, mes notes sur les différentes briques et les jeux en résultant que j'ai prises à l'issue de la première journée.
SHOOTER
Ennemi téléporteur, à intervalle peut disparaitre et revenir à un autre endroit.
Ennemi cloneur. A intervalle régulier, va se dédoubler.
Ennemi Kamikazer. Fonce vers le personnage principal directement.
Sortir d'un coté, rentre d'un autre.
Mur d'obstacle qui fait tout l'écran, avec 3 couleurs et 3 sons. Son qui indique la couleur à passer.
Clic, tir vers la direction de la souris.
Bouclier de protection, protège autour de la souris.
Power Down, fait doubler la taille du joueur.
Touche appuyée, attire les ennemis, relache pour projeter.
Labyrinthe circulaire et pivotant dont les murs sont mortels.
Bonus qui multiplie par trois le personnage (3x plus fort)
Ennemi aléatoire qui droppe un loot aléatoire.
Ennemi au comportement évolutif (zigzag, spirale)
Deux vaisseaux, touche et souris
Boites bonus aléatoires
TEXT-BASED
Boite de dialogue. Portrait, texte, trois réponses.
Mot apparait, temps limite pour le taper sur le clavier.
Suite de mots dans le désordre, à remettre dans l'ordre.
Mots qui disparaissent dans un bloc de texte, 1 toutes les 2 secondes.
Dans un bloc de texte, certains mots, si on les tape, on gagne des points.
Choix multiples
Mémorisation des choix dans le passé du jeu
Affiche la touche de controle qu'on appuie. Si mur, bloque, si ennemi, appuyer sur touche attaque.
Pierre-Feuille-Ciseau
Tooltip sonore
Twister au clavier
Spam d'une touche pour monter une entitée, si arrete de spammer, redescends
Background qui réagit aux pressions du clavier
BLOCK PUZZLE GAME
Blocs avec lettre, tape sur lettre, le fait disparaitre.
Grille 5x5, clic dessus, disparait et ceux au-dessus descendent.
Grille dont les carrés changent de couleur quand on passe en hold dessus.
Blocks à l'écran, touches de clavier dédoublent dans la direction indiquée.
3x3 avec un bloc de libre, faire glisser dans la case vide pour former l'image
Deux joueurs Tetris, l'un modifie les blocs avant que l'autre ne le recoive.
TECHNIQUE
Tileset + matrix = image canvas finale
Entrée texte avec choix multiple, retour un integer du choix
X joueurs, pour que l'équipe gagne il faut que chaque joueur se soit spécialisé dans une compétence et en soit expert
MES FAVORIS EN FIN DE PREMIERE JOURNEE
Mur d'obstacle qui fait tout l'écran, avec 3 couleurs et 3 sons. Son qui indique la couleur à passer.
Touche appuyée, attire les ennemis, relache pour projeter.
Labyrinthe circulaire et pivotant dont les murs sont mortels.
Deux vaisseaux, touche et souris
Boite de dialogue. Portrait, texte, trois réponses.
Mot apparait, temps limite pour le taper sur le clavier.
Suite de mots dans le désordre, à remettre dans l'ordre.
Mots qui disparaissent dans un bloc de texte, 1 toutes les 2 secondes.
Dans un bloc de texte, certains mots, si on les tape, on gagne des points.
Affiche la touche de controle qu'on appuie. Si mur, bloque, si ennemi, appuyer sur touche attaque.
Spam d'une touche pour monter une entitée, si arrete de spammer, redescends
Blocs avec lettre, tape sur lettre, le fait disparaitre.
Grille 5x5, clic dessus, disparait et ceux au-dessus descendent.
Grille dont les carrés changent de couleur quand on passe en hold dessus.