Christophe Nowicki

November 27, 2009

xPL Perl update script for Pachube

I’ve wrote a small update script for Pachube based on xPL-Perl.
This module is based on Beanz’s Net::Pachube module.
I use this script, for my pachube feed.

Setup

The setup is very simple on Debian GNU/Linux, at first you need the Net::Pachube module :
$ wget http://search.cpan.org/CPAN/authors/id/B/BE/BEANZ/Net-Pachube-0.01.tar.gz
$ tar xzf Net-Pachube-0.01.tar.gz
$ cd Net-Pachube-0.01
$ perl Makefile.PL
$ make
...
# make install

Note: the dh-make-perl method does not work, with this package ;-(

Then you can grab, my xpl-pachube script :

$ svn co http://svn.csquad.org/xpl-pachube/
..
# chmod +x xpl-pachube/xpl-pachube
# mv xpl-pachube/xpl-pachube /usr/local/bin

Run

You can start the xpl-pachube script in verbose this way :

$ xpl-pachube -key 52b37888404598851de -verbose -feed_id 1934 class=sensor device=cc128.01189.0.1

You need to change the -key and -feed_id arguments.

That’s all folks!

Filed under: Home automation,Programming — Tags:, , — cscm @ 23:29

September 12, 2009

La dette technique

Je viens de finir une analyse de code pour un client. J’aime beaucoup ce type de missions, car elles permettent de remettre en perspective mon travail et de mieux analyser les différentes implications de l’organisation sur le développement.

J’essaye dans ce type de mission d’identifier quels sont les points d’organisation qui transparaissent dans l’analyse de code.

Dans plusieurs cas, j’ai pu retrouver des similitudes. Ces similitudes peuvent être regroupées sous le terme de “dette technique”.

Dans cette article, je vais essayer de définir le concept, vous présenter les symptômes, les origines, les conséquences et les solutions envisageables.

Définition de la dette technique

Lorsque vous ajoutez une fonctionnalité à un logiciel, vous avez deux
possiblités :

  • Faire le plus rapide possible, c’est à dire en utilisant la
    technique la plus facile, la plus rapide et négliger la conception
  • Prendre le temps de réaliser proprement la fonctionnalité, créer une architecture, spécifier les besoin fonctionnels, techniques, faire des tests, etc.

On peut établir une métaphore financière avec la mise en place d’une solution à court terme telle qu’évoquée dans le premier cas de figure en parlant de dette technique.

Vous empruntez du temps sur l’avenir. Comme dans le cas d’un crédit. Mais le coût de cet emprunt n’est pas nul.
Plus vous développez rapidement et mal et plus la dette grandit, les intérêts se cumulent.
Et le projet peut faire faillite sous le coût de la dette.

Symptômes

Voici des exemples de situations réellement vécues au sein d’entreprises :

  • Absence de documentation sur la structure du projet : où se trouve le code source? dans quel répertoire se trouve la documentation du projet, où sont les fichiers CSS, etc.
  • Aucun test unitaire ou fonctionnel ;
  • “Lorsque je change une ligne dans le module A, cela casse le fonctionnement du module B”
  • “Ne touche pas à cette partie du code, nous ne savons pas ce qu’elle fait exactement, mais dieu merci cela fonctionne encore” ;
  • Nous venons de perdre un disque dur sur le serveur de production, où sont les sauvegardes?
  • J’ai l’impression d’avoir déjà corrigé ce bug plusieurs fois, étrange….
  • Code sans aucun commentaire ou avec des commentaire trop anciens ;
  • La connaissance du projet dépend d’une seule personne ;
  • Je vais mettre un commentaire TODO ou FIXME et je corrigerai le problème plus tard ;
  • Nous ne pouvons pas mettre à jour les composants du serveur, cela va casser le code ;
  • Nous n’avons pas le temps de faire cela, ce n’est pas une urgence vitale ;
  • Nous ne pouvons pas mettre à jour le code, personne ne comprend cette partie du code …
  • La personne responsable du module est partie en vacances …

Vous avez aussi entendu ou vécu ce genre de situation ?
Alors appelez le 81212 et dites ‘Thermomètre’ ;-)

Les origines

