4 jours et 2 nuits de déploiement

Tycho's Supernova Remnant: Tycho's Remnant Provides Shocking Evidence for Cosmic Rays (The hot, expanding debris of a supernova observed in 1572.)

Les 4 derniers jours de 2009 nous avons déployé notre progiciel de gestion intégré ALIX dans le dépôt principal de l’un des grossistes majeurs en pharmaceutiques en Tunisie. C’est une opération pour laquelle nous nous sommes préparés toute notre vie… Ou presque, étant donné qu’au décompte final le projet a duré 3 ans et demi. Pour aboutir a ce déploiement qui consacre ALIX comme seul système d’information dans toute l’entreprise et sonne le glas de tous les autres logiciels utilisés de la production au recouvrement.

Une semaine avant…

Je venais de rentrer de Beirut, et ce weekend nous avions un inventaire dans le petit dépôt du client. Le système ALIX était déjà en production depuis plus d’un an dans ce dépot, mais c’est toujours délicat un inventaire. Parce que justement c’est 1 fois l’an et que par conséquent on n’a pas souvent l’occasion de le tester en production. De plus, suite au dernier inventaire nous avons fait des modifications majeures sur le système et aux procédures; et c’était donc du code frais que nous allions utiliser.

Tout s’est bien passé. L’enjeu principal dans les inventaires, qui restent sommaires au niveau applicatif, c’est le temps. Ce jour là nous avions fini plus tôt que prévu. Ce qui nous réconfortait dans nos choix et nous rassurait sur le plus important : le déploiement final dans le grand dépôt dont la date n’était toujours pas fixée mais qui était imminent.

Etant donné que nous avions fini tôt, M. Bechir qui supérvise le projet ALIX pour notre client, improvise une petite réunion. Il nous éxplique qu’il est satisfait et qu’il propose de déployer la semaine prochaine dans le grand dépot. Nous allons faire le déploiement dans les règles de l’art au début de l’année fiscale, ce qui avait l’avantage de limiter de façon radicale le risques de géstion liés au changement de système en cours d’annèe fiscale et d’intègration de données à partir de l’ancien système (forcément).

Avec Bechir et Hassen (l’équipe ALIXSYS, au cas ou vous seriez nouveau sur ce blog. Par ailleurs, ne pas confondre Bechir avec M. Bechir le client) nous avions déjà discuté de cette éventualité et avons conclu que nous étions préts. J’ai donc accépté.

Or rien n’était prêt. Les stations de travail et leurs périfériques qui devaient étre changés n’étaient pas inventoriées, le matériel n’était pas encore commandé, le chantier du réseau avait à peine commencé et il fallait encore des semaines pour qu’il se termine.

Heureusement qu’avec ce projet, j’avais appris quelque chose d’essentiel : le zen. Les choses se passent toujours mieux que prévu… si on se prépare pour le pire. Le truc c’est de ne pas essayer d’éviter le pire, il faut économiser ses éfforts pour être prêt quand le pire arrivera. J’ai donc proposé de déployer sur le réseau en place avec le matériel en place. Le raisonnement était qu’il est trop tard pour organiser quoi que ce soit qui implique une étude ou ne serait ce qu’une simple réflexion : nous allions mettre en place le matériel essentiel, c’est a dire les 2 imprimantes industrielles et stocker des stations de travail et des périphériques de rechange prêts a être déployés dés qu’il y a un problème matériel quelque part dans le dépôt.

Makram, le responsable informatique du client, n’était pas d’accord. Il n’y avait rien à faire pour le réseau, mais pour le côté matériel il estimait qu’il était possible d’inventorier les machines dépassées, les remplacer et switcher toutes les stations de travail sous Linux la nuit de l’inventaire. Et comme tout ce volet est sous sa responsabilité, il avait le véto. Nous allons donc faire comme il dit. Et nous allons voir qu’il avait raison.

