31 juillet 2006

Lafraise.com : Success Story

1er mars 2004 :
Voir : en bas de la page d'archives http://www.lafraise.com/blog/2004/03/index.php


19 juillet 2006 :
(...) je viens de signer la vente de Lafraise, à Spreadshirt et qu'une page va bientôt se tourner, dans ma courte vie.
Voir : l'article intitulé «Ma retraite à 35 ans», au milieu de la page d'archives http://www.lafraise.com/blog/2006/07/index.php


Lafraise.com. Voir les détails magnifiques de la création de la boîte en plongeant dans ledit blog. Après 3 ans d'activité commerciale web personnalisée -- eh oui, c'est ça la technologie au service des gens -- Patrice arrivait à 80 kEUR de CA mensuel, et finalement revend.

Cette histoire est exemplaire, magnifique. Bien, bien, avant les 80 kEUR de CA, c'était tout simplement un exemple, THE exemple, de comment on pouvait comprendre internet. La revente de ces derniers jours clôt le chapitre de façon pragmatique.

27 juillet 2006

Achats IRL vs. achats online

L'autre jour j'achète une imprimante(*).
Je prends la voiture, je vais chez Surcouf, j'achète, je repars.
Au moment de déballer l'engin, pour une sombre histoire de détails sur les caractéristiques, je regarde sur surcouf.fr. J'y vois la bête 70 EUR moins chère qu'en ville. Mazette me dis-je.
Je reprends la voiture, je vais me faire rembourser, puis je me fais livrer par le net.

Quelques jours plus tard j'achète un disque dur(**).
Donc là j'ai bien compris le truc, je regarde d'abord sur le net, et je vais au magasin pour comparer. L'appareil y est à 10 EUR moins cher que sur le net, mazette.

Çà alors !


(*) Brother HL-5250DN, laser N&B, réseau, compatible MacOS / MacOS X / Win XP, silencieuse, stable, 20ppm recto-verso, imprimante que je vous recommande du reste.
(**) Non, je ne prévois pas mes achats à l'avance, quelle idée.

25 juillet 2006

Blogger : publication différée

C'est quoi ce bug ? On ne peut pas faire proprement de publication différée sous Blogger ?
Si je prépare des notes le 23/07, ce n'est pas pour les voir apparaître comme datées du 23 alors que je les publie le 25 !

23 juillet 2006

Quand une plateforme blog tombe en panne: le cas TypePad

Via pointblog : Panne mondiale pour TypePad ?

En deux mots, les blogs TypePad étaient accessibles en lecture, mais les auteurs ne pouvaient pas poster de nouveaux messages. C'était le 12 juillet, et ça a duré moins d'une journée.

C'est exactement ce qui se passe quand la consultation des messages se fait depuis un cache applicatif réparti mais avec une publication de messages centralisée. C'est le choix suivi pour le lancement des Fûts. Ce n'est pas le cas d'un système NNTP comme Usenet par exemple.

Tout ça pour dire qu'intégrer toute la logique NNTP au phénomène des blogs, serait une bonne grosse révolution. Redondance, fiabilité, pérennité.

Sans parler du cross-blogging dans les commentaires, qui est une sous-partie de ce qu'apporte NNTP, et qui pour le coup est dans les principes initiaux des Fûts. Mais c'est applicatif. La révolution devrait porter sur l'infrastructure, pas seulement sur l'applicatif.
Et qu'on ne me parle pas de RSS ! cette espèce de tam-tam XML, où «chacun» est responsable de faire la réplication des informations. RSS est applicatif. Ce n'est pas du transport, il faut arrêter cette confusion.

Un peu de distribution PHP/Java

On teste la publication d'un message sur un forum des Fûts, avec des appels synchrones uniquement, en mode DEBUG et en mono-thread.
Les appels distants pour la publication d'un message sont les suivants :
  1. PHP notifie Java que des commandes sont à traiter
  2. Java récupère auprès de PHP les commandes à traiter (en lot)
  3. Java réserve auprès de PHP une nouvelle version des données («locked rev»)
  4. Java sollicite PHP pour chaque message posté : prise en compte des données dans la rev applicative, calcul des threads
  5. Java relâche la rev auprès de PHP
  6. Java indique à PHP que les commandes sont traitées (une par une. Petit bug)