Qui est responsable de ces problèmes. La réponse est assez simple, car chaque intervenant du projet est responsable :

  • le chef de projet qui néglige la conception, planifie mal
    l’exécution des tâches ou ne transmet par correctement les demandes des clients ;
  • le client qui s’introduit dans la conception technique du
    logiciel et qui impose brutalement son point de vue ;
  • le développeur qui ne sait pas dire “non”, qui surestime ses
    capacité ou bien qui ne joue pas collectivement dans une équipe ;
  • les utilisateurs avides de fonctionnalités et volatiles dans leur
    demandes ;

Les conséquences

Les conséquences de la dette technique sont les suivantes :

  • Augmentation du temps de développement ;
  • Impossibilité de prévoir et d’anticiper les coûts d’entretien ;
  • Difficulté pour faire rentrer un nouveau développeur dans l’équipe ;
  • Faillite

Solutions

Technique

La solution technique miracle permettant de vous sortir du bourbier n’existe pas.

Ceux qui vous disent qu’il suffit de refaire le logiciel avec une autre
technologie / technique ont sûrement quelque chose à vous vendre ;-)

Infrastructure

Il faut absolument mettre en place une infrastructure pour chaque
développement quelle que soit la taille du projet.

  • Un logiciel de suivi de bugs : comme Request Tracker, Trac, Mantis, etc…
  • Un système de suivi de version tel que Subversion, Git ou Mercurial ;
  • Un système de sauvegarde ;
  • L’automatisation des tâches à l’aide d’un système de compilation automatique ;
  • Des tests unitaires et fonctionnels automatisés ;

Refactorisation

La refactorisation est une forme de paiement des intérêts de la dette.
En effet, elle permet de faire une pause dans le développement et de “nettoyer” le code.

Méthodes de développements

Je ne vais pas lancer une querelle de clocher, je ne vais pas non plus vous dire que telle ou telle méthode de développement est la meilleure.

Il existe un bon nombre de méthodes de développement.

Chaque méthode présente ses avantages et ses inconvénients.

Par contre, une chose est sûre, les équipes de développement qui appliquent une méthode de développement rencontrent moins souvent ce type de problème.

Un peu de provocation

Je ne résiste pas ;-)
Est-ce que la dette technique est mauvaise dans tous les cas ?
Comme dans le cas d’une patate chaude cela dépend de qui paiera les intérêts.
Il est possible de faire un prêt ninja avec les intérêts de la dette.

Cela fonctionne dans le cas d’un marché ou “the-winner-takes-all”.
Par exemple, dans le cas d’une start-up innovante dont le seul but est de revendre le logiciel.

La dette technique permet de partir plus vite au soleil ;-)

Références

Filed under: Programming,Work — Tags:, — cscm @ 09:24

February 4, 2009

Retour sur l’optimisation des performances du projet MAVISE

La base de données MAVISE fournir les données de base sur l’ensemble des chaînes de télévision accessibles dans l’Union européenne.
Elle à été développer par la société Easter-eggs pour le compte de la DG Communication de la Commission européenne.
Je vais décrire dans cet article les diffèrentes méthodes que nous avons mise en place pour optimiser les performances de cette application.

Problèmatique

La base de données contiens beaucoups d’informations :

  • la description du paysage audiovisuele de 30 pays ;
  • des fiches sur 5000 chaînes de télévision ;
  • des fiches sur 4000 entreprises ;
  • des fiches sur 8000 programmes de télévision ;

L’ensemble des ses données ne sont pas accessibles au grand publique.

D’un point de vu technique, la base de données PostgreSQL contient :

  • 115 tables ;
  • 100 vues ;
  • 220Mo de données.

Cela vous donne une petite idées de la taille de l’application.
La complexitées de l’application, la quantité de données disponibles et leur affichage nous as posées de nombreux problèmes :

  • Quantité de données très importante à transferer entre le client et le serveur Web ;
  • Requêtes complexes au niveau de la base de données ;

Optimisation de la base de données

Pour l’optimisation de la base de données, il faut faire attention aux points suivants :

  1. L’ORM (DB_DataObject dans notre cas) ne doit faire aucune opération de jointure . Il utilise toujours une vue dédier pour chaque fonctionnalitées ;
  2. Chaque vue ne calcule que les champs qui sont nécessaire à l’affichage ;
  3. Le plan d’execution de chaque vue est optimiser à l’aide d’index. Pour trouver quels sont les indexes à créer, il faut utiliser l’instruction EXPLAIN ANALYSE , comme décrit sur le wiki de Postgres : Using EXPLAIN.