La semaine suivante je l’ai passée a préparer 3 checklists : 1 pour l’inventaire, 1 pour le déploiement et 1 timeline. Ce travail a consisté a tester le système pour les cas d’utilisation de l’inventaire et du déploiement et faire une liste des points a vérifier et les taches a faire pour que tout se passe bien. Ensuite ces points sont discutés avec Hassen et Bechir qui enrichissent la liste avec leurs remarques. Nous avons fait cela tous les jours pendant toute la semaine. La timeline était subdivisée en 4 jours et etait mise a jour au fur et a mesure avec les taches qui devaient se faire un jour précis. Bechir et Hassen s’occupaient de régler les problèmes qui pouvaient être réglés tout de suite : certains détails de la procédure de déploiement pouvaient être réglés par des changements sur les application, notamment l’application d’intégration de données avec les anciens logiciels. A vrai dire il y a des défauts que nous avons découvert à ce moment là et qu’il fallait régler aussi.

1 pour le déploiement, 1 pour l’inventaire et 1 timeline

Week-end de l’inventaire : problèmes d’intégration de données

L’inventaire devait se faire le week-end, comme tous les ans, pour ne pas impacter la production. Le vendredi nous avons commencé a préparer le système, y compris les personnes en leurs donnant les instructions nécessaires. Les procédures d’inventaire se basaient principalement sur du papier mais avaient significativement changé et impliquaient maintenant plusieurs utilisateurs du système dans la saisie et le contrôle du déroulement en temps réel.  Nous avons fait en sorte que l’encadrement des utilisateurs soit fait par le personnel de l’entreprise qui est déjà formé. Le but étant qu’on soit disponible en cas de problème. On ne ferait donc rien. Et ça sera très bien comme ça. Et nous n’allons pas tarder a confirmer l’utilité de cette approche.

L’inventaire commence par le décompte des quantités physiques des articles en stock et se finit par leurs comparaison avec les quantités informatiques (prévues). Pour pouvoir commencer le décompte le plus tôt possible (lundi matin étant une date butoir : reprise d’activité) , nous avons choisi de faire une intégration des données en deux étapes. Nous allions intégrer les données des articles a partir de l’ancien logiciel de stock vendredi soir (ils ne risquaient pas de changer) et les données de l’état des stock samedi quand il n’y aurait plus d’activité dans le dépôt.

Samedi matin on vient, on fait rien, aucun problème. Samedi après midi, on intègre les données de l’état des stock et BANG! Nos états de vérification nous disent que les données intégrées ne correspondent pas aux informations données par l’ancien système. On a bien fait de rester disponibles. On a bien pensé que le bug serait facile a trouver au début,… à 1h du matin on était encore au bureau. Et vous savez le PC DOS virtualisé qu’on avait mis en place il y a presque 1 an pour convertir les listings de l’ancienne application? Eh bien, il nous a encore sauvé la vie. Après inspection minutieuse, il y avait au moins une dizaine de différences de plusieurs types dans les articles. Tous des problèmes d’intégration, aucun bug, et parfois des erreurs de jugement : dans le paragraphe précédent j’ai dit « ils ne risquaient pas de changer », eh bien ils ont changé les prix des articles.

Le dimanche matin, nous étions là. L’état du stock informatique intégré a partir de l’ancienne application était conforme et vérifié. Tout allait bien. Dans ma timeline, je vois : « dimanche : Installer le matériel de déploiement ». Étant donné que Makram avait décidé de switcher toutes les stations de travail à Linux, ça allait être le grand soir. L’après midi l’inventaire était bouclé sans incidents, ce qui représentait un temps légèrement inférieur aux inventaires pratiqués avec l’ancien système. Les utilisateurs directs et indirects étaient satisfaits. Le soir nous étions très fatigués nous sommes arrivés a installer tout le matériel, a convertir presque toutes les stations de travail à Linux et les configurer pour qu’ils se connectent sur l’application web ALIX. A vrai dire Makram et Hassen on fait presque tout le boulot. Nous avons désigné Bechir pour venir le lendemain a 6h du matin pour le déploiement : c’est à cette heure là que commence l’activité. Il fallait que quelqu’un se dévoue.

Bechir est capable d’analyser l’output d’une requête SQL en temps réel. Comme dans Matrix.

Premier jour d’utilisation : 1 processus et 2 interfaces utilisateur changées à chaud

Le 1er utilisateur du système fut M. Hmida, opérateur du centre d’appel qui commence sa journée à 6h du matin. Quand il a débarqué le paysage du dépôt avait complètement changé, sur sa station de travail aussi. Bechir était là pour le rassurer. Le premières commandes furent livrées sous la surveillance de Bechir, et en toute sérénité. C’est vers 9h quand tout le monde a débarqué, y compris Hassen et moi même, que les choses ont commencé a se corser.

