Cinq ans d’ALM, putain !

Encore une suite à cinq ans, putain !

Oui, je mets le terme ALM à toutes les sauces, parce que c’est mon bon plaisir.

Donc, sur ce gros projet, j’ai fait ce qu’on pourrait de l’ALM. Qu’est-ce que je mets sous ce terme ?

L’ensemble des tâches qui permettent de passer du code au produit.

Ca inclut, de façon non exhaustive

  • Les outils de build
  • Les outils d’intégration continue
  • L’intégration entre ces outils et les outils de suivi de bugs.

Et évidement, je vais vous (re)parler de Tuleap.

Mais avant, je vais reprendre les étages un par un

Compiling !

Aimablement fourni par http://xkcd.com/303/ mais vous vous en doutiez, non ?

Quand on a commencé notre projet, j’avais déja touché du build maven multi-module. Maias je n’imaginais pas que j’en ferais autant, puisque notre build intègre maintenant

  • De la compilation flex avec flexmojos (raisonnablement facile)
  • De la compilation C++ … et selon la plateforme, cette compilation utilise soit Visual Studio, soit XCode … alors ne me parlez pas de maven-nar-plugin, parce qu’il est notoirement insuffisant pour nos besoins.
  • Du packaging sous d’innombrables formes (war, ear, zxp, …)

Qu’est-ce que ça m’a appris ?

It’s alive

Que la vraie force de maven n’est pas la création d’un format de dépendance universellement utilisé.

Je veux dire, c’est vrai que c’est pratique, ces dépendances, mais quand on arrive à du build « d’entreprise », c’est-à-dire moche et farci de profils, la vraie force de maven, ça n’est pas ça. Non.

La vraie force de maven, c’est de définir un cycle de vie universel. Parce que ce cycle de vie permet, quelquesoit le type de projet, le langage utilisé, ou quelque concept que ce soit, de positionner les différentes opérations dans un tout cohérent. Ca n’a l’air de rien, comme ça, mais c’est réellement indispensable pour les gens qui s’occupent de faire un packaging réaliste. Parce que je sais, quand j’en arrive à la phase « packaging », que tout mon code est compilé, testé, que les ressources ont été traité.

Franchement, quand je regarde les alternatives à maven, je me dis qu’ils n’ont rien compris : ne pas reprendre ce cycle de vie, c’est juste irresponsable maintenant.

Groovy, baby

Alors évidement, vous me direz qu’écrire un plugin maven pour les cas non standard, c’est l’enfer. Et c’est vrai.

Heureusement, j’ai également découvert une gradation dans la personnalisation que j’applique de façon systématique (vous savez, pour tous ces trucs foireux – comme par exemple construire un fiochier de config requirejs à partir de dépendances Javascript) :

  1. Je trouve un plugin maven qui convient ? C’est la fête
  2. Je trouve un ensemble de tâche ANT qui colle ? Cool
  3. Je peux écrire un script groovy avec gmaven ? Bien (dans ce cas-là, n’écrivez pas le script dans le build, mais mettez-le dans un dossier clairement séparé, par exemple src/build/gmaven)
  4. Aucun des trois n’est suffisant ? Alors il est temps d’écrire un plugin maven.

Avec ça, rien n’est impossible dans un build.

Et notez que je ne suis passé du point 3 au point 4 que dans deux cas. Et dans les deux cas, c’est parce que je devais en fait écrire un plugin avec cycle de vie complet. Dans tous les autres cas, groovy a été suffisant, et je dirais même fun.

Non mais tout ce XML, quand même …

Tout ce XML de maven ? A priori, on le regardait sous tes les angles dans m2e quand on ajoutait un nouveau type de build, et après, il n’y avait plus vraiment besoin d’intervenir dessus. Alors dire que c’est pénible, faut pas déconner. Le pire, en fait,a vec maven, c’est qu’Eclipse ne différencie pas les scopes des dépendances. Heureusement pour nous, Jenkins compilait en-dehors de tout IDE.

Make me a sandwich

Et encore, on n’a pas besoin de sudoer Jenkins

Ben oui, Jenkins, le gagnant de la grande guerre du fork.

Lui aussi, on l’a bien tanné.

Justement à cause de notre build natif multi-plateforme. Parce que si on compile une partie de notre application selon la plateforme, on fait comment pour avoir les artefacts dans un build commun ?

Eh bien on se fait un profil spécial Jenkins, dans lequel le build maven est découpé en parties multi-plateformes et dépendant de la palteforme, et on joue du build matrix plugin pour que tout compile et se package sans problème.

Et ça marche, mpême si c’est pas très facile.

Ca chauffe !

A vrai dire, le plus grand échec a été l’implication de l’équipe : même avec un bon radiateur, personne (sauf la testeuse en chef – que toujours elle marche sur un chemin de roses fraîchement coupées) ne s’y est jamais vraiment intéressé. Et ça, c’est triste.

Parce que ça veut dire que cette histoire d’intégration continue n’a été qu’une lubie de ma part, et que je n’ai pas réussi à en communiquer la valeur pour l’équipe, le projet, le produit.

Là-dessus, je peux dire que je retiens la leçon, et que je ferais en sorte que les builds en échec ne puissent plus être ignorés.

Tester c’est douter

Cela dit, tout n’est pas si sombre, puisque le projet a quand même une bonne partie de son code testé, et que TDD a été utilisé dans la plupart des acceptations du terme. La meilleure, et la plus efficace étant qu’aucun bug ne devait être marqué corrigé sans qu’un test ait été ajouté spécifiquement. Parce que

ce qui a foiré foirera

Ca a l’air con dit comme ça, mais ça c’est vérifié à chaque fois : les parties de code ayant connu un bug en ont toujours connu plus, et plus encore.

Heureusement qu’il n’y avait pas d’exploitation statistique des liens entre code et bugs pour vérifier ça, sinon c’aurait été l’enfer.

Et mylyn ? Et Tuleap ?

Là, par contre, l’échec est patent.

Plus encore quand je regarde ce que j’ai pu faire avec gaedo où, là, chaque bug est corrigé à travers un commentaire de commit.

Imaginez que le seul lien dont on ait pu dispoiser était, éventuellement, un lien HTTP dans un commentaire de commit référençant un bug. Comme ça, par exemple :

http://mantis/bugs/view.php?id=7137
the error was stupid : I did not add children to parents when they were needed

ca, c’est moi qui l’ait écrit aujourd’hui.