Le travail principal consiste donc à éxécuter toutes les vues de l’application pour optimiser les plans d’éxécution à l’aide d’indexes.
Pour mieux comprendre la sortie de l’instruction EXPLAIN ANALYSE, j’utilise l’outil suivant : explain-analyze.info.

Pour savoir quelles sont les optimisations les plus pertinantes, il est intéressant d’analyser les logs du serveur Postgres à l’aide du logiciel Practical Query Analysis.

Il faut aussi “tuner” la configuration du serveur de base de données pour utiliser le maximum de la mémoire disponible sur le serveur.

Javascript

Nous avons utilisé le framework Javascript Mootools, le contrôleur de tableau dhtmlxGrid et l’éditeur de contenu TinyMCE.

Dans chaque page de l’application, il faut faire attention à ne charger que les fichiers nécessaire.
En effet, ces outils, bien que très pratiques sont très volumineux et augementent la taille des pages dans des proportions importantes.

Dans certains cas, nous avons dépasser plus de 640Ko de code Javascript dans une page ;-)

Les solutions que nous avons mis en place pour réduire la taille de ces fichiers :

  • La compression Gzip, malheureusement nous avons rencontrer de problèmes très importants avec Internet Explorer ;
  • Nous avons ensuite opter pour YUI Compressor qui fonctionne bien mieux ;

Systèmes de Cache

L’application dispose de nombreux systèmes de caches :

  • Le système de cache du gestionaire de template Smarty ;
  • Notre propre système de cache pour le contenu des tableaux, réalisé à l’aide du module Pear Cache_Lite ;
  • L’API de XCache, pour certains calculs et XCache pour les opcodes PHP ;
  • Le système de cache d’Apache Cocoon pour le système d’impression ;
  • La cache du navigateur des utilisateurs. Il est possible de bien contrôler le contenu du navigateur des clients à l’aide du module mod_expires d’Apache.

Réduction de la taille des pages

Nous avons travailler pour réduire au maximum la taille des échanges entre le navigateur web et le serveur.
Pour cela nous avons utilisé la compression Gzip sur :

  • Le contenu des tableaux ;
  • Les pages produites par le système de tempate ;

Celle-ci est réalisé par le gestionnaire de tempon de PHP, à l’aide de la fonction ob_gzhandler ;

Outils utilisés

L’optimisation d’une application est toujours empirique, il est nécessaire d’avoir de bon outils pour observer les effets des modifications.
Pour cela nous avons utilisé :

Les liens utiles pour l’optimisation des performances d’une application Web

Pour finir, voici quelques liens très interessants sur l’optimisation d’une application Web :

Filed under: Programming,Work — Tags:, , — cscm @ 21:42

June 1, 2006

PHP REST SQL, Web Services for dummies

Je vous passe l’ensemble de la propagande habituelle sur les Web Services ( l’architecture SOA, Annuaires de services, SOAP, etc…).

Pour ma part, je pense qu’il existe deux grandes familles de WebServices :

  • Contrôle : l’éxécution d’action
  • Données : la mise à disposition d’informations

Pour la première famille, l’ensemble des techniques disponibles (SOAP, WSDL, UDDI) couvrent les besoins.
Quant à la seconde famille, je trouve que ces techniques sont bien trop complexes à mettre en oeuvre.

Problèmatique

Imaginons que vous avez besoin de mettre à disposition le contenu d’une base de données relationnelles ( liste de contacts, tickets, commandes en cours, etc. ) à l’aide d’un Service Web.

1/ Solution envisagée : le développement d’une Interface SOAP spécifique à votre problèmatique

Le développement de celle-ci sera long, car il vous faudra :

  • désigner l’interface
  • développer les composants
  • tester le fonctionnement
  • écrire la documentation

2/ Solution envisagée : adopter la méthodologie REST

J’ai découvert cette méthodologie suite à un article du journal du Net : SOAP, XML-RPC et EST : différences et intérêts

Elle est spécifiée dans le mémoire de Roy Thomas Fielding : Architectural Styles and the Design of Network-based Software Architectures