Le serveur a commencé a échouer la baleine (en argot geek, ça veut dire avoir des problèmes de surcharge. voir Fail the whale). Le système était a la limite de l’inutilisable. C’était le bordel. Les commandes partaient en retard, le contrôle qualité était fait à l’emporte pièce. C’était le bordel.  Ça nous a pris 1 heure pour diagnostiquer le problème : 1 tableau de bord utilisé par ~50% des utilisateurs, notamment par les contrôleurs qualité,  bouffait les ressources comme pas possible. Réunion de crise : mesure d’urgence : rallonger le temps de rafraichissement des indicateurs. Ensuite discussion :

  1. Cette interface est irrécupérable. Elle doit afficher les commandes en cours avec leurs états en temps réel. Autant dire toute l’activité du dépôt. Elle traite énormément de données et on aura beau optimiser, on ne gagnera pas beaucoup et ça prendra du temps.
  2. Cette interface est utilisée par deux rôles dans le système : les contrôleurs qualité (en large majorité) et 8 magasiniers
  3. Les contrôleurs qualité (CQ) n’utilisent en fait qu’une seule fonctionnalité de l’interface et qui ne consomme pratiquement aucune ressource

En 15 minutes nous avons fait une nouvelle interface pour l’armée des CQ, en 15 minutes nous l’avons testée, en 15 minutes nous l’avons déployée, en 30 minutes nous les avons formés. Ce sont les joies du MVC et de l’architecture RESTful. Ce fût une réussite : la charge du serveur est tombée de moitié. Les CQ ont même préféré cette interface, évidemment : elle est plus simple.

Si nous avons pu faire cette interface aussi rapidement, c’est qu’elle fait partie d’une catégorie de tâche que nous avons classée dans notre wiki dans : « Les tâches que nous n’aurons jamais le temps de faire ». Nous avions bien identifié un problème d’ergonomie dans cette interface (les CQ n’utilisaient que 0.1% de cette interface), nous avions bien discuté et trouvé une solution élégante, mais rien ne justifiait de leurs faire une interface propre jusqu’à maintenant. Parce que l’ergonomie n’est pas une science exacte et :

  • Nous n’avions reçu aucun feedback négatif de la part des utilisateurs (testeurs)
  • Du point de vue de l’expérience utilisateur, plus il y a d’utilisateurs qui utilisent une interface, mieux c’est. Ils s’entre-aident. C’est l’effet communauté. C’est pour cela que je pense, par exemple, que les interfaces personnalisées sont généralement mauvaises du point de vue de l’expérience utilisateur.

Hassen en vitesse de croisière

Changer les procédures au nez et à la barbe de ISO9001

Le système était redevenu utilisable, d’autant plus que l’heure de pointe pour l’activité est passée. Tout allait bien, ou presque… Malgré le fait que ALIX fonctionnait bien, les commandes continuaient à prendre un léger retard. A première vue, ça bloquait au niveau de la préparation des commandes. Une petite inspection sur place pour prendre le pouls des utilisateurs, à permis très vite d’identifier le problème. La procédure était trop lourde et les commandes s’accumulaient au milieu du magasin.

Par rapport au petit dépôt sur lequel ALIX s’était fait les dents, ce dépôt si est énorme. Il est subdivisé en 8 zones, dont 3 sont contiguës et numérotées 1,2,3.  La procédure imposait une validation au début et a la fin de chaque zone. Mais voilà, le zones 2 et 3 étaient dépendantes de la zone 1 : on ne pouvait commencer la zone 2 qu’après avoir fini la zone 1. Ce qui fait que dépendamment des commandes, le magasinier  de la zone 2 pouvait terminer une commande et revenir au début de sa zone pour se retrouver avec 5 commandes en attente et d’autres qui arrivent (ça peut prendre beaucoup de place). Ce qui ajoute a la confusion c’est qu’il doit aussi gérer se propres priorités et renseigner le système. Ce n’était clairement pas faisable. Et les commandes s’accumulaient en zone 2.