Ce qui est bizarre, c’est que j’avais parlé de mylyn, de Tuleap, et qu’un autre collègue avait parlé de svn commit hooks … mais aucune de ces tentatives n’a pris. Et pour des raisons diverses … La pire étant celle qui nous a empêché d’utiliser Tuleap : « j’ai pas vraiment eu le temps de regarder ». je dois dire que ça, ça m’a tué.

Alors, content ?

En fait, la plupart des choses installées vont continuer à fonctionner … jusqu’à ce qu’on les arrête.

En revanche, je reste convaincu de l’intérêt de ces outils, et je n’hésiterai pas à pousser leur adoption la prochaine fois.

Cinq ans de projet, putain !

TL-DR

Dans une série d’article commençant par cinq ans, putain ! j’essaye de faire un post-mortem d’un projet d’environ 5 ans de dév. Là, je vais vous parler gestion de projet. Ca n’est peut-être pas mon rôle, mais j’y ai trempé un peu.

Ouaip, bosser sur le même projet pendant cinq ans, c’est long.

Quand on a commencé ce fichu projet, on s’est dit que ce serait bien de faire de l’agile plutôt que du n’importe quoi, comme c’était auparavant l’usage dans la boîte.

Du n’importe quoi ?

Oui : sur la première année, j’ai aidé mes collègues à finir de livrer une version du logiciel historique dont la date de livraison initiale était … avant mon arrivée dans l’entreprise. Et en fait, il a fallu toute la première année pour livrer.

Et encore, on a gagné du temps en

  • mentant pendant les comités de pilotage
  • virant la moitié des fonctionnalités
  • introduisant des gros hacks pour que ça marche

Est-ce que c’était intellectuellement satisfaisant ? Bien sûr que non. Surtout que de l’agile qui marche, j’ai déja vu ça il y a bien des années. J’étais donc plutôt déterminé à assister mon mentor local dans cette transition.

Allez on commence les assouplissements

La première chose qu’on a mis en place, curieusement, c’est un pipeline d’intégration continue. Et ça a bien marché. Parce que ça nous permettait de ne plus stresser (trop) autour des livraisons. Bien sûr, des gros paquets de code foireux ont été livrés, et des retards conséquents ont été pris. Mais le fait de disposer chaque jour d’un build complet était (et est toujours) une satisfaction profonde, parce que ça donne une existence « concrète » au produit qu’on développe.

Et puis il a fallu s’intéresser à l’amont. Les user stories, les tâches, les sprints et toute cette terminologie que je trouve rétrospectivement inutile et qui n’a en fait pas marché. Je vais essayer d’éclaircir.

Donc, on a essayé de faire du scrum (qui comme chacun le sait, est une forme d’agilité) et, à cause de notre équipe moitié intégrée, moitié distribuée, on a dû gérer nos tableaux avec un outil (qui n’est pas en cause ici).

Raconte-moi une histoire – le backlog et les stories

Evidement, dans ces tableaux, la première entrée, c’est le backlog, et dans ce backlog, on trouve les stories de notre client (en l’occurence, le marketting). Et c’est là qu’est le premier problème : faire du marketting, et réussir à exprimer un besoin, c’est loin d’être simple. Et les personnes qui s’en sont occupées n’ont sans doute pas été formées à cette tâche (mais ça, ça reviendra souvent). Du coup, on a pu rencontrer, malgré le formalisme assez classique « En tant que …, Pour …, Je voudrais .. » des problèmes assez pénibles :

  • Toutes nos stories avaient comme rôle « l’utilisateur ». Du coup, impossible de dégager différents sous-sytèmes ou autorisations qui auraient pu clarifier les choses. En fait, il a fallu attendre que le projet ait déja 4 ans pour voir émerger différents rôles.
  • Il n’y avait que rarement des demandes, et bien plus souvent des solutions … dont le réalisme prétait évidement le flan à la critique.
  • Il était également  courant de voir le contenu du backlog totallement transformé d’un sprint au suivant, essentiellement parce que le marketting avait rencontré un client avec d’autres besoins

Des défauts pénibles, donc, que je regrette vraiment de ne pas avoir tenté de corriger, d’une façon ou d’une autre.

Qu’est-ce qu’il aurait fallu améliorer ?

Notre marketting n’a jamais compris ces histoires d’agilité : pour eux, il fallait « juste livrer ». Du coup, leur expliquer que donner des rôle bien définies était difficile. Pour ça, je pense que l’approche des personaes aurait été bien pratique : mettre un nom, un visage, pour que,v raiment, les différents rôles apparaissent clairement.

De la même manière, la fourniture de solutions complètes (mais toujours incorrectes) aurait sans doute nécessité de notre part plus d’accompagnement initial, pour vraiment comprendre le besoin sous-jacent plutôt que l’implémentation proposée.

Il est chouette, ton jouet … il fait quoi ?

Cela dit, on disposait de nos stories, qu’on traduisait en paquets d’items, ce qui nous paraissait correct, jusqu’à la première fin d’itération.

Oh, oui, pardon, je parle d’itération … sans doute parce que nos sprints avaient dépassé les 6 mois, ce qui les rend assez … peu courts, dirais-je.

Et donc, à la fin d’une itération, on fait deux choses :

  1. une démonstration
  2. une rétrospective

Deux occasions d’être fier de son travail … ou pas.

Ca tourne !

La démonstration … l’occasion pour l’équipe de briller devant le marketting. Qu’est-ce qui pourrait foirer ?

Oh, plein de choses (que j’ai vu, hein)

  1. Des développeurs qui ne préparent pas de démonstration, et ne s’attendent même pas à en faire, alors que leur développement est releasé
  2. Des démos qui foirent
  3. Un marketting qui profite de la réunion pour parler d’autres parties de l’application (qui n’ont reçues aucun développement, donc)
  4. Un autre marketting qui profite lui aussi de cette réunion pour râler sur cette équipe de dév qui est toujours en retard

Et quand je dis que je les ai vues, je veux dire que je les ai toutes vues dans la même démo. Alors forcément, à la fin de la démo, l’équipe est … peu satisfaite, pour dire le moins.

Qu’est-ce qu’il aurait fallu améliorer ?

La préparation de la démo, évidement. Il aurait fallu demander à toute l’équipe si les démos étaient prêtes, et testées. Et j’insiste d’autant plus sur le second point que j’ai moi-même foiré une démo parce que je l’avais insuffisament testée. Pour le premier point, je dois bien avouer que la seule façon de s’assurer que les gens préparent une démo est de les laisser se vautrer sur scène au moins une fois.