Total pour un message : un appel distant de PHP vers Java, 5 appels distants dans l'autre sens.

En cible, 1./2. forke.
Pour les tests, 1./2. est synchrone.

Voici les temps de réponse :
  1. PHP/PC ---(local)---> Java/PC
    moyenne 1356 ms, écart-type 64 ms (5 %)
  2. PHP/PC ---(LAN)---> Java/minimac
    moyenne 6988 ms, écart-type 2828 ms (36 %)
  3. PHP/free.fr ---(internet)---> Freebox ---(LAN)---> Java/PC
    moyenne 3266 ms, écart-type 1191 ms (36 %)
  4. PHP/free.fr ---(internet)---> Freebox ---(LAN)---> Java/minimac
    moyenne 7778 ms, écart-type 3672 ms (47 %)
Axes d'améliorations :
  • Mettre une vraie machine en frontal SOA DMZisé. Le «minimac» PPC patine quand on veut lui faire faire du J2EE.
  • Penser à un serveur hébergé.
Urgence :
  • Aucune. Depuis quand 10 secondes pour poster un message sont-elles un délai rédhibitoire sur le web ? ;-)

21 juillet 2006

Tests de mini-scénarios web

Pour le développement, il y a une catégorie de tests qui se déroulent sur des scénarios, c'est-à-dire des enchaînements de pages. On procède ainsi :
  1. on décrit la suite de pages du site web à tester. Soit en donnant explicitement les URLs, soit en indiquant quel clic simuler, soit en indiquant quel formulaire soumettre.
  2. pour chaque page, on donne la série de tests à passer sur le HTML : validité du HTML, contenus attendus, contenus interdits...
  3. pour chaque page, on donne la série de tests à passer sur l'état de la base : le test le plus simple étant de contrôler le nombre de lignes dans certaines tables.
Note : c'est assez différent de la «fermeture Hyper Texte», qui valide que tous les liens à l'intérieur d'un site sont cohérents, mais qui concerne davantage un site statique qu'un site dynamique.

Voici les écrans qui résument les résultats des tests sur scénarios.

Tout d'abord l'écran global, qui montrait dans sa première version les résultats de validation HTML, et qui montre maintenant en sus les résultats de validation DB :


La colonne «v.» donne le nombre total de tests pour chaque page, HTML et DB confondus.
En rouge, le nombre de tests qui ne passent pas.

Puis l'écran qui résume l'évolution de la base au fil du scénario :


En lignes les tables, en colonnes les étapes du scénario (les actions SUBMIT sont indiquées), et à l'intérieur du tableau les nombres de lignes dans chaque table. Quand le test ne passe pas (en rouge), on indique le nombre de lignes attendu et le nombre réel.

16 juillet 2006

Les joies de l'intégration

Une servlet avec du joli code Java qui marchait bien sur de l'Intel Core Duo, ne fonctionne plus après déploiement sur un Mac mini PowerPC G4.

Je n'arrive plus à lui dire de lire plusieurs octets à la fois en HTTP :
final InputStream is = socket.getInputStream();
// Ne fonctionne pas sur le Mac mini :
// final int byteCount = is.read(bytes, 0, 4096);
// --> SocketException: Illegal Argument
final int b = is.read(); // Pour le Mac Mini.

Résultat de ce changement : perfs -11%


Ah, et incidemment, toujours sur des tests en LAN, le déploiement de la servlet sur le PowerPC G4 rend l'ensemble 2,6 fois plus lent qu'avec le déploiement sur le Core Duo.
  • PC : Core Duo 2,8 GHz / 2 Go, Windows XP, JDK Sun 1.4.2_11, Tomcat4
  • Mac : G4 1,25 GHz / 512 Mo, NetBSD 3.0, JDK Blackdown 1.3.1, Tomcat4