Ce qui est incroyable c’est que cette procédure était en place depuis des années et était même documentée et certifiée ISO9001, mais l’ancien système de gestion de flux – développé par nous mêmes d’ailleurs. Une ancienne version de ALIX – permettait de la contourner. Ils validaient toutes les zones qui restent à la fin de la journée!!

Réunion de crise : mesure d’urgence : faire sauter la zone 2. Après avoir discuté des conséquences possibles, nous avons simplement dit au magasinier de la zone 2 d’ignorer le système et de faire juste son travail de préparation des commandes. Ensuite nous avons fait sauter quelques verrous par ci, par là, et nous avons entrepris de changer l’interface des magasiniers pour que ces trois zones se comportent comme une seule zone dans certains cas. Et tant pis pour ISO90001, il suivra. Cette dernière tâche prendra le reste de la journée et le lendemain matin.

La magie

Le lendemain la magie à opéré. Malgré le fait que le serveur continuait a faire des pics de charge a 10 (normalement le maximum c’est 1) tout marchait, les utilisateurs – bizarrement – ne se plaignaient pas, et les commandes étaient traitées au rythme normal comme si de rien n’était. Nous n’en revenions pas. On est restés sur nos gardes toute la journée, mais rien.

Bien sûr, il y avait encore plein de choses à faire, une longue liste de défauts a corriger, des fonctionnalités a ajouter, mais il n’y avait plus le bordel. Il faut comprendre que le plus grand défi dans un projet qui implique autant de personnes est logistique et organisationnel. Si la sauce ne prend pas, vous aurez beau faire, le projet sera un échec. Le utilisateurs sont inter-connectés procéduralement, si une partie refuse d’utiliser le système parce qu’elle estime qu’il est inutilisable, vous n’aurez pas le temps de corriger le problème avant qu’une autre partie n’arrête de l’utiliser parce que son utilisation du système dépend de la première.

J’avais planifié 2 jours de bordel, et ça s’est résolu en 1 jour. J’estime que c’est un succès notable. Mais pour rendre a césar ce qui appartient à césar, ce succès n’est pas le nôtre, c’est celui de l’entreprise qui a commandé le projet avec tous ses employés et ses gestionnaires que je tiens a remercier particulièrement. A vrai dire mon impression est que toutes les conditions du succès étaient là avant qu’on arrive.

Markkit : Le Stabilo pour le web - Globalnet Tunisie: fournisseur d’accès Internet et ADSL : actualités et informations
Interview vidéo de Slim Amamou : Tunisie : Shopping : High tech & Téléphonie : Tuniscope
Point d’identité sans discrimination

Ou j’explique que la discrimination est le seul mécanisme par lequel on crée de l’identité.

Les Collections sont des Objets fascinants. Supposons que vous soyez un collectionneur. De timbres. Vous ouvrez l’un de vos grands album, comme d’habitude, pour profiter du réconfort de la vision de vos timbres et souvenirs associés; bien rangés dans leurs pochettes. Mais voilà que cette foi, au beau milieu de l’album, vous trouvez une image autocallante panini. Vous vous en offusquez : Qu’est ce que cette image fait là?

Mais pourquoi est ce que vous pensez que cette image n’est pas a sa place, d’abord? Parce que ce n’est pas un timbre? Comment vous le savez? Il y a bien des timbres à l’éffigie de joueurs de foot, il y a bien des timbres autocollants, il y a bien des timbres de cette taille là, il y a bien des timbres sans dents. Qu’est ce qui fait que l’image autocollante est différente? Et surtout qu’est ce qui fait que les timbres sont Identiques? C’est fascinant une collection. Parce que tous les objets qui y appartiennent sont identiques; d’une certaine manière. Et en même temps, évidemment, différents.

En réalité pour Discriminer la simple image autocollante des timbres; vous vous référez probablement a différents Signes imprimés sur les timbres qui indiquent qu’une Autorité postale garanti leurs Authenticité.

Résumons :

  • Une collection c’est fait d’objets à la fois identiques et différents, un peu comme les Hommes
  • Si vous voulez identifier un ou plusieurs objets de la collection pour les exclure ou pour les classer dans une autre collection, ça revient a les discriminer des autres objets de la collection. En somme Identifier = Discriminer.
  • Quand il est impossible de discriminer – ce qui est courant vu la dichotomie Identité-Différence au sein d’une collection – on fait appel a une Autorité qui tranche arbitrairement.