Pour le marketting, là, c’est simple, parce que je l’ai fait la fois suivante : il ya  un ordre du jour clair à cette réunion, et si certains veulent s’en écarter, c’est à l’animateur d ela réunion (moi, sur ce coup-là) de les recadrer, ce que j’ai fait.

Et dans les coulisses

Parce qu’il y a un pendant interne à cette démo : la rétrospective.

Personnellement, j’adore ce moment où on peut tenter de proposer de nouveaux modes d’organisations.

Par exemple, c’est lors d’une de ces réunions que j’avais proposé qu’on utilise Tuleap … mais j’en reparlerais.

Bref, là aussi, c’est une réunion qu’il vaut mieux préparer …

Et comme vous devez vous y attendre, j’ai eu quelques réponses comiques aux trois questions rituelles.

Vous savez :

  1. Qu’est-ce qui a bien marché ?
  2. Qu’est-ce qui n’a pas bien marché ?
  3. Qu’est-ce qu’on peut améliorer ?

Et l’ordre est important : commencer par ce qui a bien marché permet normalement aux gens d’avoir un étatt d’esprit positif … enfin, normalement.

Mais avant d’en venir aux insultes internes, une petite astuce offerte

Tout ça, c’est la faute à Raoul.

Lors de la rétropsective, regardez bien la deuxième question : c’est la porte ouverte aux réglements de compte. Pour les éviter, l’astuce est simple, on avait une persona de mauvais développeur : Raoul Abdaloff (le nom ne doit rien au hasard, et tout à l’UMP). Et tout ce qui s’est mal passé est de sa faute. Une fois muni de ce mauvais développeur, qu’est-ce qui peut foirer ?

Tout va mal, et rien ne s’améliorera

Dans l’ensemble, ces réunions se passaient bien. Jusqu’à ce jour funeste, où trois collègues ont répondu dans un bel ensemble

Qu’est-ce qui a bien marché ?

Je sais pas

Qu’est-ce qui n’a pas bien marché ?

Tout

Qu’est-ce qu’on peut améliorer ?

Rien

Là, faut être lucide, parce que les mecs, j’ai bien eu envie de les passer par la fenêtre.

Qu’est-ce qu’il aurait fallu améliorer ?

Pour la rétropsective, pas grand chose, puisque le but du jeu était d’améliorer le processus. Et ça marchait bien !

Du coup au bout de cinq ans c’est le top ?

J’ai déja parlé du dépôt de bilan, non ?

Eh bien on peut dire que ça a tout détruit.

Aujourd’hui, il n’y a plus

  • de démos
  • de rétrospectives
  • de sprints
  • d’agilité
  • d’envie

Ca calme, non ?

Mais pourquoi ?

Au fond, l’agilité, le scrum, le lean, le kanban, tout ça, c’est mignon, mais c’est juste un mensonge.

Parce qu’en fait, ces idées se contentent de dire qu’il faut que les personnes aient envie d’améliorer leur mode de travail pour que leur mode de travail s’améliore … Autrement dit, ça permet plus de canaliser l’enthousiasme de jeunes chiens fous que de remotiver des vieux développeurs dont la culture sectaire a réduit l’enthousiasme a néant.

Et, je regrette de le dire, même mon enthousiasme a disparu dans la bataille (d’un autre côté, c’est aussi pour ça que je m’en vais).

Du coup, si je peux me permettre un conseil aux apprentis agilistes, ou à ceux qui se demandent pourquoi leur processus agile est arrêté au bord de la route : regardez vos développeurs, et vos « clients ». Est-ce qu’ils sont motivés ? Est-ce que ça leur plaît ? Est-ce qu’ils ont envie de faire mieux ? Si ça n’est pas le cas, laissez tomber tout ça, et contentez vous de faire des itérations courtes, et de durée fixe. Parce que ça, le rythme, ça aide aussi beaucoup. Et le perdre, souvent, c’est un signe que quelque chose d’autre ne va vraiment pas.

 

Ch’mongoDB

Eh ouais, hier soir, c’était chtijug sur MongoDB avec Tugdual Grall.

Mais avant, minute copinage …

Le chtijug a la chance d’avoir un nouveau sponsor, et ça, c’est cool (d’autant plus que ce sont mes voisins de bureau jusqu’à ce soir) :

IMG_20141217_185256[1]

Le représentant d’Onyme a peut-être un moins chouette polo que certains précédents sponsors, mais un sacrément chouette discours

Et je me suis laissé dire qu’ils recrutaient

Bref, merci les gens !

Revenons-en donc à Tugdual

IMG_20141217_185548[1]

Oracle, eXo, Couchbase, MongoDB … clairement, le développeur un peu âgé a souvent touché à plein de trucs

Même fatigué, c’est un speaker sacrément rodé qui nous a fait une présentation intéressante, bourrée de live-coding, sur MongoDB.

Alors MongoDB, qu’est-ce que c’est ?

IMG_20141217_190640[1]

Mongo, une base agile, flexible, intituive et stockant les données dans un format facile à exploiter

En gros, c’est une espèce de gros système de stockage de BSON (un format binaire adaptant le JSON) disposant d’interfaces dans les différents langages … mais ça n’est pas ce que racontait vraiment ce slide moche.

Non. Ce que voulait expliquer Tugdual, c’est que les bases de données relationelles datent de 40 ans, à une époque où l’esapce disque coûtait vraiment cher. Et donc à cette époque, l’optimisation la plus importante concernait l’utilisation du disque. D’où les bases relationenlles où la donnée est forcément unique, et en troisième forme normale.

C’est pratique pour les DBA, parce que la donnée est bien structurée.

C’est en revanche infernal pour le développeur, puisque la donnée n’est pas accessible facilement. Ce qui explique, par exemple, l’intérêt pour les outils de mapping objet-relationnel.

Un autre inconvénient du fait qu’une écriture se fasse à de multiples endroits, c’est que l’écriture nécessite d’être encapsulée dans une transaction, qui est lourde en termes de ressources pour le serveur (et donc impactant l’ensemble des clients).

A l’opposé, MongoDB cherche à être une base de stockage agréable pour les développeurs.

Ca veut dire quoi ?

  • MongoDB stocke des documents en JSON, qui peuvent contenir des champs simples ou des tableaux de tableaux de tableaux (avec toutefois des limites … qui me semblent assez difficiles à atteindre à première vue).
  • Si deux documents doivent contenir chacun la même donnée, il peut être plus simple de dupliquer cette donnée … ou de la référencer (mais dans ce cas, c’est le développeur qui gèrera l’unicité du lien)
  • Du coup, comme le document est complet, il n’y a pas vraiment besoin de transactions : soit il est écrit, soit il ne l’est pas, mais le développeur le sait tout de suite. Donc MongoDB est non transactionnel, et ça n’est pas grave.