Ce qui est remarquable dans cette méthodologie, c’est :

  • sa simplicité
  • la réutilisation de protocoles standards éxistants du web
  • la possiblité de mettre en cache le résultat de la requête de manière transparente.

Le project PHP REST SQL

Par la suite, j’ai découvert le projet PHP REST SQL, celui-ci permet de mettre à disposition le contenu d’une base de données MySQL via une interface Web.

Ce projet consiste en une classe, qui s’interface avec une base de données MySQL et qui permet à l’aide de requêtes HTTP de récupèrer les données de la base, créer, modifier et supprimer des champs.

Ma contribution : abstraction par rapport aux bases de données

Actuellement, le projet ne supporte que les bases de type MySQL, j’ai donc réécrit la classe pour prendre en comptes toutes les bases de données supportées par le module PEAR MDB ( MySQL, PostGreSQL, Oracle, Frontbase, Querysim, Interbase/Firebird, MSSQL et SQLite).

J’ai testé son fonctionnement avec 3 bases (MySQL, PostGreSQL et SQLite).

Cette contribution est disponible sur SourceForge : database abstraction (MySQL, Postgres and SQLite Support).

Installation et Configuration

Installer et mettre en oeuvre le classe, il suffit de :
1/ Télécharger la classe :

$ wget 'http://sourceforge.net/tracker/download.php?group_id=126371&atid=705494&file_id=180054&aid=1498241'  -O php_rest_sql.tar.gz

2/ L’extracter dans votre arborescence Web :

tar xzvf php_rest_sql.tar.gz -C /var/www

3/ Editer le fichier de configuration phprestsql.ini.

4/ Editer un fichier .htacces et activer le module rewrite dans Apache.

Et voila !
Vous pouvez accéder au contenu de votre base de données directement à l’aide d’un navigateur.

Il ne vous reste plus qu’à écrire un client pour accéder aux données, à l’aide de la bibilothèque PHP CURL par exemple.

Conclusion

J’ai soumis mon patch à Paul James, l’auteur du projet et proposé l’idée de transformer celui-ci en module Pear. Il faut savoir que l’auteur a développé le project Tonic autour du même concept.

Mais il s’agit d’un veritable framework de développement web et qui par conséquent est beaucoup plus intrusif.

Filed under: Programming — Tags:, , — cscm @ 10:51

February 4, 2006

sqlite_fetch_object for PHP4

The sqlite_fetch_object function is not implemented in the PECL extension version 1.0.3.
I’ve rewrite it sqlite_fetch_object in PHP :

// An empty class
class bidon {
}

// Fetch resultset as an object
function sqlite_fetch_object(&$resource){
                $arr =  sqlite_fetch_array($resource);
                $obj = new bidon();
                foreach ($arr as $key => $value) {
                        # Check is valid $T_VARIABLE
                        if (ereg("[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*", $key)) {
                                $obj->$key;
                        }
                }
                return $obj;
}

Voila

Filed under: Programming — Tags: — cscm @ 13:30

January 19, 2006

XMLHttpRequest.status != 302

Je viens de découvrir une nouvelle limitation de l’objet XMLHttpRequest utilisé par la méthodologie Ajax.
Celui-ci ne supporte pas les rédirections HTTP envoyées par un serveur web.

Effectivement, un serveur web peut indiquer au client, via l’envoi d’une réponse de type 300 que le document demandé ne se trouve pas à la page indiquée.

L’objet XMLHttpRequest suit automatiquement les redirections sans vous en informer.

De ce fait, il n’est pas possible d’informer le client d’une redirection envoyée par le serveur.

Nous avons experimenté ce comportement avec tous les navigateurs du marché.

Mes recherches sur ce sujet le confirment :
http://www.codecomments.com/archive361-2005-3-412946.html

Il existe une solution, non portable qui conssiste à utiliser l’objet WinHttpRequest

Celui-ci propose de nombreuses méthodes supplémentaires, dont notamment la désactivation du suivi des rédirections automatiques : WinHttpRequestOption

Mais il n’est disponible que sous Microsoft Windows …

Il faut noter, que le suivi automatique des rédirections est une faille de securité, car lorsque les redirections bouclent, le navigateur du client plante.

C’est notamment le cas de Mozilla Firefox, qui est pourtant capable de détecter les boucles de redirection classique.