Un modèle de société avec la personne en haut et la société en bas

Maintenant, j’ai 13 ans. Je construit mon Identité avec ce qui me tombe sous la main : musique, série télévisée, équipe de foot, religion, jeux vidéo, voir même quelques fois mes parents. C’est que je suis un être humain doué de conscience et que le mécansime d’identité est cablé dans mon cerveau par 3 000 000 d’années d’évolution. Ce n’est pas par hasard que l’évolution a séléctionné ce comportement : l’identité est le socle de la confiance et la confiance le socle de la société. Je ne peux pas faire confiance à quelqu’un que je ne reconnais pas. Par ce qu’il m’est impossible de me rappeler ce qu’il a fait dans sa vie (son Historique), ou qui est la personne qui me l’a fait connaitre (son Autorité supérieure). L’historique et la délégation d’autorité sont les deux uniques mécanismes pour bâtir la confiance.

Pour vivre en société je dois pouvoir Identifier les membres de ma société et leurs permettre de m’identifier. Pour cela j’utilise la discrimination : je commence par me discriminer moi même, construire mon Identité, ceux a qui je veux ressembler, j’émule. J’utilise les Signes.  Je porte un jean tombant, je suis un cholo. Je met du Khol, je suis un emo. Ensuite je discrimine tous ceux qui me ressemblent de ceux qui ne me ressemblent pas et je crée avec eux des liens d’Autorité. C’est cela une société.

Résumons:

  • Construire son identité c’est se discriminer soi même.
  • La fonction de l’identité dans une société c’est de permettre la confiance en assurant la reconaissance.

La France connait en ce moment un grand débat sur l’identité nationale. Mais que signifie Identité nationale? Est ce que cela a un sens? On pourrait imaginer ce modèle : Une société des nations (ou une collection de nations). Pour construire l’identité nationale, il faudrait discriminer sa nation des autres nations. Mais sur quels critères? On pourrait choisir quelques valeurs : liberté, égalité, fraternité. Ou alors instaurer une Autorité qui discrimine arbitrairement. C’est aux français de voir. L’identité nationale a donc bien un sens.

Il doit vous surprendre que la question de l’immigration n’a aucune relation proche ou lointaine avec le sujet. J’en suis surpris moi même. Il est évident qu’en créant un ministère de l’immigration et de l’identité nationale (entre autres), la France ne se facilite pas la tâche. Cela ne fait que brouiller les pistes et ajouter à la confusion. Logiquement l’identité nationale devrait être du ressort du ministère des affaires étrangères. Si on opte pour la solution de l’autorité de discrimination, bien sûr…

“Leaky abstractions” comme un art de vivre

La plus ancienne base de données du monde : un cimetière

La plus ancienne base de données du monde : un cimetière

La conversation a commencé juste après le barcamp . Nous sommes allés prendre un petit café, Jazem, Houeida, Hatem, Kais et moi; et la conversation avait tourné autour des bases de données. Plus tard la conversation à continué entre Kais et moi par messagerie instantanée. Et encore plus tard avec Pr. Hatem Ben Sta au Caire. Ce que j’essayais d’expliquer, en mode non structuré mais caractéristique des conversations en direct, c’est pourquoi je me méfie des ORM, pourquoi nous n’utilisons pas de framework à ALIXSYS et comment on fait.

Quand vous écrivez une application qui, d’un côté est basée sur un modèle objet, et d’un autre côté fait appel à une base de donnée relationnelle pour stocker les données, vous avez  la désagréable impression de vous répéter et que toutes ces lignes de codes ordonnant a vos objets de s’enregistrer sont de trop. C’est normal. C’est que, comme l’expliquait Dan Ingals (à moins que ça ne soit Alan Kay, citation approximative de toutes façons) : “Dans la vraie vie, quand on rempli un Verre d’eau, on ne lui demande pas de se “mémoriser” juste après. ça n’a pas de sens.” Un système basé sur un modèle objet devrait gèrer le stockage des données de manière transparente, sans intervention du programmeur.