Et paf, Tugdual enchaîne sur une démonstration de la « convivialité » du shell mongo.

insertion d'un document dans la collection "customers", et récupération de la liste des "customers"

insertion d’un document dans la collection « customers », et récupération de la liste des « customers »

Et là, c’est le drame : comme le shell Mongo n’offre ni complétion, ni mise en valeur de la syntaxe, et que Tugdual était un peu fatigué (mais ça, je comprends, parce que coder à l’heure de l’apéro, c’est loin d’être facile), les accolades oubliées s’enchaînent en rafale

Ami lecteur, trouve l'accolade manquante ... Ouaip, c'est lioin d'être facile

Ami lecteur, trouve l’accolade manquante … Ouaip, c’est lioin d’être facile

Notez que je ne critique pas Tugdual, mais le shell mongo. Peut-être qu’un outil comme Robomongo, mongodb-shell ou même l’un des innombrables plugins Eclipse aurait pu lui faciliter la vie. Mais je comprend qu’en tant qu’évangéliste Mongo, ça lui soit un peu difficile d’utiliser des outils tiers.

Bref. Après l’insertion, une autre chose intéressante : la seule chose que doivent avoir les documents Mongo, c’est un attribut « _id » qui peut être soit généré (à partir de l’adresse Mac, du numéro de process, et du timestamp unix), soit écrit manuellement. Et il se passe quoi quand un utilisateur essayé de créer un nouveau document avec un _id déja utilisé ?

Si j'essaye d'avoir deux documents avec le même _id, j'ai droit à une jolie erreur

Si j’essaye d’avoir deux documents avec le même _id, j’ai droit à une jolie erreur

Bon, maintenant que j’ai bourré la base, il est temps d’y chercher des trucs.

Et là, franchement, pour moi, c’est le moment du malaise.

Parce qu’autant je veux bien comprendre l’intérêt des documents en JSOn, des réponses du serveur en JSON mais quand Tugdual a fait ses query/update avec du JSON pour

  • rechercher les documents à mettre à jour
  • définir les opérations d’altération à effectuer (modification, suppression, insertion)

Je dois avouer que j’ai eu comme un malaise

Regardez donc :

Une opération simple de recherche et mise à jour, avec un paquet de JSON dedans

Une opération simple de recherche et mise à jour, avec un paquet de JSON dedans

Et si ça ne vous paraît pas assez clair il y a évidement de la doc sur internet.

Je vais quand même essayer de clarifier mon malaise : il me semble que tous les paramètres de toutes les opérations sur une base MongoDB sont passés sous forme de JSON. Et c’est quelque part assez bien.

Toutefois, tenter d’exprimer une recherche et une mise à jour sous cette forme paraît assez bizarre, surtout vu quelques choix faits (et présentés ici)

  • Les opérations de MongoDB sont définis dans les paramètres sous forme d’attributs JSON préfixés par « $ » alors n’allez pas utiliser ce caractère magique dans vos données !
  • Si vous cherchez au fond d’un sous-document, il faudra passer votre chemin de recherche dans une chaîne (parce que « . » n’est pas accepté comme clé dans un hash JSON). Du coup vous aurez certaines clés avec des guillemets autour et d’autres sans. Et vous vous demanderez d’où vient l’inconsistence.
  • Si vous cherchez dans un tableau une valeur ayant plusieurs propriétés, ce sera … un peu plus compliqué.

Bref, je peux le reconnaître, je n’ai pas aimé cette syntaxe, bien qu’elle soit extrêmement déclarative.

Bon, une fois arrivés là, il est temps de sortir du shell et de passer au driver Java, qui se présente sous plusieurs formes (au passage, il y a des tonnes de drivers, listés dans une très belle page – dixit Tugdual) :

  • Un driver basique qui vous fait manipuler des DBObject qui sont en fait une vision javaisée et fluente des documents JSON. Au apssage, ce driver fournit un chouette outil de création de requête : QueryBuilder.
  • Morphia, qui est un ODM qu’on pourrait considérer comme un concurrent d’Hibernate OGM ou de Spring Data, mais spécifiquement conçu pour MongoDB.
  • MongoJack qui utilise les annotations de Jackson pour mapper les objets Java sur les documents JSON.

Petite parenthèse : le style Dracula d’Intellij ne m’a paru super lisible …

Et pourtant j'étais au deuxième rang ...

Et pourtant j’étais au deuxième rang …

Une fois ces différents outils présentés, Tugdual nous explique, à travers un exemple d’application web, comment utiliser tout ça au mieux.

D’après lui, et plus j’y pense, plus j’approuve, la meilleure solution et d’utiliser le driver basique pour les lectures, et les mappers pour les écritures. Et la raison est assez simple :

En lecture, on passe le JSON de Mongo jusqu’au client … typiquement écrit en Javascript, et donc parfaitement capable de lire ce Javascript.

En revanche, en écriture, pour contrôler ce qui est écrit dans la base, on a intérêt à passer par un mapper. MongoJack a ma préférence … surtout que, contrairement à Tugdual, je sais lui faire ignorer les propriétés inconnues (en utilisant par exemple la DeserializationConfig).

Une fois ce tour du dev fait, Tug est passé au clustering … Bon, là, c’est assez classique : il y a du sharding, de la haute disponibilité via l’élection automatique d’un master … La routine, en quelque sorte.

Et il était déja l’heure du …

Ouaip, Onyme sait toujours aussi bien recevoir !

Et alors, est-ce que je vais passer à MongoDB ?

Bon, j’ai failli il y a peu travailler sur une application utilisant massivement du MDM. Et MongoDB faisait partie des systèmes de stockage candidats.

Je dois bien reconnaître que cette présentation m’a appris pas mal de choses vraiment chouettes sur cette base. Et je comprend bien les cas d’utilisation présentés par Tugdual :

  • Vision 360° d’un client pour, par exemple, du support
  • Aggrégation de données provenant de façon assynchrone de plusieurs systèmes de gestion de données

Bref, la construction de rapports et leur utilisation dans des applications architecturés autour de concepts proches de CQRS paraît facile avec MongoDB.

En revanche, ce qui me paraît beaucoup plus compliqué, c’est la construction de données historisées « sans fin » (à cause par exemple de la limite dans la taille des documents).