Filed under: Programming — Tags:, — cscm @ 08:25

January 12, 2006

Gestion des exceptions SOAP en Perl avec les module SOAP::Lite et Error

Après une longue journée de travail, j’ai enfin réussi à faire fonctionner correctement le système de gestion d’exception de SOAP::Lite avec le module Error. Tout d’abord quelques explications.

Système de gestion d’exception

Tout programme en exécution peut être sujet à des erreurs, pour lesquels des stratégies de détection et de réparation sont possibles. Ces erreurs ne sont donc pas des bogues des programmes, mais des conditions particulières, on parle aussi de conditions exceptionnelles ou exceptions dans le déroulement normal d’une partie d’un programme.

Module Perl Error

Le module CPAN Error permet de gérér les exceptions en Perl. Il propose une interface objet semblable à celle disponible dans des langages comme Java ou bien C#. Le module repose sur la fonction die du langage.

SOAP::Lite

Le projet SOAP::Lite permet de prendre en charge l’ensemble des protocoles lier aux Web Services (SOAP, WSDL et UDDI). L’ensemble des fonctionnalitées offertes sont extrèment riches et puissantes. Vous pouvez aussi bien faire un serveur qu’un client en Perl et vous interfacer avec des Service écrit dans de nombreaux autres langages.

Entre la théorie et la pratique …

L’ensemble des interactions sont décrites dans les spécifications des protocoles de Web Services. Mais comme présque toujours en informatique, chaque constructeur, langage ou implémentation apporte son lot de spécificitées.

Dans le cas du langage Perl, les deux principaux sont l’absence :

  • de typage
  • d’un système de gestion d’exception

Le permier problème se controurne à l’aide de la déclaration des type dans un fichier WSDL.
Pour le second, j’ai eu un peu plus de mal avant de trouver la solution.

A propos du code source de SOAP::Lite

Ce n’est vraiment pas un exemple à suivre :

  • très peu de commentaires dans le code
  • seul fichier de 5000 lignes
  • le mode de debug trace n’est pas assez verbeux
  • on se demande souvent si l’auteur du module n’a pas coder sous l’imfluence de certaines drogues

L’anomalie de fonctionnement

Lorsqu’une exception est levée à l’aide de la fonction throw dans un module Perl elle créer un objet pour indiquer des informations sur le contexte de l’erreur. L’objet le plus simple est Error::Simple

sub foo {
   throw Error::Simple( "A simple error");
}

Il est possible de créer vos propres objets en utilisant l’héritage en utilisant l’objet Error comme base.

La framework SOAP::Lite détourne la fonction die et renvoie une exception SOAP qui contiens un objet. La problème est que cela ne fonctionne pas correctement :

 SOAP Fault :
        Fault String : Application error
        Fault Detail :  {
          'Error__Simple' => {
                             '-file' => 'Demo.pm',
                             '-text' => 'A simple error',
                             '-package' => 'Demo',
                             '-line' => '9'
                           }
        };

        Fault Actor  : http://localhost:4242/

Le contenu de Fault Detail n’est pas un objet MAIS une table de HASH.
De plus un message d’erreur du côte du serveur vous indique qu’il y’a visiblement un problème avec la serialisation :

 Use of uninitialized value in sprintf at /usr/share/perl5/SOAP/Lite.pm line 814.
Cannot encode 'namesp1:something' element as 'hash'. Will be encoded as 'map' in  stead

Après quelques heures de tatonnement et de recherche dans le code source de SOAP::Lite, j’ai trouver la source du problème.

Les attributs du module Error contiennent tous un préfixe qui fait échouer la serialization :

$VAR1 =  bless( {
        '-file' => '...',
        '-text' => '...',
        '-package' => '...',
        '-line' => '...'
        }, 'BadError')

La fonction résponsable de ce bug est SOAP::Serializer::encode_hash.
Une expression régulier empeche la serialisation d’un caractère ‘-‘ dans le flux XML.

J’ai donc déciser de supprimer le caractère ‘-‘ dans le nom des attributs à l’aide du boût de code suivant :