Mais alors pourquoi les programmeurs persistent à utiliser des SGBDR ? Principalement par habitude, mais quelques fois aussi par souci d’intégration. En environnement d’entreprise, vous avez souvent ces conditions :

  • Un ou plusieurs SGBDR sont déjà déployés et en production
  • Les développeurs ont l’habitude de développer des applications basées sur SGBDR
  • Des applications décisionnelles (reporting, BI, etc…) sont déployées sur les SGBDR et le personnel est formé à leurs utilisation

En résumé SQL est un standard. Les gens ont tendance à l’oublier, mais SQL est probablement le standard le plus puissant du monde informatique. Le nombre de programmeurs qui parlent SQL doit être plus grand que ceux qui parlent HTML. SQL est plus puissant que HTML.

Écrire du code c’est écrire. En soi, ce n’est pas très différent d’écrire un poème, une facture ou sur un mur. Le but principal, au delà du langage, c’est de se faire comprendre; si possible par le plus grand nombre. Un standard est précisément fait dans ce but : pour que tout le monde parle la même langue. Et ça, ça n’a pas de prix.

Cette situation pose un dilemme : Objets ou SQL ? Et les réponses proposées sont :

  1. On abandonne la POO
  2. On abandonne SQL et on adopte smalltalk
  3. On abandonne SQL et  on adopte un système de stockage non relationnel
  4. On adopte un ORM
  5. La réponse 5 :)

Je vous déconseille de prendre le 50/50, je vous le donne en mille : ce sont toutes des mauvaises réponses. Mais ce sont là toutes les réponses envisageables à l’heure actuelle. Même si adopter smalltalk est tentant, vivre en autarcie n’est pas une option pour tous les projets. CouchDB, TokyoTyrant, BigTable et autres systèmes de stockage non relationnels ont le vent en poupe en ce moment, mais ils ne résolvent pas nôtre problème (Le stockage automatique et transparent des objets; juste pour rappeler). Il reste l’ORM. Qui résous bien partiellement le problème mais qui a l’énorme inconvénient de cacher SQL de la vue du programmeur. Ce qui est bien du point de vue des concepteurs d’ORM mais mal de mon point de vue.

Les standards aussi sont une écriture. Et à ce titre, je considère que leurs finalité c’est d’être lus, compris et appliqués par des hommes et non pas des machines. C’est ce qui fait la différence entre un bon standard et un mauvais comme SOAP et ses dérivés. On n’écrit plus du code comme en 1980, c’est devenu un travail collaboratif. En 1980 écrire du code ressemblait à une conversation privée entre vous et la machine. En 2009 écrire du code ressemble à un talk show : vous avez bien un animateur-ordinateur en face de vous, mais la conversation est devenue publique. Le code est devenu public. Libre. Formellement, vous vous adressez à l’ordinateur, mais pratiquement, vous vous adressez à d’autres programmeurs. Et tous ces programmeurs parlent SQL, ça serait dommage de ne pas en profiter.

Les “leaky abstractions” à la rescousse

Un Objet est une abstraction de très haut niveau. Elle permet de représenter toutes les choses de l’univers. Elle permet aussi de représenter plein d’abstractions de niveau plus bas. Avec un Objet, on peut tout faire. Notamment créer un Objet/Abstraction nommé Base de données.

Mais construire des abstractions est un art. Une bonne abstraction doit cacher ses détails. En mathématique, si j’utilise “n” comme abstraction pour représenter un nombre entier, c’est bien pour m’éviter de raisonner sur les 1, 2, 3 et autres 4 et 5 de toute la suite individuellement. Ce qui me serait impossible de toutes façons. “n” est une bonne abstraction parce que, avec, je peux prouver que la somme de deux entiers est un entier par exemple . Maintenant, si j’utilise le symbole ☹ comme abstraction pour représenter “tous les nombres contenant le chiffre 7 ou multiples de 666″, outre le fait que c’est complètement débile comme vous pouvez le constater, je ne peux rien faire avec mon ☹ sans devoir me rappeler ce qu’il représente. La suite 7, 17,  27, 37, 47, 57, 67, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 87, 97, 107, 117,  127, 137, 147, 157, 167, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 187, 197, 207, 217,  227, 237, 247, 257, 267, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 287, 297, 307, 317,  327, 337, 347, 357, 367, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 387, 397, 407, 417,  427, 437, 447, 457, 467, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 487, 497, 507, 517,  527, 537, 547, 557, 567, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 587, 597, 607, 617,  627, 637, 647, 657, 666, 667, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 687, 697, 707, 717, 7 27, 737, 747, 757, 767, 770, 771, 772, 773, 774, 775, 776, 777 est bien représentée par ☹ mais pour la créer j’ai du traiter séparément les 2 cas : 7 et 666. ☹ n’est pas une bonne abstraction.