Et puis, après avoir bossé sur des bases graphes, je dois bien reconnaître que je reste très attaché au graphe, c’est-à-dire à la création, et à la gestion de cohérence de ces liens par le système. Or c’est précisément le sujet que MongoDB ne veut pas adresser (et je les comprend, parce que ça simplifie bien des choses).

Cela étant, c’était une sacrément chouette session. Merci au chtijug !

Cinq ans, putain !

Comme il me reste plus que cinq jours de présence dans celle qui sera bientôt mon ancienne entreprise, je pense que le moment est parfaitement adéquat pour me lancer dans une petite série d’articles revenant sur ces cinq années de présence dans une boîte qui s’est appelée Perigee.

Je vais, pour ce premier article, ne pas vous parler de ce qui m’a occupé pendant quatre de ces cinq années : une espèce d’usine à gaz permettant de générer des catalogues grâce à Indesign.

Parce que la technique est chiante. Surtout quand c’est l’une de ces horreurs dont Adobe a le secret (oui, je parle d’Indesign).

Parce que, quand ce projet a commencé, l’idée (en 2010, donc) de créer un nouveau logiciel dont le seul objectif était de produire du papier me paraissait anachronique (pour être gentil).

Bref …

En fait, c’est la première fois dans ma carrière que j’ai eu la chance de pouvoir prendre des décisions impactantes pour un développement logiciel, mais aussi la première fois que j’ai pu vivre un projet de la première idée farfelue à sa réalisation concrète. Et même si le projet est un échec commercial, c’est également, de mon point de vue, une certaine forme de réussite technique … une réussite aussi évidente que pourrait l’être, dans un autre domaine, un aéroglisseur de transport de troupes : en dehors de son domaine d’utilisation, c’est lourd, lent, pénible, insupportable, même. Mais dans son domaine, c’est la meilleure solution possible … ou presque. Toujours est-il que voir un logiciel se construire de la première à la dernière brique est une sacrée aventure collective.

Et je crois que c’est la principale transformation que m’a fait subir mon mentor local : comprendre que si le codage ets une étape nécessitant de la tranquilité, le développement d’un logiciel, pris comme un tout, est avant tout un travail d’équipe nécessitant de la communication. Et pas n’importe laquelle. J’ai l’impression que le développement st de l’ordre de la maïeutique. En effet, l’équipe dans son ensemble cherche à donner corps à une idée, pour le simple développement, ou à comprendre ce qui dysfonctionne, dans le cas plus courant de la correction de bug.

Quoi ?

Vous me dites que vous ne comprenenez pas pourquoi je parle plus de correction de bugs que de développement ?

Eh bien c’est aussi l’une des grandes leçons de ce développement : même pour un nouveau développement, même pour un bout de code qui n’a pas encore passé l’épreuve du client, on passe plus de temps à reprendre du code qu’à en écrire du nouveau.

Et je pourrais développer ça sur quinze pages, mais ça me forcerait à entrer dans des considérations techniques qui ne sont pas le sujet de ce texte … mais peut-être du prochain.

Cap sur 2015

J’ai cet article dans mes brouillons depuis près d’un mois … et 2015 se rapproche inexorablement, et avec ce changement d’années d’autres changements se profilent.

Bref, vous vous souvenez qu’il y a un an, mon employeur avait déposé le bilan, puis avait été partiellement repris, et moi avec.

Qui dit reprise dit nouvelle direction, et donc nouvelle stratégie. je n’entrerais pas dans les détails de cette nouvelle stratégie, parce que ce blog n’est pas le bon endroit pour en discuter. Je me bornerais à dire que, comme quand c’est arrivé il y a 14 ans chez Miriad Technologies (à une époque où je n’avais pas encore de blog – et où le mot n’existait d’ailleurs même pas), la nouvelle stratégie n’avait pas vraiment de place pour moi, ce que j’ai compris avant qu’il faille en parler clairement.

J’ai donc pris la décission d’aller voir ailleurs si j’y serais.

Oh, pas très loin.

Mais alors vraiment pas loin, puisque je vais retourner dans le temple de Lille is French Tech : Euratechnologies. Et plus précisément, je vais aller chez Cap Gemini.

Quoi ?

Ca vous fait bizarre parce que j’ai toujours affirmé une relation plus qu’ambivalente vis-à-vis des marchands de viande ?

C’est vrai.

Mais mes discussions m’ont conduit à un poste qui ne m’emmènera pas forcément en représentation technico-commerciale permanente chez les clients.Et d’autres raisons, beaucoup moins palpables, me font penser qu’il pourrait s’agir d’un emploi bien plus intéressant que ce que je peux en penser. Bref, j’yv ais, parce que je suis intrigué, et un peu effrayé, de voir ce qui peut se passer dans l’une des incarnations les plus limpides de Cleer …Et puis ce changement va me permettre de faire un bilan de ces cinq dernières années.

Après deux mois de Javascript, on se sent comment ?

La question peut paraître … curieuse. Elle n’en demeure pas moins valide : quand on est comme moi un développeur Java un peu expérimenté, et qu’on passe d’un coup à ce langage aussi ubiquitaire que malaimé, qu’est-ce qui surprend ? Qu’est-ce qui étonne ? Qu’est-ce qui déçoit ?

J’ai vu des choses …

Avant d’aller plus loin, une petite mise au point. Je ne vais pas vous parler du dernier projet à la mode de lad ernière startup qui démarre. Non. J’ai fait du Javascript ces deux derniers mois pour la même raison qui m’avait forcé à faire du Flex pendant trois ans en pointillés sur le même projet : si vous voulez faire une extension pour indesign CC 2014, vous n’avez pas vraiment le choix, vous devez faire du HTML+Javascript. Alors du coup, je ne vais pas vous parler de Javascript qui communique avec son serveur via HTTP, mais de Javascript qui communique avec une extension Java/C++ via le système de communication créé par Adobe. Et, il faut le dire, Adobe fait des choix techniques … surprenants (j’y reviendrais).

En dehors de ces contraintes techniques spécifiques, l’application sur laquelle j’ai bossé n’a pas vraiment de spécificités. Enfin, pas trop :-)

Alors, grunt, bower, npm ?

hrm hrm …

Je vais essayer d’expliquer ça de façon claire, même si ça va choquer.

Le projet pour lequel on fait cette interface est un projet multi-module de taille « moyenne » : 32 modules différents, compilant et générant tout un tas d’artefacts. Est-ce que j’allais introduire dans ce gros paquet de modules, et dans mon Jenkins, un autre outil, ou plutôt ensemble d’outils ? Non. Je voulais (peut-être de façon dogmatique) que cette interface soit packagée par maven.