12 juillet 2006

Associations et Web Agencies

Je vois en ce moment des associations se faire démarcher de façon assez agressive par des Web Agencies françaises, qui leur proposent de monter des sites web rapidement, facilement, et économiquement.

À l'adresse de ces agences, je pense que le secteur de marché est bon ;-)

Cela dit, au vu des sites de ces boîtes, ce qu'elles proposent relève davantage du CMS que de l'outil collaboratif.

Où est la plus-value ?

1. Dans la qualité ?
Les associations s'en fichent un peu.

2. Dans le prix ?
Leur prix est standard : 3000 ~ 3500 EUR pour un site institutionnel d'une dizaine de pages.
L'approche commerciale agressive est de proposer un «partenariat». En gros : donne-moi ton fichier client et je te fais une méga-ristourne.

Je ne mettrai pas de lien vers les sites de ces agences. Ce n'est pas pour éviter de leur faire de la pub, mais par respect des contacts associatifs qui m'en ont parlé.

J'ai quand même le droit de mettre un lien, celui de Médiacité, qui a la bonne approche à mon avis : «Notre vocation est de répondre aux besoins de communication publique et de promotion territoriale».

Ils ne font pas partie des agences qui démarchent, donc je peux en parler :-)

Pourquoi est-ce la bonne approche ? Parce qu'en étant spécialisé dans la promotion territoriale, le financement peut être mixte. Et ça, c'est très clairement un élément différenciateur :-) Cela dit pour des petits sites, je ne sais pas si le modèle reste bon. Ah, on me fait signe que oui. Alors oui.

Techniquement, d'après ce que j'en ai vu, eux aussi font du CMS.

Plateformes de blog : Gandi

Je viens de créer un blog chez Gandi, vu que j'y gère le domaine halfj.com.

L'URL : http://blog.halfj.com/.

Ma première impression est plutôt mitigée.