Ce genre d’abstractions, Joel Spolsky les appelle “leaky abstractions“, littéralement “les abstractions qui fuient” comme un robinet,  parce qu’elles laissent transparaitre leurs charpente. Il va même plus loin, il théorise : “Toutes les abstractions non triviales fuient”. Si on examine les abstractions utilisées par Ruby on Rails pour son ORM, cela se confirme.

D’abord RoR fait une simplification : 1 classe = 1 table ce qui n’est pas toujours la solution optimale. Nous avons pu constater par exemple que avoir plusieurs classes utilisant la même table est une situation assez commune de par son optimalité. Par exemple, pour la plupart des systèmes vous avez plusieurs classes d’utilisateurs : Clients, Commerciaux, Administrateurs, etc… Nous avons trouvé que utiliser 1 seule table et plusieurs Classes pour les utilisateurs est une solution optimale.

Ensuite RoR utilise des abstractions du genre “has_many:”, “has_one:” pour représenter les relations entre les objets. Or ces abstractions sont très peu expressives pour représenter les relations entre les objets. Les objets peuvent avoir toutes sortes de relations : une Souris:mange(Fromage) un Chat:chasse(Souris) . Ce qui est exprimé en réalité dans RoR ce sont les relations sous-jascentes dans la base de données. Vous voyez la fuite (leaky abstraction)? Cela ne m’étonnerait pas que les programmeurs RoR finissent par construire leurs modèle objet en pensant aux tables qui vont être créées dans la base.

Quitte à avoir un modèle conscient de sa condition d’objet informatique volatile, nous allons le faire parler carrément SQL avec la base de données. Observez ce petit bout de code PHP :

$senefer = Creature::select("where name like 'Sanfour %'");
$ghadhbaan = new Creature("Sanfour Ghadhbaan");
$ghadhbaan->insert();

J’en vois certains qui sont en train de s’arracher les cheveux. Mais vous avouerez que la clareté de ce code est incontestable. Ce modèle déroge aux règles les plus élémentaires de la conception : le code est strictement lié au modèle de la base. Si on change la base on doit changer le code. Mais les autres ORM y dérogent aussi. Et j’ai horreur de faire semblant. Je préfère faire avec. Et vous verrez dans un moment que ce n’est pas si grave que cela.

La méthode select() est statique et c’est une factory. Elle génère des objets de sa Classe.

$senefer[0] instanceof Creature; //retourne TRUE

Ce genre de méthode dans sa plus simple expression est très simple à écrire :

class Creature
{
  static function select($options = NULL)
  {
    $resultats = self::$db->query("select nom from creatures $options");
    foreach ($resultats as $ligne) {
      $creatures []= new Creature($ligne['nom']);
    }
    return $creatures;
  }
}

Ici on voit bien la liaison stricte entre le code et la base. Mais dans la pratique, il est de toutes façons impossible changer la base sans changer le code d’une manière ou d’une autre. Ce qu’on fait, généralement, c’est confiner le code qui peut changer de manière à ne pas avoir à le chercher. Et dans cette optique, je trouve que le code est assez bien confiné dans cette simple méthode select(). Si par exemple il nous vient à l’idée de changer le nom du champ “nom” en “nom_et_prenom” dans la table “creatures”. Nous aurions simplement à changer le code comme suit :

class Creature
{
  static function select($options = NULL)
  {
    $resultats = self::$db->query("select nom_et_prenom as nom from creatures $options");
    foreach ($resultats as $ligne) {
      $creatures []= new Creature($ligne['nom']);
    }
    return $creatures;
  }
}

PHP est une simple couche au dessus de la base de données, comme aiment à le dire ses détracteurs. On se propose de l’utiliser comme tel et d’en tirer parti. Je ne concevrais probablement pas mon modèle de la même manière si j’écrivais du code en Scheme.