Tester du JS dans maven, c’est possible ?

A la lumière de mes expériences avec Wisdom, je me suis dit que j’allais jeter un oeil à frontend-maven-plugin histoire de profiter de ses fonctionnalités (en particulier les tests). Mais, curieusement, je n’ai pas réussi à lui faire faire quoi que ce soit. Alors j’ai arrêté de faire le mariole, et j’ai dit à l’un de mes collègues de faire un système de test Javascript à base de Fluentlenium (qui est devenu pour une raison que j’ignore du Selenium pur et dur) et de JunitParams.

Autrement dit, pour chaque test Javascript, on crée un fichier HTML le chargeant via requirejs (j’y reviendrai) et on récupère grâce à Selenium le résultat du test via un peu de Javascript. Ca pique un peu les yeux la première fois, mais ça marche en fait très bien (même si tester du code asynchrone avec Jasmine est un peu compliqué).

Et les dépendances ?

Bon, évidement, comme notre projet n’utilise pas HTTP, nos dépendances Javascript (pour lesquelles Webjars rempalce très avantageusement NPM) nécessitent un peu de travail, essentiellement pour faire une translation de chemin qui les rende facilement utilisables.

Je m’explique.

Notre projet a (par exemple) ces dépendances :

		
	<dependency>
            <groupId>org.webjars</groupId>
            <artifactId>requirejs</artifactId>
            <version>2.1.14-3</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>requirejs-text</artifactId>
            <version>2.0.10</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>log4javascript</artifactId>
            <version>1.4.9</version>
        </dependency>
		

Comment je fais pour utiliser log4javascript sans m’emmerder à mettre son numéro de version partout ?

Parce que, par exemple, avec Wisdom (désolé de prendre cet exemple de façon systématique, mais son utilisation m’a appris quelques trucs vraiment chouettes), je n’ai pas besoin de mettre le numéro de version grâce au WebJarController.

Eh bien c’est … assez compliqué, et ça se fait en plusieurs étapes

  1. On a un script groovy (encore merci à gmaven) qui nous permet de créer pour les dépendances Javascript des propriétés maven. Les artefacts mentionnés me donnent donc les propriétés org.webjars:requirejs:javascript:require, org.webjars:requirejs-text:javascript:text et org.webjars:log4javascript:javascript:log4javascript qui deviennent faciles à inclure dans un <script src="${org.webjars:log4javascript:javascript:log4javascript}"></script>
  2. Le même script maven crée également une grosse variable ${requirejs.dependencies.compile.paths} qui sera bien utile pour générer le shim de requirejs.
  3. Et tous nos artefacts javascript sont dézippés grâce à amven-assembly-plugin pour générer l’application.

Alors évidement, toutes ces technologies sont infiniment moins hypes que les build tools Javascript, mais elles nous permettent d’intégrer proprement des dépendances Javascripts dans notre build et ça, ça fait plaisir.

Et requirejs, c’est vraiment bien ?

Vous allez rire (ou pas), mais pour l’instant, deux choses ont été embêtantes (mais résolues)

  1. Si vous chargez tous vos scripts avec le protocole file://, vous serez limités par la longueur maximale des chemins de Windows. Et si vous avez des gros chemins, par exemple pour des classes Java dans des packages profonds pour lesquelles vous générez des stubs Javascript à l’aide de flexmojos (essentiellement parce que GraniteDS intègre un super générateur pour les entités et les services – et ne me demandez pas comment je transforme mes fichiers .as en .js), eh bien vous allez pouvoir vous amuser à écrire un algorithme de translation de chemin et un plugin amven (ou un script gmaven) pour copier les bons fichiers aux bons endroits au bon moment (parce que amven-assembly-plugin est clairement dépassé, là).
  2. Et si vous avez des dépendances en scope compile et d’autres en scope test, ça ne posera pas vraiment de problème à requirejs, mis à part bien sûr qu’il faudra distinguer le data-main de l’un et de l’autre.

Mais dans l’ensemble, require me réconcilie vraiment avec le côté « packageless » de Javascript. Je n’ai pas besoin de faire ces fameuses fonctions anonymes auto-appelées. Je déclare chacun de mes fichiers presque comme je le ferais en Java, et tout (ou presque) est explicite. Le fait de travailler dans un environnement contrôllé donne un sentiment de sécurité asssez plaisant, et des fichiers déclarés selon une syntaxe vraiment agréable.

Et Ractive, c’est pas du flan ?

Ce qui est assez marrant, c’est que plus je m’en sers, moins je comprends les mecs qui font de l’angular (oui, ça sonne comme du bashing, mais c’est plutôt de l’incompréhension).

Il nous a été assez facile d’écrire des composants pas forcément triviaux, et à chaque fois qu’on se dit que Ractive pose un problème, il s’agit en fait d’un problème entre la chaise et le clavier (une erreur ID10T comme dirait mon collègue).

Et le fait de ne pas s’embarasser d’une gestion du modèle nous a permis d’utiliser ce fameux protocole de communication Adobe sans « trop » de problèmes.

Ah bon, alors vous faites pas de JSON ?

J’ai dit protocole, je n’ai pas dit format d’échange.

En fait, on utilise du JSON, mais sans passer par la librairie JSON fournie par Adobe (et je vous conseille de faire de même parce que cette librairie est buggée).

En revanche, échanger du JSON entre du Java et du javascript pose une question sérieuse : on part d’un monde typé, dans lequel chaque objet peut avoir des méthodes associées, méthodes pour lesquelles on aimerait bien disposer d’équivalents en Javascript. Par exemple, l’un de nos objets doit s’afficher en utiliser le resourceBundle fourni, on a donc envie de mettre la méthode dans le fichier Javascript généré par Flexmojos (pas de panique, Flexmojos en génère en fait deux : un qui sera réécrit à chaque build pour contenir les champs définis par le Java, et un autre généré une seule fois, dans lequel on peut ajouter notre code).

Mais comment fait-on pour que le JSON reçu du Java s’interprète non pas sous forme de hash anonyme, mais grâce à notre classe ?

