title:      ★ Architecture web moderne et agile
slug:       architecture-web-moderne-et-agile
date:       2008-06-04 02:19:22
type:       post
vignette:   images/logos/architecture_web_couchdb.png
contextual_title1:  Critique du livre Designing the obvious
contextual_url1:    20081008-critique-du-livre-designing-obvious
contextual_title2:  ★ RDF, l&#39;ADN de notre identité numérique ?
contextual_url2:    20080811-rdf-adn-de-notre-identite-numerique
contextual_title3:  Différences entre identification, autorisation et authentification
contextual_url3:    20080716-differences-entre-identification-autorisation-et-authentification

Pour rebondir sur [les propos de Christian](http://www.christian-faure.net/2008/06/01/dataware-et-metadataware/) qui essaye de combiner <abbr title="REpresentational State Transfer">REST </abbr> et <abbr title="Resource Description Framework">RDF</abbr>, je voudrais discuter de l'architecture « idéale » à laquelle je suis arrivé. C'est une problématique à laquelle je suis confronté aussi lors de ma réflexion pour [la killer app sémantique](https://larlet.fr/david/biologeek/archives/20080112-ma-killer-app-pour-le-web-semantique/) et qui fait partie des trois points bloquants actuels avec l'ergonomie et la confidentialité des données.

## Avant la ressource, il y a la donnée

Comme le souligne Christian, [REST](https://larlet.fr/david/biologeek/archives/20070413-pour-ne-plus-etre-en-rest-comprendre-cette-architecture/) s'adresse à des ressources et non directement à des données, d'où le problème lorsqu'on essaye de construire une [application RESTful](https://larlet.fr/david/biologeek/archives/20070629-architecture-orientee-ressource-pour-faire-des-services-web-restful/) qui tape directement sur des triplets [RDF](https://larlet.fr/david/biologeek/archives/20080425-le-point-sur-rdf-et-rdfa/). Commençons par étudier le stockage, on verra l'accès plus tard.

Il existe plusieurs moyens de stocker une donnée, on a longtemps cru que le modèle relationnel (PostreSQL, MySQL, etc) était la solution à tout mais dès que l'on est confronté à un très grand nombre de données, celui-ci atteint ses limites et **laisse aujourd'hui généralement place au modèle non-structuré et distribué** (CouchDB, Hadoop, BigTable, etc) qui a fait ses preuves grâce à Google.

Malheureusement, aucun des deux n'est adapté au stockage du RDF, ce qui est à l'origine de performances assez catastrophiques lorsqu'on atteint plusieurs milliers de triplets (ce qui arrive assez rapidement). De plus le modèle de type document est puissant justement dans sa souplesse, il est possible d'ajouter des champs à la volée, il serait donc vraiment dommage de restreindre son usage à 3 champs !

Dans l'idéal, il faudrait avoir une base performante qui soit développée spécifiquement pour stocker du RDF, en pratique **je crois plus en un mapping RDF sur une base structurée existante**, il y a des projets comme [HRDF pour Hadoop](http://wiki.apache.org/hadoop/HRDF) qui tentent justement d'arriver à ça. On arriverait au schéma suivant :


    Données (RDF)
        ↑
        | MapReduce + TODO
        |
    Données sérialisées (CouchDB, Hadoop, etc)


Les opérations de [MapReduce](http://hadoop.apache.org/core/docs/current/mapred_tutorial.html), [possibles en Python](http://www.michael-noll.com/wiki/Writing_An_Hadoop_MapReduce_Program_In_Python) et [automatisables grâce aux générateurs](http://blog.last.fm/2008/05/29/python-hadoop-flying-circus-elephant), permettraient de récupérer directement du RDF en sortie. De plus, mes problèmes de confidentialité, pourraient être nativement pris en compte à ce niveau (?)


## Mais on veut manipuler des ressources !

C'est génial d'avoir du RDF mais ce que l'on souhaite généralement manipuler est à un niveau plus élevé que l'on pourrait appeler **RRM pour Resource RDF Mapping**, c'est ce que fait par exemple [RDFAlchemy](http://www.openvest.com/trac/wiki/RDFAlchemy) qui est le pendant à SQLAlchemy qui est un <abbr title="Object Relational Mapping">ORM</abbr> classique.

*J'ai essayé un moment de créer une API RESTful directement sur un TripleStore mais ça pose de toute façon ensuite un problème ergonomique car les utilisateurs manipulent nécessairement des ressources et non des triplets au final, cette abstraction est donc utile dans mon cas mais ça peut varier selon les usages.*


    Ressources sémantiques (objets Python)
        ↑
        | RDFAlchemy
        |
    Données (RDF)
        ↑
        | MapReduce + TODO
        |
    Données sérialisées (CouchDB, Hadoop, etc)


Une fois nos ressources définies, **il faut maintenant un outil pour y accéder via une interface RESTful**, c'est seulement ici que [Django entre en jeu](https://larlet.fr/david/biologeek/archives/20070501-developper-une-application-restful-avec-django/). J'aurais l'occasion d'en reparler car je suis en train de développer mon propre outil de vues afin de faciliter ceci (après avoir retourné dans tous les sens [django-rest-interface](http://code.google.com/p/django-rest-interface/), je ne suis pas totalement satisfait et le projet est mort).


    Représentations standardisées (HTML, JSON, Atom, etc)
        ↑
        | Django + TODO
        |
    Ressources sémantiques (objets Python)
        ↑
        | RDFAlchemy
        |
    Données (RDF)
        ↑
        | MapReduce + TODO
        |
    Données sérialisées (CouchDB, Hadoop, etc)


Vous pouvez terminer le millefeuilles en connectant un site, un widget ou votre <abbr title="Rich Internet Application">RIA</abbr> sur cette API qui est évidemment buzzword compliant (le titre original était « Architecture Foutaises! » mais j'avais peur que ce soit encore interprété comme un gros troll).


    Utilisations (site, widget, RIA, etc)
        ↑
        | REST/APP
        |
    Représentations standardisées (HTML, JSON, Atom, etc)
        ↑
        | Django + TODO
        |
    Ressources sémantiques (objets Python)
        ↑
        | RDFAlchemy
        |
    Données (RDF)
        ↑
        | MapReduce + TODO
        |
    Données sérialisées (CouchDB, Hadoop, etc)



## Et pour quelques threads de plus...

J'en ai rapidement parlé lors de ma [présentation de Django](https://larlet.fr/david/biologeek/archives/20080521-conferences-django-pour-pycon-fr/), il est très important de pouvoir effectuer des tâches asynchrones lorsqu'elles pénalisent les performances de votre site et donc l'expérience utilisateur.

Pour ça, **Erlang semble former un [couple parfait](http://humani.st/scalable-web-apps-erlang-python/) avec Python** puisqu'il permet une parallèlisation à moindre coût, ainsi qu'un communication via HTTP+JSON. Ça tombe bien car c'est l'un des format qui est servi par notre interface RESTful en Django ! On pourrait aussi imaginer que les traitements asynchrones puissent accéder directement aux données RDF selon les cas.


    Utilisations (site, widget, RIA, etc)
        ↑
        | REST/APP
        |
    Représentations standardisées (HTML, JSON, Atom, etc)
        ↑                                         |
        | Django + TODO                           |
        |                                         ↓
    Ressources sémantiques (objets Python)    Traitements asynchrones (Erlang)
        ↑                                         ↑
        | RDFAlchemy                              |
        |                                         |
    Données (RDF)   ------------------------------/
        ↑
        | MapReduce + TODO
        |
    Données sérialisées (CouchDB, Hadoop, etc)


Vous cumulez ainsi la rapidité de développement offerte par Python (et Django) d'une part et les performances d'Erlang pour les travaux demandant un certain temps. **Le meilleur des deux mondes.**


## Quelques inconvénients évidents

**À chaque mapping, on perd en performances** et là on fait Document → RDF → Resource → Représentation ce qui fait quand même quelques étapes... bien sûr **on gagne en standardisation et en pérennité**, il sera possible de changer d'outils, voire de supprimer certaines transitions plus tard lorsque les avancées technologiques suivront. **C'est le coût de l'agilité** et à ce stade il serait difficile d'estimer si c'est vraiment pénalisant au final.

Le problème des outils innovants, c'est qu'ils **manquent d'extensions et/ou n'ont aucun benchmark** permettant de valider un choix compte tenu du nombre de données estimées. De plus, coder chaque lib inexistante à la main est assez fastidieux et je trouve plus intéressant de consacrer mon temps à réfléchir au produit final.

Enfin, ça demande de **maîtriser un bon nombre de technos**, je suis en train d'apprendre Erlang pour compléter mon arsenal mais plus le domaine des compétences s'étend et plus vous perdez en efficacité, ça peut être préjudiciable si vous travaillez seul. Ou pas, si vous êtes un geek curieux :-).


À ce stade de ma réflexion c'est ce qui me semble le plus pertinent mais je suis loin d'être un expert sur la question. Idées et retours d'expériences bienvenus, comme toujours.