La méthode insert() est dynamique. Dans sa plus simple expression l’implémentation ressemblerait à :

class Creature
{
  function insert()
  {
    $nom = $this->nom;
    self::$db->query("insert into creatures (nom) values('$nom');");
    return $this;
  }
}

Pour formaliser tout cela nous pourrions faire une petite interface :

interface presistance
{
  public static  function select($options = NULL);
  public function insert();
}

C’est tout ce dont on a besoin.

Ou sont passées update() et delete() ?

Nous avons pu constater, au bout de quelques années d’expérience quand même, que supprimer des données dans une base de données n’était pas du tout naturel. Le plus souvent les données sont plutôt marquées comme “supprimées” (ou annulé ou désactivé etc …). Dans les faits la requète “delete” est plutôt une requêtes de maintenance (optimiser la performance de la base) et de ce fait, dans la plupart des cas ne fait pas partie du système.

Nous avons pu constater aussi que les opérations de mise à jour des données “update” sont souvent complexes, impliquent plusieurs tables à la fois et quelques fois même transactionnelles. Une opération update() qui synchroniserait l’objet avec ses tables dans la base de données, dans la pratique, serait mieux implémentée conceptuellement comme une suppression (ou annulation ou désactivation etc…) suivie d’une nouvelle insertion. Par contre l’opération de suppression de l’objet utilisera forcément la requête  “update” formulée dans une méthode spécifique à l’opération :

class Creature
{
  function tuer()
  {
    $nom = $this->nom;
    self::$db->query("update creatures set supprime='oui' where nom='$nom'");
    return $this;
  }
}

Cette méthode est capable de tuer un sanfour. Ce qui est une prouesse : on n’a jamais vu un sanfour se faire tuer. Mais tuer() est la méthode appropriée pour supprimer un sanfour.

Cette conception a été utilisée sur plusieurs projets et si je vous en parle maintenant c’est que nous avons pu tester son efficacité et sa simplicité. Ce dernier point est très importants pour nous. Veuillez observer ce schema illustrant notre process :

Process ALIXSYS

Process ALIXSYS

Si j’ai mis “Former les développeurs” ostentatoirement au début du process, c’est pour insister sur la consommations de resources en amont et combien il est important d’optimiser cette activité. Vous me direz : mais vos développeurs sont déjà formés. Oui, mais on recrute.

Quand nous avons fait la refonte de notre progiciel de géstion intégrée ALIX, il y a quelques années quand nous étions un département R&D dans une autre société, l’objectif principal identifié était de simplifier son accés aux programmeurs novices. ALIX était un système assez complexe avec une base de code assez importante qui faisait que quand on écrit du code pour ALIX on a à peine l’impression d’écrire du code PHP ou HTML : tout était caché derrière les bibliothèques et l’architecture du système elle même compliquait les choses. Nous avons tout reconçu depuis le début pour que quelqu’un qui a des connaissances rudimentaires en PHP puisse s’y retrouver dans le code et se faire utile très rapidement. C’était un impératif pour nous car nous avions un turnover assez important et nous recrutions souvent des jeunes diplômés.

Aujourd’hui ce n’est plus un impératif, mais cette expérience m’a permis de me rendre compte que avoir un système simple avec une base de code accessible donne un avantage compétitif certain. Prendre un frais diplômé et le rendre opérationnel comme développeur sur le système en 3 mois est certainement le trait conceptuel le plus attrayant du système ALIX. Et j’en suis très fier.

Cependant je ne suis toujours pas tout à fait satisfait. On peut aller plus loin. Et pour la version 3 de ALIX, je compte le débarasser de tout son code. ALIX sera alors un pur processus. Le rève.

Ma présentation au BarCamp Tunisie 2009
BarCampTunisia 2009

6548_b293_400

BarCampTunisia 2009

[Reposted from slim]

BarCampTunisia 2009

6464_0a71_400

BarCampTunisia 2009

[Reposted from slim]

BarCampTunisia 2009

6459_6a7f_400

BarCampTunisia 2009

[Reposted from slim]

BarCampTunisia 2009

6366_c158_400

BarCampTunisia 2009

[Reposted from slim]