Eh bien là, c’est vraiment compliqué :

  1. On demande à Jackson d’envoyer les informations de type dans le flu JSON grâce à son système de déserialisation polymorphe (on a utilisé jsonMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_OBJECT))
  2. Du coup, côté Javascript, on récupère des hashes qui associent à une classe le hash correspondant à l’objet, et là, c’est l’enfer : on a dû écrire un système qui « unmarshalle » ces hashes anonymes pour retourner des instances des classes Javascript correspondant aux aux classes Java. Et comme ça passe par require, il faut faire ce truc qui fait toujours peur : du code récursif asynchrone. Heureusement que Deferred est là, parce qu’il me semble que de tout le code Javascript, c’est la partie la plus compliquée que j’ai eu à écrire. Un enfer, je vous dit
  3. Ah, et en bonus, il ne faut pas oublier le code inverse : celui qui va prendre des objets Javascript ou des hashes anonymes pour créer de beaux obejts Java à l’autre bout du fil … Pas gagné.

Tiens, d’ailleurs, c’est le moment idéal pour vous rappeler que, comme les maps javascript n’ont pas de clés non string, ça ne peut pas être le cas non plus pour le JSON. Alors comme vous ne voulez pas réécrire tout votre code serveur pour votre nouveau client moderne, eh bien vous aller devoir vous taper la (dé)sérialisation des maps sous forme de tableaux de tableaux … Bon courage ;-)

Autrement dit, comme d’habitude, la couche de communication va vous plonger dans un enfer sans nom, et surtout sans aucune raison valable.

Oui mais alors, le fait que ce soit pas compilé, qu’il n’y ait pas vraiment d’objets, c’est galère ?

Pour être honnête, oui.

Et pour être encore plus honnête, c’est pas trop grave.

Parce qu’en fait, il s’agit vraiment d’une interface HTML/Javascript : la partie complexe de l’application est bien au chaud, dans du code Java qui est correctement testé, qui a été écrit de façon à être raisonnablement robuste et qui est surtout déja utilisé en prod, donc qui a passé l’épreuve du feu.

Du coup, même si on galère parfois sur des histoires de types, ou de paramètres manquants/mal typés que Javascript ne voit pas parce que ça n’est pas son problème, ça n’est pas vraiment dramatique.

Et donc tu referais sans hésiter la même chose en plus gros ?

A dire vrai, mon Wiko a une version portable de Firefox qui fait fonctionner Ractive sans problème (comme Chrome, d’ailleurs). Alors du coup, demain, si je dois développer une application web, je peux vous assurer que le serveur se cantonnera à envoyer du JSON à mon client require/Ractive qui me fera, lui, une chouette interface.

Au passage, le bonus caché de Ractive, c’est que la philosophie est vraiment très proche de celle des web components, ce qui est loin d’être avantage mineur.

Eventuellement, j’ajouterais un coup de Facebook Flow pour valider mon code, et peut-être aussi que j’utiliserais plus frontend-maven-plugin pour minifier et toutes ces sortes de choses, mais dans l’ensemble, je comprend mieux ces histoires de microservices : si le client peut s’occuper d’aggréger et de présenter les données, pourquoi s’embêter à utiliser toute la pile JavaEE là où Wisdom suffit largement ?

Groovy it, dude !

Je vais faire un peu de live-blogging d’un problème pénible.

Ce matin, je devais faire un merge.

Et curieusement, ce merge foirait, à cause d’une erreur … difficilement compréhensible


Working copy and merge source not ready for reintegration
svn: Reintegrate can only be used if revisions 9043 through 9581 were previously merged from http://achille.perigee.fr/svn16/autocat/autocat-java/branches/2.1 to the reintegrate source, but this is not the case:
autocat-java/branches/2.0-item-196-cc-html5

J’avais trouvé (via Stackoverflow évidement) une méthode manuelle pour corriger le problème. Et j’étais en train de me préparer à faire tout ça à la main en quelques heures.

Et puis je me suis dit que c’est quand même con de corriger une cinquantaine de fichiers à la main quand je peux scripter ça.

Et aussitôt, j’ai lancé ma meilleure Groovy Console pour y écrire ce script, qui fait exactement ce que mentionne la solution : faire un svn propdel sur chaque fichier mentionné.

Et dix minutes plus tard …

Le plus compliqué pour moi a été de me décider : est-ce que j’utilise svnant, ou est-ce que je fais directement de l’exécution shell de « svn » ? Eh bien ce qui m’a poussé vers la deuxième solution,c ‘est que svnant n’est disponible que par téléchargement direct, et que je n’avais pas le courage de voir comment Groovy Grapes allait devoir être configuré pour ça …

En tout cas, ça confirme encore une fois mon opinion sur le fait que Groovy est définitvement LE langage de la JVM pour scripter dans tous les environements.

J’ai pas fait de crowdcast sur Javascript ..

Bref, j’ai eu peur de passer pour un con.

Evidement, le crowdcast, seuls les auditeurs des castcodeurs savent ce que c’est.

Pour les autres, dites-vous que c’est la rubrique « les auditeurs ont la parole » des castcodeurs, et qu’elle a déja eue autant de succès que les commentaires audio de podcastscience (regardez le texte écrit en colonne à droite).

Bref.

La semaine dernière, j’avais demandé si je pouvais parler de chouettes librairies Javascript :

Ce qui avait eu l’heur de plaire aux dits castcodeurs :

Même si finallement, j’ai changé d’avis

(ca vous branche, cette twit-conversation recopiée ? Moi, en tout cas, ça me facilite la vie).

Je vais vous expliquer pourquoi plus en détail.

En fait, j’avais eu cette idée suite à la soirée du chtijug, et en particulier la présentation de Romain et Julien sur Polymer.

Je voulais donc parler de Ractive, et de son intérêt supérieur quand on l’utilise avec Requirejs. Seulement, autant je pouvais facilement parler de requirejs parce qu’il me semble occuper une niche unique dans l’intégration IoC en Javascript (alors que non en fait), autant pour Ractive, je me voyais mal dire en public que Ractive c’est de la balle, quand je sais que c’est avant tout une question de choix personnel (coix que todomvc présente assez bien, d’ailleurs).

Et puis je suis tombé sur cet article (via @jponge)

Et j’ai longuement réfléchi : qu’est-ce qui garantit que Ractivejs ou Requirejs survivront plus de quelques mois ? Et dans ce cas-là, franchement, j’aurais l’air de quoi si je les mets en avant plus publiquement que sur ce blog ?

Et même sur ce blog, d’ailleurs. J’y ai en effet déja parlé de quelques technologies qui me paraissaient intéressantes et qui, depuis, ont disparu (Qi4j, Majick-properties, et même gaedo, en un sens, sans même parler de tous ces sites hypes qui s’évanouissent quelques mois plus tard).

Bref, j’ai eu peur de passer pour un con.

Ou alors j’ai enfin atteint une certaine maturité.

