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

6545_6dee_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]

BarCampTunisia 2009

6322_1586_400

BarCampTunisia 2009

[Reposted from slim]

BarCampTunisia 2009

6329_be4b_400

BarCampTunisia 2009

[Reposted from slim]