QCon London 2014, day Two
06 Mar 2014Groupon, breaking up the monolith
Groupon a commencé petit, avec une belle appli rails dans les règles de l'art. Mais leur codebase a rapidement explosé en même temps que la boite grossissait, c'est à dire, beaucoup et très vite. Ils ont du faire une appli mobile très rapidement et rajouter une couche d'API en facade de l'appli Rails. Puis ils ont racheté une boite qui faisait la même chose qu'eux mais pour la partie hors-US et se sont donc retrouvés avec deux fois le même set de features mais implémentées de deux manières différentes.
Bien sur, avec deux codebases différentes les features n'évoluaient pas de la même manière aux US que dans le reste du monde. De la même manière, faire évoluer l'appli mobile voulait dire faire évoluer le site principal. Avec autant de systèmes différents faire la moindre évolution mettait le système dans des états instables.
Ils avaient en cours un grand projet de modification du look and feel de leurs sites, mais réussir à propager celui-là partout en même temps était impossible. Certains utilisateurs voyaient le vieux Groupon, d'autre le nouveau.
Ils se sont donc mis dans un grand projet de refactoring de tout ça. Ils ont pris plusieurs mois pour tout refaire from scratch et... n'ont jamais réussi.
Ils ont alors pris une autre approche. Leur but était de découper l'appli principale en plusieurs petites applis. Ils ont commencé par extraire toute la procédure de signup dans un site externe, tout en utilisant l'API mobile.
L'appli de signup a été écrite en nodejs, et est toute petite, environ 15 fichiers en tout. Il y a eu quelques cafouillage lors de la mise en prod, mais rien de dramatique. Et surtout, vu que l'appli ne concerne que quelques pages, les problèmes étaient assez localisés.
Finalement cette première expérience porte ses fruits, ils veulent le faire sur une autre partie. Ils demandent alors à une autre équipe de réecrire une autre feature avec la même stack technique, histoire de tester si les choix techniques sont cohérents. Cette fois-ci, la modification a été plus longue, 6 mois au lieu de 2 semaines, car elle nécessitait des modifications de l'API qui à leur tour demandaient de la modification du legacy.
Après cette étape, ils passent à la vitesse supérieur et entament plusieurs chantiers en parallele. Chacun d'eux prends une feature et la transforme en une appli nodejs. Plusieurs équipes, à plusieurs endroits du monde, travaillent avec la même stack. Ils en profitent pour mettre au point un framework interne pour simplifier la cohérence des devs et créer la documentation qui va avec.
Là, ils décident de revoir le CSS et de faire un bootstrap-like interne pour que le look and feel de toutes les pages soit cohérent. Il est assez facile de mutualiser une feuille de style, mais il était plus dur de garder une cohérence en terme de mise en page quand plusieurs équipes, plusieurs designers font leurs pages chacun de leur coté.
Ils optent pour une modularité sous forme de components. Chaque équipe écrit des components (html/css/js) qui peuvent être inclus dans des pages et un serveur central abrite la liste des différents templates de page existants, dans lesquels ils peuvent inclure leurs components. Cette méthode leur permet de garder une cohérence dans les différentes pages, tout en laissant un peu de liberté aux designers pour ne pas être toujours bloqués dans les mêmes templates.
Ils testent plusieurs méthodes pour assembler les templates avec les components, et finalement parviennent à une solution à base de templating mustache et de chargement des components coté client en javascript.
Une fois que leurs chantiers parallele ont fonctionnés, ils ont bloqué la production pendant 2 mois (sauf pour les bugfix) afin de finir de casser l'appli rail originale en apps nodejs. Ca leur a pris plus de temps que prévu car ils avaient plus de pages qu'ils ne le pensaient.
Concernant l'API, ils ont du garder une extreme retro-compatibilité car des tas d'applis externes en dépendent. Néanmoins ils ont développé une couche d'abstraction qui prends les anciennes urls en entrée et les passent à la nouvelle API. Ils monitorent l'usage de chacune des anciennes urls et les enlevent au fur et à mesure qu'elles ne sont plus utilisées.
Un side effect bonus qu'ils ont découvert avec cette manière de splitter en plein de petites applications c'est qu'il leur est alors très facile de faire une feature spécialisée pour certains pays qui sont culturellement très différents. Ce n'est de toutes façons qu'une quinzaine de fichiers, qui prennent environ 2 semaines à développer. Si une app prends plus de 2 semaines, c'est qu'elle est trop grosse, et il faut alors la splitter.
Take-away : - Inutile de reprendre un monolithe from scratch - Trop dur de tout découper en une fois - Isoler une feature atomique, la refaire à part - Tester si marche pour une autre feature, avec une autre team - Itérer au fur et à mesure que la confiance vient - Assurer la rétrocompatibilité de l'API - Mesure pour enlever ce qui ne sert pas au bout d'un moment.
Tools and techniques for managing complexity at Etsy
Encore Etsy, et leurs méthodes magiques. Cette fois, le talk était accès sur leur manière de scaler (aussi bien en terme d'utilisateur, de taille de la codebase, ou de taille de leur équipe).
Tout d'abord, ils axent tout sur le partage. Partage en open-source de leurs outils, partage des dashboard ou des logs accessibles à tout le monde, employés qui changent d'équipe pour 1 mois chaque année.
Ensuite, ils déploient régulièrement, et font de petits commits. Chaque changement est donc assez peu impactant, et c'est donc plus facile de corriger ou de changer de trajectoire.
"You write it, you run it". Chacun est responsable de deployer la feature sur laquelle il a travaillé, de mettre en place les dashboards pour monitorer.
Vu qu'ils font de la feature flipping à mort, et qu'ils ont près de 300 "pages" principales différentes sur leur site (sans parler des version admin, identifié, membre, vendeur), ils ont calculé avoir approximativement 1.200.000 pages possibles différentes.
Avec le temps, le nombre de CSS et de JS augmente considérablement et ils ne savaient pas comment trouver du code CSS mort dans leur application. La méthode manuelle était de chercher un selecteur, trouver dans quel fichier il était défini, trouver tous les fichiers qui @import ce css, puis les templates html qui incluent ce css, et les template qui incluent le template, pour remonter aux fichiers PHP puis aux règles apache... Bref, impossible à maintenir.
Ils n'osent pas supprimer du code sans savoir les impacts. Mais garder du code mort ça fait de l'overhead, aussi bien mental pour le développeur, que pour le cpu lors de la compilation ou le réseau.
Ils ont donc construit un outil nommé Shrinkray qui tourne en live dans le navigateur des visiteurs. Il va prendre 10 selecteurs CSS au hasard dans les feuilles de style chargées, et regarder si elles matchent quelque chose sur la page en question. Ces informations sont ensuite envoyées au serveur d'Etsy qui aggrège des stats là dessus qu'ils peuvent consulter et ainsi isoler le "vrai" code mort.
Pour eux, le browser du client fait partie intégrante de leur architecture et ils l'utilisent comme cela.
Maneuverable architecture
Notre speaker nous a parlé de James Boyd, un pilote d'avion de combat durant la guerre qui avait une manière de piloter très spéciale et peu commune. Il ne voulait pas l'avion qui va le plus vite ou le plus haut, mais celui qui peut plus facilement tourner.
La métaphore porte sur le fait que "sans maitrise, la puissance n'est rien". L'idée est qu'il est très important de pouvoir réagir vite aux inputs exterieurs et que cela peut donner un avantage important sur les concurrents.
Il enchaine sur le fait que la meilleure manière de pouvoir manoeuvrer rapidement est de ne pas avoir une appli monolithique mais une multitude de petites applis qui peuvent être maneuvrées independemment.
Pour évoluer rapidement, ne pas se focaliser sur les détails. Pas la peine d'avoir une api avec des endpoints super bien mappés. Urls are cheap. On peut en créer plein pour s'adapter aux différents besoins même si plusieurs urls pointent au même endroit. Il suffit d'avoir des logs sur les utilisation des urls pour savoir quand on peut en dégager une du code si elle n'est plus utilisée.
Pour gérer les différences de pays (i18n, différences légales et culturelles), ils ont une liste de components visuels d'UI générique, tweaking par une liste de features flippés du moment qu'une est nécessaire pour un cas précis, sa spécificité est ajoutée à la liste des options flippables pour tout le monde.
Ils versionnent leurs components, et laissent toutes les versions dispos en ligne en même temps. Comme ça, chaque site de leur portail peuvent utiliser la dernière version d'un component lors de leur conception et ne pas avoir besoin de gérer l'upgrade du component central automatiquement, c'est du opt-in quand ils veulent uploader il leur suffit de changer l'url.
Il utilise les URL pour absolument tout, des fichiers statiques jusqu'au versionning de ses FAQ, toutes les versions de tout ce qui est versionné est toujours disponible sur leur réseau à tout moment. Ainsi chaque objet possède un identifiant unique et un nom pointe toujours vers exactement la même chose immutable.
Il pousse le "vice" plus loin, en donnant par exemple le cas des paniers des sites d'e-commerce. Chaque panier est unique, avec un certain identifiant. Plutot que d'avoir un panier personel lié à un utilisateur, il a une liste de paniers, chacun avec un identifiant unique et une combinaison d'articles dedans, ainsi chaque utilisateur possède seulement une référence vers un panier. Cela permet d'avoir des objets complétement différents, indépendants.
Il donne ensuite un exemple de comment il a découplé un système d'envoi de mail de rappel d'expiration de carte bleu en plusieurs systèmes : un qui register des taches CRON à une certaine date et une certaine URL, un autre qui prends une date et retourne une date interessante pour envoyer un mail (genre pas le week-end) et finalement un autre service qui envoie le mail.
Globalement son idée est bien foutue et fonctionne globalement comme un pipe, avec une vraie separation of concerns. Malheureusement, ça peut facilement être mal fait et partir dans trop de couches d'abstraction qui rendent le système difficile à comprendre et maintenir.
Hoodie, Offline first
Hood.ie est un framework dont le but est de faciliter le mode offline. L'idée est que nos devices mobiles ne sont pas toujours connectés, il y aura toujours des métros, des tunnels, des zones non-connectées. On passe sans cesse d'un mode connecté à un mode non-connecté.
Pour hood.ie, l'appli est pensée pour être offline, l'online est une feature. Dans les applis d'aujourd'hui, le mode offline n'est pas toujours pensé, on a des spinners qui tournent indéfiniment pour rien.
On peut utiliser le cache manifest des browser pour définir les objets qui doivent être gardés en offline et ne doivent pas etre cherchés online. Le système possède encore pas mal de problèmes qui le rendent difficile à utiliser.
Par la nature même du cache manifest, il est difficile de mettre à jour les éléments qu'il cache. Il faut mettre à jour le cache manifest lui-même (par exemple en ajoutant un commentaire de timestamp). Même si l'appli est actuellement connectée, le cache manifest ira toujours chercher ses données en offline. Et si on est offline, un asset qui n'est pas défini dans le manifest (même s'il est en cache), ne sera pas affiché. Tout ça sans parler qu'il faut recharger deux fois le manifest pour que sa mise à jour soit prise en compte.
Autre solution, il y a les serviceWorkers qui commencent à arriver, qui permettent de se plugguer sur les events du navigateur, pour par exemple accrocher un event fetch pour télécharger une ressource externe et ainsi implémenter sa propre logique de cache.
La définition même de "online" est douteuse. Est-ce que ça veut dire connecté à un réseau wifi ? 3G ? Quid des proxy, ou des limitations de forfait data ? Et si c'est juste le serveur et/ou la ressource en question que je souhaite contacter qui est inaccessible ?
Sous Firefox et IE par exemple, il existe un event pour savoir si on passe en offline ou non, sauf qu'il est fired quand on passe manuellement le browser en mode offline. Chose que personne ne fait jamais.
Il existe un workaround qui consiste à se plugguer sur toutes les requetes AJAX de son appli et de capter les timeout et de passer alors l'appli en mode offline. A partir de ce moment, on arrete de faire des requetes, on tente juste, régulièrement, de poller le serveur pour voir s'il est à nouveau accessible et repasser en mode online.
Il faut bien que je garde mes données en local quand je suis offline. On peut bien sur mettre ça dans un cookie, mais c'est une extremement mauvaise idée car il y a une limite à la quantité de data qu'on peut y mettre et surtout, les cookies sont renvoyés au serveur à chaque requete.
Il y a localStorage et son API simple à base de setItem(key, value) et getItem(key). C'est simple, ça marche partout. Mais c'est synchrone, et ça bloque mon UI quand je m'en sers, et ça se remarque vite quand je traite de grosses data. Et puis surtout, ça ne peut stocker que des strings, donc obligé de convertir en JSON et parser à chaque fois. Sans parler de la limite de taille, d'environ 5Mo, et qu'il n'y a aucun moyen de savoir si on a dépassé ou non la limite.
Maintenant, on a indexDB, qui est asynchrone, et qui fait des transaction atomiques. En plus on peut stocker des objets directement et la limite de taille est bien plus grande (~50Mo). L'API est plus complexe, et les implémentations sont différentes selon les browsers.
La solution est d'utiliser localForage, un wrapper développé par Mozilla qui permet d'utiliser indexDB avec la syntaxe simple de localStorage, tout en gérant les fallbacks.
Hood.ie est parti sur du CouchDB, car il propose une très bonne synchronisation master/master, ce qui est parfait pour une synchronisation entre un client et un serveur qui sont tous les deux sources de données principales.
Avec Hood.ie, chaque utilisateur possède sa propre base de donnée CouchDB, donc la synchronisation se fait vraiment entre deux objets qui sont liés à un unique utilisateur. Parfois des objets sont partagés entre plusieurs nœuds serveur, et dans ce cas c'est le serveur qui se charge de faire la synchro entre les nœuds (copier les nouvelles versions des objets dans les bases de chacun), les bases sont ensuite synchronisés avec les clients.
L'idée principale pour la synchro est d'avoir la même schéma de stockage en local et sur le serveur, avec un protocole particulier qui permet de faire la synchro. Au dela de PouchDB/CouchDB, il existe aussi JsGit, qui permet d'implémenter le protocole git pour versionner ses données et les pusher/puller avec un serveur.
Au niveau de la sécurité, aucune vérification n'est faite pour les modifs en local, c'est seulement une fois qu'on effectue la synchronisation que le serveur vérifie l'authentification.
Comment gérer les conflits ? En fait, il faut les éviter. L'idée est d'avoir plein d'objets (documents) différents plutot que de gros objets pour éviter et simplifier les conflits. Par exemple , si on souhaite gérer un blog avec ses posts et les commentaires associés, il vaut mieux avoir un objet pour le post, et un autre pour la liste des commentaires, sinon deux utilisateurs peuvent poster un commentaire en même temps et avoir un conflit sur le post.
Il est très important de montrer à l'utilisateur que les données sont accessibles, il faut éviter au maximum de cliquer sur quelque chose et d'avoir un spinner infini qui apparait.
Il faut aussi que ce soit transparent, il ne faut pas que l'utilisateur ait besoin de faire des actions spécifiques pour enregistrer quelque chose pour l'offline (exemple typique, les FAQ/Docs qui sont souvent fetchées depuis le site web dans une app).
Garder un maximum de choses en localStorage, pour accelerer les calculs et rendre l'UI smooth. Si besoin de fetcher quelque chose, le faire en tache de fond, quand l'utilisateur ne le voit pas.
Attention, mettre ses données dans les mains de l'utilisateur en local fait repenser l'architecture en terme de sécurité des données.
Mobile webperfs : Getting and Staying fast
Le mobile devient de plus en plus important, le nombre de sociétés qui possèdent désormais plus de visiteurs en mobile qu'en Desktop ne cesse d'augmenter. Le mobile est devenu un first class citizen, et il faut en prendre soin.
On s'attends à ce qu'un site soit aussi rapide sur mobile que sur desktop, voir plus. On se repose sur le fait que les téléphones sont de plus en plus rapides, ont de plus en plus de RAM, qu'on passe de EDGE à la 3G, puis la 4G.
Mais la 4G n'est pas la solution ultime. Il y aura encore plus rapide dans le futur, et tout le monde n'aura pas la même connection. Il y a aujourd'hui plus de cartes SIM en circulation au Royaume-Uni que d'habitants. Ajoutons à cela la diversité des devices, et on a un panel extremement large et on ne peut pas se contenter de développer pour le haut du panier en terme de vitesse.
La latence est le principal problème pour la performance en situation de mobilité. Même dans une situation parfaite, avec de la fibre optique, la data est limitée par la vitesse de la lumière, un round-trip jusqu'à un serveur à l'autre bout du globe ne pourra jamais dépasser la vitesse de la lumière, ou plus pragmatiquement les 2/3 de la vitesse de la lumière avec nos infrastructures actuelles.
Niveau mobile, la 4G améliore la latence par rapport à la 3G, mais un bottleneck se créé au niveau des fournisseurs d'accès. Plus il y a de personne sur le réseau 3G, plus la vitesse de download est dégradée pour chacun. La latence est aggravée en situation mobile du fait du protocole employé par la 3G. Le fournisseur d'accès régule la latence réseau sur son propre réseau, et pas au niveau du device, il peut donc se passer une à deux secondes avant qu'une requete envoyée par un téléphone ne parte réellement de celui-ci.
Rajoutons à tout cela que TCP n'est pas adapté à une multitude de petits fichiers, et que les réseaux wifis généralement accessible en situation de mobilité (Starbucks, conference room) sont rarement au top, on a un panel de situation de surf sur mobile qui est assez noir.
La grande question est donc : comment est-ce qu'on mesure les performances web dans ces conditions ?
Heureusement, on commence à avoir des outils assez évolués pour regarder pas à pas le chargement de notre page et repérer les problèmes. Les browsers (modernes) implementent désormais la navigation API ou la Resource Timing API qui donnent beaucoup de metrics sur les différentes étapes de rendering de la page depuis les premières connection réseau jusqu'à la première intéraction utilisateur possible en passant par les différentes phases de rendering. Une plateforme comme NewRelic permet même de visualiser tout cela en mode Saas.
Le bon vieux WebPageTest reste encore l'outil priviliégié pour visualiser le chargement de tous les assets d'une page en mode waterfall, incluant le temps de résolution DNS, de connection, de traitement serveur et de téléchargement. Les bottlenecks sont alors extremement facile à repérer et les optimisations sautent au yeux. Le site webpagetest.org permet de faire des tests sur son site depuis différents endroits du globe avec des qualité de connection variées.
Dans le même genre, Appurify se concentre sur la connection mobile. Leurs serveurs de tests se situent à San Francisco mais ils ont moyen de simuler la qualité d'une connection mobile sur par exemple du Vodafone UK, avec la possibilité de choisir la qualité de réception d'une à cinq barres, ou de simuler un réseau moisi comme celui offert par un Starbucks en periode d'affluence.
Pour tester en situation réelle, les Chrome DevTools permettent de brancher son Android sur son laptop et de le controler depuis celui-ci. Il est ainsi possible d'y brancher la console de debug de chrome et d'étudier le comportement du chargement des pages.
A noter aussi qu'un outil comme Charles peut s'insérer en tant que proxy entre le device mobile et le réseau wifi sur lequel il se connecte et peut ajouter de la latence à la demande pour simuler un réseau mobile.
S'en sont suivis des exemples de quelques sites de "gros" acteurs qui prennent un temps monstrueux à se charger sur mobile, comme nbcnews et ses 19s de chargement, 344 assets sur 115 domaines différents.
Et donc, dans tout ça, quelles sont les solutions ?
La solution la plus facile est déjà tout simplement de réduire la taille de la page. L'objectif est d'avoir une page, assets compris, qui pèse moins de 300Ko. pour ça, on passe par du Gzip qui est un gain instantané sur tous les assets textes (js, css, html). En quelques lignes de config serveur on peut déjà gagner près de 80%.
Pour réduire la taille des images il existe pas mal d'outils d'optimisation. Une simple passe d'ImageOptim sur un fichier jpg permet en général de gagner 50% de taille de fichier sans que la différence sur l'image ne soit perceptible par un œil humain. Les choses se compliquent quand on souhaite prendre en compte les problématiques de responsive webdesign, mais le sujet pourrait avoir sa propre conférence tellement il est complexe.
D'autres amélioration qui peuvent etre faites sur les images sont d'utiliser SVG quand cela est possible, ou des iconfont. Il est souvent aussi possible d'utiliser du CSS plutot qu'une image de fond (pas toujours, certains dégradés demandent plus de travail par le browser que le simple affichage d'une image).
Enfin, il faut faire attention quand on charge des webfonts, il y a de nombreuses façons de le faire mal et de charger trop de fonts non-utilisées, ou devoir attendre l'execution d'un script. Il est à noter que l'utilisation de webfont est à double tranchant : tant que la font n'est pas chargée, aucun texte n'est lisible. Certaines fonts sont très lourd à charger car elle contiennent les glyphes d'alphabets dont vous n'aurez jamais besoin (cyrillique, grec, etc). Réduire la font au subset des glyphs qui vous interesse permet de gagner en général près de 33% sur la taille du fichier
Ce qui me permet d'enchainer sur le second point d'amélioration principal : diminuer le nombre de requetes. Le protocole HTTP est fait de telle manière qu'il y à l'initialisation une congestion window qui force le browser à effectuer plusieurs round-trip avant de pouvoir faire son téléchargement à vitesse maximale. Les détails de cette partie restent encore un peu flou pour moi (HTTP ? TCP ? où se situe le bottleneck ?). Mais cela signifie qu'il existe un sweet spot, une taille de fichier maximale que le client peut télécharger en un seul round-trip. Il y a moyen de configurer cette valeur (initcwnd
) sur son serveur assez facilement. La valeur par défaut est généralement à 3, et a majorité des CDN le montent à 10, il est donc recommandé de mettre soi-même cette valeur à 10 pour en profiter.
Une fois que tout ceci est fait, il faut tirer partie du cache. La règle d'or est : Cache all the things. Que ce soit coté serveur ou coté client, il ne faut pas hésiter à cacher un maximum de choses pour éviter les requetes réseaux.
Enfin, une fois qu'on est arrivé là, que nos assets sont bien arrivés dans notre client, le dernier point que l'on peut optimiser est le rendering. Certains élements de notre page bloquent le rendering, c'est à dire que rien ne va s'afficher tant qu'ils ne se sont pas executés. Le javascript est le premier sur la liste, c'est pour ça qu'on recommande de mettre les scripts en fin de page et d'attendre le body.onload pour initier leur traitement. Mais comme je disais au dessus, il y a aussi les fonts, qui empechent l'affichage du texte sur lequel elles sont définies tant que le fichier de font n'est pas chargé.
Si vous avez bien tout réalisé jusqu'ici, votre page a du se charger plutot bien. Mais maintenant, votre utilisateur va changer de page et... tout ce processus va recommencer à zéro ? bien sur, avec un bon cache, pas mal de choses seront déjà là, mais il existe quelques autres astuces qui permettent d'anticiper les changements de pages. Les browsers commencent à mettre à disposition du developpeurs des outils comme dns-prefetch, subresource, prefetch et prerender qui permettent de donner des indices au browser sur ce que l'on pense que la prochaine action de l'utilisateur va etre, pour que lui puisse mieux organiser de son coté les ressources qu'il va charger.
Si on prends un peu de recul sur le coté technique, il y a encore des astuces qui permettent d'améliorer non pas la vitesse de chargement de votre page mais la perception qu'en ont les utilisateurs.
Déjà, si vous faites comme le Guardian, vous chargez en premier le contenu de votre page, ce pour quoi vos utilisateurs viennent (le titre et le texte de l'article par exemple), puis vous chargez la mise en forme, en seulement en dernier le reste (analytics, pubs, boutons de partage). Vous pouvez aussi jouer avec le fold, et ne charger que ce que l'utilisateur voit réellement sur son écran, et ne charger le reste (commentaires, etc) que s'il scroll.
Le site mobile d'Instagram va même plus loin, en trichant sur le feedback visuel. Dès que vous cliquez sur un bouton, il change d'aspect pour indiquer que l'action a réussie, même la requete n'est même pas encore partie au serveur. De la même manière, ils commencent à uploader la photo que vous venez de prendre pendant que vous écrivez son commentaire, comme ça, dès que vous appuyez sur Send, ça semble instantané.
Et finalement, comme le disent si bien les Animaniacs : "If in life you don't succeed, blame it on your parents". C'est ce qu'à fait Facebook. Ils ont utilisé le spinner du téléphone plutot que leur spinner custom car leurs tests montrent que comme ça les utilisateurs pensent que c'est la faute du téléphone et pas la faute de l'appli.
En quelques lignes, le take-away de tout ça : - Measure. Measure. - Send less bytes - Prioritise what you send - Send it when no-one is looking - If else fails, distract the visitor
Continuous Improvement Version Constant Innovation
Basically there are two main issues with Continuous Improvement. Continuous and Improvement
L'amélioration n'est pas assez. Blackberry améliore depuis des années mais son produit reste globalement le même. L'amélioration n'est pas l'innovation, cf. iPhone.
Ca part d'un postulat négatif, sentiment que de toutes façons ça ne sera pas assez bien, alors on rentre ensuite dans l'apathie, du "à quoi bon ?"
Il y a une limite à l'amélioration continue. Un coureur de marathon ne pourra plus s'améliorer à un certain moment. Ca ne scale pas.
Qui décide de ce qui doit etre amélioré ? Users ? La presse ? On entre dans du CDD (Complaint Driven Development) ou du PRDD (Press Release Driven Development)
Il est impossible de s'améliorer constamment, le mouvement perpétuel n'existe pas, on tends vers une limite.
A un moment, il vaut mieux arreter d'améliorer et partir sur un autre projet.
Il ne faut pas se fixer des objectifs, surtout en tech où tout évolue trop vite. Il faut se fixer des directions dans laquelle on veut évoluer. Le probleme d'un objectif est qu'on ne pourra peut-être pas l'atteindre, même s'il n'a plus de valeur à un instant t+1, mais qu'on continuera de se fatiguer à tout faire pour l'atteindre.
Voir la suite du talk directement en vidéo (plus de batterie pour prendre des notes).
Want to add something ? Feel free to get in touch on Twitter : @pixelastic