sub encode_hash {

my($self, $hash, $name, $type, $attr) = @_;

  while(my ($k, $v) = each (%$hash))
  {
    if ($k =~ m/^-/)
    {
        $k =~ s/^-//;
        $hash->{$k} = $v;
        delete $hash->{'-'.$k};
    }
  }

  if ($self->autotype && grep {!/$SOAP::Constants::ELMASK/o} keys %$hash) {

Et Voilà !

Cela fonctionne enfin correctement :

 SOAP Fault :
        Fault String : Application error
        Fault Detail :  {
                             'detail' => bless ( {
                             '-file' => 'Demo.pm',
                             '-text' => 'A simple error',
                             '-package' => 'Demo',
                             '-line' => '9'
                           }, 'Error::Simple')
        };

        Fault Actor  : http://localhost:4242/

Je vais contacter l’auteur du module pour trouver une solution plus propore ;0)
Mais en attendant celle-ci fonctionne correctement.

Filed under: Programming — Tags:, , — cscm @ 21:20

November 26, 2005

Génération dynamique de fichiers WSDL avec Perl

Dans le cadre de mon travail, je devais rendre accesible via des Web Services un ensemble de modules écrits en Perl.

Pour que les interfaces d’un module soient accessible via SOAP, il faut les décrire à l’aide du langage WSDL.

Le format WSDL est basé sur XML, il est relativement difficile de le comprendre et encore plus de l’écrire à la main.
C’est pour cette raison que la plupart des langages de programmation proposent des outils de géneration automatique.

Le principale problème que l’ont peut rencontrer avec ce genre d’outils est le manque de contrôle.

Pour palier à ce problème, Perl propose une solution remarquable : décrire l’interface à l’aide de commentaires directement dans le code.

Effectivement à l’aide du module Pod::WSDL, il est possible d’extraire les informations nécessaires pour créer le fichier de déscription d’interface.

Par exemple :

=begin WSDL

_IN $bar $string description du paramètre
_RETURN $string
_FAULT Error::Simple Le type d'éxception déclancher en cas d'erreur
_DOC description rapide du fonctionnement de ma fonction

=cut

sub foo ($) {
my $bar = shift;
return $bar;
}

Ensuite, il ne reste plus qu’à charger le module précédant et extraire les informations pour produire le fichier WSDL, à l’aide du bout de code suivant:

use Pod::WSDL;

my $pod = new Pod::WSDL(
source => 'My::Server',
location => 'http://localhost/My/Server',
pretty => 1,
withDocumentation => 1);

print $pod->WSDL;

Celui-ci vous affiche le fichier WSDL, directement sur la sortie standard.

Les fichiers produits par Pod::WSDL sont conformes aux spécifications et fonctionnent parfaitement.
Je les ai testé avec SOAP::Lite et le framework Apache Axis.

Nous avons une jolie solution pour créer des fichiers WSDL directement lors de l’installation de nos modules.

Néanmoins j’ai voulu pousser le concept de génération dynamique un peu plus loin.

Tout simplement parce que mon interface SOAP est séparée des modules qu’elle met à disposition (dans deux paquets différents).

Dans Web Services, il y a la notion de Web. J’ai donc mis à contribution le framework Mason, qui est un outil de template permetant de faire des sites web dynamiques en Perl.

Celui-ci dispose deux fonctionnalités intéressantes :

  • un système de cache ;
  • un système de gestion de page non disponible.

Le système de gestion de page non disponbile, permet de créer des pages web dynamiquement en fonction de l’url demander.

Le fichier dhandler suivant permet de créer dynamiquement un fichier WSDL en fonction du nom du module Perl:

< %once>
use Pod::WSDL;
use strict;
< %once>
< %init>
my $arg = $m->dhandler_arg;
$arg =~ s/\.wsdl//;
my $pod;

eval {
$pod = new Pod::WSDL(
source => $arg,
location => 'http://localhost/soapEndPoint',
pretty => 1,
withDocumentation => 0
);
};
if ($@) {
return 404;
}
$m->out($pod->WSDL);
< /%init>

Par exemple pour récupèrer le fichier WSDL pour le module Test, il suffit d’aller sur l’url : http://localhost/Test.wsdl.

L’opèration de géneration est rélativement rapide, mais dans le cas d’un service fortement solicité, il faut mettre en place un système de cache, comme celui décrit dans la documentation de Mason : DATA CACHING

Voilà

Filed under: Programming — Tags:, , — cscm @ 22:22

Powered by WordPress