En tout cas, je crois que je vais attendre encore un peu avant d’en parler, même si je continue à penser que ce sont deux bons projets, qui adressent bien mieux qu’angular ne saurait le faire les défis du développement d’applications web dans le navigateur.

Et du coup, je me dois de féliciter encore une fois les castcodeurs et les crowdcasteurs qui ont eu le courage de parler dans le poste. Parce que pour l’instant, je ne suis pas encore sûr d’avoir un truc intelligent à y dire, dans le poste. Et vous savez ce que disait Pierre Desproges sur le sujet …

Le révisionisme dans Git, et un thermomètre en polymère.

Oui, j’y étais.

Hier soir, j’ai été assister à une chouette session du chtijug sur trois sujets, traités assez rapidement …

Avoir de beaux historiques dans git

Cyril et Hubert nous on fait un duo à base de pierre-feuille-papier-ciseaux-lézard-spock sur le thème des historiques dans git. C’est apparement une session qu’ils avaient déja présentée à Devoxx, puisqu’ils sont déja sur Parleys. Et tant mieux, parce qu’on a eu droit du coup à une présentation bien rôdée.

Ils nous y ont donc parlé de l’intérêt d’avoir un historique git beau et propre, sans commits avec des messages comme (je regarde dans mon projet …)

  • « WTF ? was lacking ? » (ça c’est moi)
  • «  » (oui, rien, ça arrive bien trop souvent)
  • « modif Nicolas afin de prendre en compte les interfaces héritées » (ça c’est quand je commite depuis le poste d’un collègue)
  • « PB-0005104,PB-0004951,PB-0005108,PB-0005006,PB-0004981,PB-0005173,PB-0005112 ,PB-0005037,PB-0005012,PB-0005164,PB-0005143,PB-0005010,PB-0004995,PB-0004955,PB-0004956″ (le pire message du monde : pleind e bugs résolus sur plein de fichiers différents)

Et donc, pour éviter ça, Hubert nous propose d’adopter le format Angular/Karma/…

Le format proposé n’est pas idiot, même si la description n’inclue que de façon très sommaire les liens vers les bugtracker (github issues en particulier a déja des outils bien pratiques, qu’il aurait été bon de mentionner).

Je passe par contre sur les lignes de commandes insupportables de git (surtout que SourceTree fournit le même workflow sans en passer par vi).

Cela dit, une question n’est pas posée : dans quel mesure ce travail est-il réellement utile par rapport à la mise en lien avec un bugtracker ? Autrement dit, quelle est la valeur ajoutée de ce travail d’esthétique de l’historique ?

Tiens, et une autre qui em vient comme ça : dans quelle mesure on essaye de faire de git une espèce d’ALM du pauvre quand des outils comme Tuleap existent ?

Un thermomètre dans ton web

Très chouette démonstration liant de l’Arduino, du Java8 et du Simple HTTP Server. Tout le code est sur Github, mais honnêtement, le code, là-dedans, c’est pas grand chose. Je cite :

Et encore, il manque le slide avec la tronche du chimpanzé …. et le fameux étalonage du thermomètre (qui m’a en fait très peu surpris, puisque comme l’a justement dit Mathieu, c’est réellement la façon professionnelle d’étalonner).

Une session à voir pour le style

Des superhéros polymérisés

Peut-être la session la plus proche de ce que je fais en ce moment avec Ractive. Il s’agissait en gros de produire un web-component avec polymer pour afficher de jolies fiches de super-héros.

Bon, par contre, il n’y a pas plus de version internet que pour le thermomètre, puisqu’il s’agissait là aussi de pur livecoding (ou plutôt, live-template-using, puisque Julien avait préparé des templates par dizaines pour que le ryhtme de la démo soit tenu, une très bonne idée).

Je retiens deux ou trois choses

  • Polymer est vraiment très très proche de Ractive : des templates utilisant Mustache, du two-way binding facile avec le modèle, et une grande simplicité du code
  • Le modèle des composants déja existants dans Flex est loin d’être mort. Thibaud parlait de JSF, mais ça remonte en fait bien plus loin … je dirais … Motif (quoi que je n’arrive pas à me souvenir si les composants étaient définis de façon duale par une construction statique + du code pour les événements).
  • Apparement, la spec derrière Polymer évolue encore assez régulièrement (la petite anecdote de Romain sur les trois réécritures de leur projet depuis Devoxx 2014 – donc 6 mois – m’a fait un peu flipper). Donc c’est pas encore complètement prêt à l’usage. C’est en revanche clairement la directionv ers laquelle converge le web.

Je suis un people

Et c’est qui la tête d’oeuf au premier rang ?

Ben ouais.

Bon, par contre, je pense que je tenterai l’after la prochaine fois, parce que le chtijug, c’est aussi ça

Kouign-amman, nous voici !

Bon, théoriquement, je devrais écrire « kit et kat, nous voici ». Seulement,

  1. Je préfère le kouign-amman
  2. Je trouve désastreusement déplorable que Google soit (plutôt que Microsoft, par exemple), le premier éditeur d’OS à « re-brander » une version de son OS pour en tirer un bénéfice.

Ah, oui, au fait, je vous parle d’Android, là, pas de cuisine.

Parce que les gens de Wiko ont eu la bonne idée de mettre à disposition KitKat pour mon Raimbow. J’ai donc installé la mise à jour à partir de Windows la semaine dernière. Et dans l’ensemble, ça se passe plutôt bien. Même si j’ai dû manuellement réinstaller toutes les applications (d’accord, il y en a des grosses, mais puisque Google Play mémorise toutes les applications que j’ai installé – ou pas – il n’était pas capable de mémoriser que je voulais les installer en wifi ? HEIN ?). Bref, j’ai donc tout réinstallé.

Tout, sauf un truc qui me manque terriblement : Kii Keyboard. Je l’avais découvert grâce à SebSauvage, et je le trouvais fantastiquement meilleur que le clavier par défaut de Google. Mais il n’existe plus sur Google Play, et je me méfie comme de la peste de tous ces sites de téléchargement d’APK. Donc pour l’instant, j’utilise le clavier par défaut. Moins bien, mais disponible (et aucun des autres que j’ai pu essayer, Swiftkey, Dasher, et autres ne m’a réellement convaincu).

Bon, et puis il y a un autre souci, mineur celui-là. J’aimerais bien remettre Adaway, mais je dois pour ça rooter mon téléphone, et je n’ai pas encore trouvé la bonne méthode. Mais je suis sûr que je vais trouver …