"Il y a du potentiel" (façon 2.0 de dire que l'interface est compliquée).

09 juillet 2006

Outil de diaporama

Une des demandes du Jardin Sauvage (tiens, ça me fait penser qu'il faudrait publier un compte-rendu de la réunion, un jour) était de pouvoir mettre en ligne des diaporamas. Avec fond sonore s'il vous plaît.

J'ai trouvé Lightbox JS V2.0, ça a l'air assez fort.
C'est du pur JavaScript, uniquement côté client, non intrusif pour le reste du code HTML de la page.
Voir des exemples d'utilisation sur le blog de parapente Le rêve d'Icare.

Qu'en pensez-vous ?

Connaissez-vous d'autres produits pour faire des diaporamas ?


Quant à la lecture des MP3, le Dewplayer s'impose, à mon avis.

Perfs de la couche présentation

Avant de passer aux appels distribués PHP/Java, voici quelques mesures de temps de traitements applicatifs PHP sur le forum en l'état.
Ces mesures font apparaître les temps hallucinants dus à la couche de présentation.

Pour rappel, aujourd'hui :

1. Le traitement applicatif PHP remplit des DataBeans, c'est-à-dire des objets qui n'ont que des méthodes getXxx() et setXxx().

2. Le relais est ensuite passé à la couche de présentation, qui sérialise les DataBeans en XML par la méthode «toXml()». Pour de sordides raisons de limitations de PHP, on normalise le résultat en UTF-8 propre, avant d'appliquer la XSLT qui a servi au maquettage XHTML. On renormalise ça en UTF-8 propre, puis on formate le XHTML en HTML 4.01 «optimisé». Cela fait 5 passes où l'on utilise XML.

Ce sont ces passes qui prennent du temps.


Les mesures ont été faites en une heure, sur des écrans de consultation en mode debug, avec le jeu de données «dataset-005» (ça, c'est pour les intimes).
On a testé l'affichage d'une liste de 3 forums, l'affichage d'une liste de 38 messages dans un forum, en tri par date puis en tri par enfilade, l'affichage d'un message, avec une liste sous-jacente en tri par date puis en tri par enfilade.



1. Liste de 3 forums

XML du DataBean sérialisé : 13 Ko
HTML : 14 Ko
Temps total : 612 ms
Couche applicative : 226 ms (37%)
Couche de présentation : 374 ms (61%)

2. Liste de 38 messages, tri par date

XML du DataBean sérialisé : 29 Ko
HTML : 70 Ko
Temps total : 1400 ms
Couche applicative : 341 ms (24%)
Couche de présentation : 1042 ms (74%)

3. Liste de 38 messages, tri par thread

XML du DataBean sérialisé : 29 Ko
HTML : 59 Ko (il y a moins de lignes de séparation dans la table qu'en tri par date)
Temps total : 1275 ms
Couche applicative : 335 ms (26%)
Couche de présentation : 925 ms (73%)

4. Un message, avec liste sous-jacente triée par date

XML du DataBean sérialisé : 18 Ko
HTML : 23 Ko
Temps total : 924 ms
Couche applicative : 307 ms (33%)
Couche de présentation : 605 ms (65%)

5. Un message, avec liste sous-jacente triée par enfilade

XML du DataBean sérialisé : 18 Ko
HTML : 23 Ko
Temps total : 943 ms
Couche applicative : 340 ms (36%)
Couche de présentation : 587 ms (62%)

6. Répartitions moyennes détaillées :
  • Couche applicative : 31%
  • Couche de présentation : 67%
    • Sérialisation du DataBean en XML : 2%
    • Transformation XSLT : 29%
    • Formatage du HTML : 22%
    • Temps total des deux renormalisations en UTF-8 : 14%




Les pistes d'optimisations sont les suivantes, :

1. Ne plus s'appuyer sur XML pour la couche de présentation.

C'est-à-dire construire directement le HTML en PHP en une passe, au lieu d'utiliser XML sur 5 passes. C'est fou comme c'est plus rapide le PHP, si, si. On devrait gagner entre 50% et 60%.

Néanmoins il faut garder la skin XSLT, est passer des UAT avec, car c'est la seule qu'on ait aujourd'hui qui soit corrélée à un maquettage hors serveur.

2. Faire la mise en page davantage en CSS plutôt qu'en HTML.

On gagnera évidemment d'autant plus de temps que le HTML sortant sera proche d'un bête dump du DataBean.

2.1. Passer à des entités numériques (é) plutôt que codes (é) quand on y gagne. Sur «é» (é), on gagne 2 octets.

Le fait de ne transférer que des octets sur 7 bits n'est pas négociable. Donc autant gagner sur la taille des entités.

3. Afficher plusieurs messages par page.

S'il faut une seconde en dev (2 sec. en prod) pour afficher un message, ça va faire cher de la discussion.
Il faut impérativement permettre de lire les messages par lots.




Quand seront faites ces optimisations :

4. Pas avant l'automne.

Les optimisations 1 et 2 ne sont même pas critiques pour les premiers utilisateurs. On a des temps de réponse de l'ordre de 1,5 sec. sur poste de développement, donc de 3 sec. en production. Je parie que ça passe.

Pour l'optimisation 3, là, c'est sûr, ça va se voir. Cela dit, arrivons d'abord au béta-test.

08 juillet 2006

Navigation structurelle

Je ne parle pas là de la localisation dite «chemin de fer» de type «a -> b -> c» en haut des pages qui indique à quel niveau de l'arborescence du site on se trouve.

Je veux parler des facilités de navigation au sein d'un site ou d'un sous-site offertes par certains navigateurs.

Dès qu'on navigue dans une liste, on doit avoir des liens «Premier élement», «Élément précédent», «Élément suivant», «Dernier élément», et «Retour à la liste».

Les liens <a> correspondants doivent avoir un attributs«rel», respectivement à "first", "prev", "next", "last", et "up".

Et la partie <head> de la page doit contenir des <link> avec les mêmes attributs. Cela permet à iCab, Opera ou Mozilla, d'afficher ces liens de façon uniforme, dans leur «Site Navigation Toolbar» (Mozilla), encore appelée «Navigation bar» (Opera).

L'article de Jajob Nielsen sur iCab sur le sujet : http://www.useit.com/papers/icab.html

Je me demande : qui utilise ces liens pour surfer sur le net ?

Pour un intranet, ça a davantage de sens à mon avis. What do you think?

03 juillet 2006

Passage facile à Eclipse 3.2

Eclipse 3.2 : 120 Mo en téléchargement.
Copier/coller du plugin pour Subversion depuis la 3.1.2, et redémarrage sans aucun problème.

C'est beau, la technique.

29 juin 2006

Sessions et contextes de navigation (2)

Mais non, ce n'est pas compliqué.

La session, c'est l'endroit où l'utilisateur fait ses actions.
Elle sert à logger les actions qui ont lieu dans une « unité de connexion », c'est-à-dire entre le moment où l'utilisateur se connecte -- il peut même s'identifier, on ne lui en voudra pas --, et le moment où il se déconnecte -- avec un beau timeout si besoin.
La session permet de rapprocher des actions entre elles, en disant en gros qu'elles sont l'œuvre du même utilisateur.

Les sessions inactives sont effacées au bout de, euh... d'un certain temps.

Le contexte de... données ? de page ? Ce sont des données mises dans un cache temporaire, au sein de la session.
Ce sont des données qui ne bougent pas au sein d'une « unité de consultation ».
Par exemple, lorsque l'utilisateur rapatrie une liste de messages, soit en se connectant une première fois, soit en cliquant sur « Rafraîchir », soit en effectuant une recherche, cela crée un contexte au sein de la session. L'utilisateur peut naviguer dans la liste, y lire des messages, la liste reste immuable. En particulier, elle n'est pas impactée par l'arrivée éventuelle de nouveaux messages dans le système. Il faut pour qu'il y ait un tel changement, un rafraîchissement explicite.

Pour ne pas dupliquer les données, ces contextes s'appuient sur des données « versionnées ».

Et pour ne pas faire exploser la base applicative, les contextes de données sont effacés au bout de, euh... disons que quand ça explose c'est trop tard.

Le contexte de... navigation ? de page ? Ce sont des informations de type contexte, qu'on accepte de véhiculer de page en page, pour éviter d'avoir à stocker trop d'informations en base.
Ce contexte suit une « unité de navigation ».
C'est typiquement un type de tri, qui peut être changé à l'affichage, même s'il impacte la navigation, sans avoir à recharger la liste.

Les contextes de navigation sont propagés de page en page, à condition de ne pas s'être vautré dans le code HTML.

Seule la session peut être suivie par un cookie. Et encore, ça coince dans le cas où deux sites sont sur le même serveur.
Le cookie sert donc davantage à la session multi-serveurs.
Hrem... Vaste sujet.


Ainsi, avec les contextes de données on peut faire du multi-écran et naviguer dans deux listes de résultats de recherches différentes, et avec les contextes de navigation on peut naviguer de façons différentes dans une même liste.

C'est super simple, non.

26 juin 2006

Onduleur

Installation de prises parafoudres pour les postes de travail, et d'un onduleur pour le serveur.

Modèle : MGE, UPS SYSTEMS, Protection Center 500. Acheté à la Fnac.

25 juin 2006

Entreprise > Association > Startup

Comment dire... Entre Paul Graham qui explique dans ses articles comment et pourquoi créer sa startup avec le minimum vital, Jean-Hubert qui détaille avec humour et pédagogie les étapes de la création d'une SARL en France en 2006 -- on fera avec profit également un tour chez Jean-Luc Watine, «Entrepreneurs: Créer et choisir son statut» --, et Laurent Samuel, qui vient de sortir une chronique intitulée L'association 1901 au service d'un projet d'entreprise» sur Envie d'entreprendre (mais si, rappelez-vous, l'infatigable Olivier Marone !)... il y a comme des super prémices, là.

C'est fou comme tout s'enchaîne parfaitement.
Il n'y a qu'à relier les points.

Et sinon, le blog de Laurent Samuel, «Créer et animer une association Loi 1901», me semble tout à fait bien, en ce qui concerne les associations.

22 juin 2006

Report annoncé

Diantre, comme le temps passe. Déjà fin juin et pas de béta publique ?

Entre les réunions avec les associations, le développement, l'écriture des statuts, et d'autres choses qui n'ont rien à voir avec les Fûts mais qui ont bousillé le planning, ça n'avance pas comme prévu.

Donc cette semaine j'ai annoncé à deux associations intéressées que la sortie publique de la plateforme Les Fûts était reportée à la rentrée de septembre.

Bugzilla

En termes de bug tracking, Bugzilla est installé sur le PC pour «évaluation». Entendre : on va clairement utiliser le produit, mais on ne le migrera que plus tard sous NetBSD.

Petite remarque, ça commence à faire beaucoup d'outils indispensables qui sont installés ou auprès desquels on est inscrits, mais qui ne sont pas reliés les uns aux autres ! Basecamp, Blogger, forums NNTP, Google Groups, mails, halfj, CruiseControl, Bugzilla, dbdoc, codegendoc, Antdoc...

À part ça, l'installation sous Windows d'une appli web écrite en Perl est encore et toujours un poème. Un poème sale et douloureux, mais un poème.

20 juin 2006

Consultations multi-serveurs

Un utilisateur peut faire suivre sa session d'un serveur à l'autre.

Quand il y a des modifications métier, pas de problème, les impacts sont redistribués par le back-end vers les différents serveurs applicatifs.

Mais que se passe-t-il quand il y a des modifications applicatives ? Par exemple l'utilisateur a lu tels messages d'un forum sur tel serveur, ils apparaissent donc comme «lus». Il navigue jusqu'à un autre serveur, qui, pas de bol, donne accès au même forum. Les mêmes messages y apparaissent donc comme «non lus». Et c'est bien le principe : les tâches de consultation se font en local sur les serveurs applicatifs, sans allers-retours vers le back-end. Les deux serveurs sont donc désynchronisés.

Pour permettre de récupérer au cas par cas la cohérence entre les états applicatifs des différents serveurs front-end, il y aura un bouton «Synchronize», qui demandera au back-end de mettre à niveau tous les états applicatifs de l'utilisateur.

Versions des objets métier

Gérer les contextes de navigation, c'est bien. On permet ainsi à l'utilisateur de changer ses modalités d'affichage d'une fenêtre à l'autre. Mais que se passe-t-il quand les données elles-mêmes changent pendant ce temps ?

On voit qu'il faut que chaque contexte de navigation pointe explicitement vers un «jeu de données figé», une baseline, afin de rester cohérent quand on navigue au sein des pages.

Par ailleurs, que se passe-t-il quand les données sont en maintenance ? Par exemple, de nouveaux messages ont été postés, et le back-end effectue en tâche de fond le calcul de tous les threads. Il a besoin pour cela de réserver la totalité des messages, car potentiellement tous les threads vont être modifiés.

On peut utiliser des verrous, que ce soit des verrous applicatifs ou des verrous techniques (les fameuses «transactions». Mouarf). Mais cette solution a le léger inconvénient d'interdire toute autre modification des données pendant la maintenance. Cet inconvénient est léger en effet, car le fait le back-end sert entre autres à ordonnancer les tâches de modification.

Cependant, les verrous ne permettent pas de gérer correctement les contextes de navigation. En effet, quand le verrou est relâché, les données courantes ont été modifiées. Le contexte de navigation est alors invalide.

Et donc... on en revient aux versions, aux baselines.

Les versions correspondent à des «états cohérents» des données. Cette cohérence est assurée par le back-end. Il n'y a jamais de versions concurrentes, jamais de merge.

C'est toujours le back-end qui incrémente les versions, jamais directement l'utilisateur. L'utilisateur ne fait que poster ses demandes d'actions, et c'est le back-end qui en fait la résolution.