January 2010

Pour un de nos projets web, nous allons changer la charte graphique. Le projet en question est codé avec le framework Ruby on Rails, ce qui implique de passer sur chacun des fichiers dans app/views pour vérifier le markup, de modifier les feuilles de styles et de s'assurer que le tout est cohérent sur toutes les pages du site. Comme le site est conséquent, cela risque de ne pas être tout simple. Aussi, ai-je écrit deux scripts pour nous aider.

Le premier script sert à extraire toutes les URL appelées depuis les fichiers de logs Rails :

Le second script permet d'ajouter des commentaires HTML au début et à la fin de chaque fichier dans app/views pour l'identifier depuis le code source de la page HTML générée :

Je pense que cela va nous aider dans notre approche, mais je me demande s'il n'existe pas d'autres trucs pour cela. Avez-vous déjà été confronté à cela ? Si oui, comment vous en êtes vous sorti ?

Depuis quelques mois maintenant, af83 utilise la base de données NoSQL MongoDB dans son pôle R&D. Mais pourquoi ce choix ?

Qu'est ce que MongoDB ?

MongoDB est un système de stockage de données NoSQL. En effet, ce n'est pas la peine de faire du SQL pour requêter votre base de donnée MongoDB. On parle alors de base SchemaLess, car il n'est pas nécessaire de faire un script SQL plus ou moins complexe pour créer et définir la structure des données qu'on peut mettre dans notre base. C'est simple, on met juste un énorme Hash.

Le fait de n'avoir des données que sous forme de Hash revient à avoir une base de données dite orienté Documents. MongoDB est donc une base de donnée SchemaLess orientée Documents.

Les bases de données de ce type les plus connues sont CouchDB Riak et MongoDB.

Les plus d'une base de données orienté Documents, SchemaLess ?

La première grande utilité est qu'on est pas obligé d'avoir des scripts de migration pour définir et faire évoluer le format de sa base de données. C'est simple : on crée son objet et on le met dans notre base. On ne se pose pas plus de questions. Cette logique est donc beaucoup plus orientée Objet Dynamique. Un utilisateur peut facilement rajouter par la suite de nouvelles données à cet objet. Avec une base de données SchemaLess, il suffit de modifier son objet, pas sa base de données.

Dans cette même verve, il y a la création de tables. En SQL pur, à chaque nouvelle table, il faut créer un script SQL pour l'ajouter. Là, pas besoin. Tout se fait automatiquement. On peux ainsi facilement switcher entre deux bases de données et créer autant de bases que d'utilisateur.

Le sharding de MongoDB

MongoDB depuis sa version 1.2 intègre une gestion de sharding. L'application de cette gestion permet d'avoir une scalabilité plus importante. Nos données sont toutes cohérentes, car on accède toujours à tout.

Le concept du sharding n'est pas d'avoir plusieurs bases de données en master/master, mais une seule base de donnée qui répartie ses propres données dans les différentes instances. On se retrouve ainsi à posséder certaines données sur une instance et les autres sur une autre.

GridFS

MongoDB embarque avec lui un système de fichiers complet. Ce système est GridFS. MongoDB est limité par document à 4Mo, mais on a vite besoin de stocker des documents plus importants. GridFS permet ça. On stocke donc tout document supérieur à 4 Mo sur le système de fichier GridFS. GridFS permet ainsi d'avoir le sharding sur ses fichiers. On a donc besoin de rsync entre plusieurs machines. GridFS fait le boulot pour soi. On pourrait facilement rapprocher GridFS à Hbase.

Un système de requêtes évolué

Enfin le vrai intérêt de MongoDB selon moi, surtout par rapport à Riak ou CouchDB, c'est sa gestion de requêtages. On peux requêter de façon très fine grâce à une grande quantité de mots-clé. On peux donc faire des requêtes aussi riches qu'en SQL, mais tout ça sur une base de données orientée Documents.

On peux par exemple chercher tous les documents qui possèdent plusieurs éléments dans un tableau

db.things.find( { a: { $all: [ 2, 3 ] } } );

Alors qu'en SQL on aurait plus fait un

SELECT * FROM things WHERE a LIKE '%2%' AND a LIKE '%3%'

Mais cette dernière est finalement incomplète car marchera pour un champs a contenant un array [32] en SQL mais ne fonctionnera pas dans le cas de la requête MongoDB.

On peux aussi faire de la recherche en donnant une fonction Javascript

db.myCollection.find( { $where: "this.a > 3" } );

C'est très modulaire et le nombre de mot clé ne cesse d'augmenter.

Oui, je suis un convaincu de l'utilité de MongoDB. Mais comme toute chose, essayez-le pour vraiment en voir les avantages et vous faire votre propre opinion.

Enfin pour les Rubyistes, vous avez à votre disposition des ODM (Object Document Mapping, l'ORM des base de données orienté Document) complet pour requêter votre base MongoDB : MongoMapper, MongoID et même un adapter DataMapper.

Ruby gems

af83 utilise Ruby on Rails pour certains de ses projets. De projet en projet, nous prenons des habitudes comme réutiliser certains gems. Je souhaite vous faire partager la liste de ces gems. Cette liste n'a rien d'extra-ordinaire. Ce sont principalement des gems très classiques mais qui méritent d'être mis en avant.

  1. Will Paginate est un plugin Rails pour gérer la pagination. Il est depuis longtemps la référence dans ce domaine et il continue de s'améliorer sans pour autant perdre sa simplicité. Indispensable. http://wiki.github.com/mislav/will_paginate/
  2. Authlogic est une solution complète pour l'authentification et la gestion des utilisateurs. C'est toujours assez délicat de gérer les mots de passe des utilisateurs, les activations de compte, les mots de passe perdus, mais ce gem apporte une manière propre de le faire en gardant une haute exigence de sécurité. http://rdoc.info/projects/binarylogic/authlogic
  3. Acts as state machine offre une solution très appréciable pour gérer des états sur les modèles, et les transitions entre ces états. Rails 3 offrira un module State Machine fortement inspiré de acts as state machine. En attendant, acts as state machine reste indispensable. http://github.com/rubyist/aasm
  4. Friendly_id est un gem bien pratique pour avoir des URL très parlantes. Il permet de créer des slugs et permalinks très facilement en vous évitant les surprises : historique de slugs, mots réservés et support d'unicode sont de la partie. http://norman.github.com/friendly_id/
  5. Thinking Sphinx est une bibliothèque pour connecter ActiveRecord au service de recherche fulltext Sphinx. Son DSL offre de nombreuses possibilités pour faire des recherches avancées sans difficultés. http://freelancing-god.github.com/ts/fr/
  6. HTML Entities est un moyen très simple d'encoder et décoder les entités HTML. http://htmlentities.rubyforge.org/
  7. FasterCSV est une bibliothèque pour manipuler des données au format CSV. Nous l'utilisons sur quasiment tous nos projets pour fournir des exports CSV des données présentes sur le site web. http://fastercsv.rubyforge.org/
  8. rspec est un framework incontournable pour spécifier le comportement de nos applications et nous assurer qu'il n'y ait pas de regressions. http://rspec.info/
  9. factory_girls permet de remplacer les fixtures de Rails, et d'avoir des données pour les specs qui soient faciles à maintenir au fur et à mesure des évolutions. http://github.com/thoughtbot/factory_girl
  10. Pour finir, af83 utilise également has_media, une bibliothèque maison pour la gestion des médias. http://github.com/AF83/has_media

Pour cette nouvelle session d'atelier, le thème était l'organisation technique des projets.
Parmi les thèmes abordés : le versionnage des sources avec Git, la numérotation des versions d'une application, les jalons correspondant dans Trac, les branches à utiliser, les environnements déployés et leur utilité.

Deux présentations ont donc été faites :

Prochaine étape : migrer l'ensemble de nos projets sous Git ;)

Logo des webhooks

Les webhooks sont un principe tout simple, mais qui offre de nombreuses possibilités pour étendre les fonctionnalités d'un site web. L'idée est vraiment simple : quand quelque chose de particulier se passe sur notre site, on envoie une requête HTTP avec le verbe POST vers une URL donnée. Les webhooks servent donc à notifier des scripts externes à une application web qu'un événement a eu lieu.

Hmmm, ça reste abstrait ? Prenons donc un exemple pour voir pourquoi et en quoi c'est très pratique. Github implémente des webhooks. Vous pouvez configurer pour un de vos dépôts git des URL de callbacks. A chaque fois qu'un commit aura lieu sur le dépôt en question, ces URL seront appelées avec les informations utiles (le nom du dépôt, la révision du commit, etc.). Cela offre de nombreuses possibilités : vous pouvez vous en servir pour déclencher un build sur votre service d'intégration continue (integrity par exemple), mettre à jour la documentation (rdoc.info offre ce service pour les projets ruby) ou encore analyser certaines métriques (Caliper).

Nous voyons que les webhooks peuvent donc servir à notifier très rapidement d'un événement. Mais ce hook peut également déclencher d'autres actions. Par exemple, le service d'intégration continue qui vient de recevoir un hook pourra lancer un build, puis poster le résultat sur un service de microblogging, et celui-ci pourrait alors lancer un autre webhook pour que les utilisateurs qui suivent ce compte soient notifiés, par exemple, en lançant qui script qui enverrait un message jabber, etc. Les webhooks sont cascadables à volonté.

Il existe une autre classe d'utilisation des webhooks : permettre à des script externes d'agir sur le site lui-même. Quand l'URL externe est appelée par un webhook, l'application peut lire le retour et agir en conséquence. Le cas le plus parlant est celui des robots sur Google Wave. Quand un utilisateur écrit dans une wave surveillée par un robot, celui-ci est prévenu par un webhook du contenu qui vient d'être écrit et il peut modifier la wave en réponse. Cela permet d'étendre le fonctionnement de Google wave via l'équivalent de ce que l'on pourrait appeler des plugins, mais avec la grosse différence que le code de ces plugins n'a pas besoin d'être sur le même serveur que la wave elle-même. On peut donc laisser la possibilité à des développeurs externes d'enrichir notre application de manière contrôlée.

Bref, les webhooks me semblent un élément de plus en plus important dans le web temps réel. L'alternative utilisée jusque là, le polling, devient de moins en moins adaptée à des contenus dont le rythme de mise à jour ne cesse d'accélérer. L'exemple de github est d'ailleurs assez symptomatique : il peut se passer plusieurs mois entre 2 commits, mais dès que j'ai commité, je souhaite que l'intégration continue se déclenche au plus vite afin d'être prévenu au plus tôt des regressions que j'aurais pu provoquer avec mon commit.

J'espère que cette introduction aux webhooks vous donnera envie d'appronfondir un peu le sujet, et surtout d'en mettre en place dans vos applications.

Gordon

Le langage de programmation Go est un langage sorti récemment. Pourtant, quand on voit qui est derrière ce langage, je ne peux m'empêcher de penser que ce langage vaut le coup d'être étudié. Le projet a commencé chez Google avec des personnes comme Ken Thompson et Rob Pike. Ils sont tous les deux à l'origine (ou ont contribué fortement) à UTF-8, UNIX, ed, Plan 9, acme... Excusez du peu.

J'ai donc décidé d'essayer Google's Go. Vous pouvez voir mes premières lignes de code sur github : Goldorak Go et goals calendar.

Le but de ce billet n'est pas de vous donner un avis définitif sur ce langage (il me reste encore bien trop de choses à découvrir avant de me permettre de donner un avis, même si je suis pour le moment assez enthousiasmé par ce que j'ai vu), mais de vous donner quelques liens si vous souhaitez aussi découvrir ce nouveau langage.

Tout d'abord, je conseille la lecture du guide d'installation, du tutoriel et du guide Effective Go. Le Go Language Resources est également un point de passage obligé.

Ensuite, on peut assurément commencer à écrire un peu de code, et au fur et à mesure commencer à utiliser des packages de la bibliothèque standard. Par exemple, Michael Hoisie recommande ces 5 packages : bytes, reflect, os, ioutil et vector.

Enfin, j'ai modifié ma configuration de zsh et de vim :

  1. # ~/.zshrc
  2. export GOROOT=$HOME/go
  3. export GOARCH=386
  4. export GOOS=linux
  5. zstyle ':completion:*:(all-|)files' ignored-patterns '*.8'
  1. " ~/.vimrc
  2. set wildignore+=*.6,*.8
  3. au BufRead,BufNewFile *.go set ft=go
  1. " ~/.vim/ftplugin/go.vim
  2. setlocal sw=8
  3. setlocal ts=8
  4. setlocal noet
  1. " ~/.vim/syntax/go.vim
  2. " Ce fichier est fourni avec Go et est également disponible sur :
  3. " http://golang.org/misc/vim/go.vim

Tux et Tix vous saluent

Ça fait un peu plus d'un an que je fais passer des entretiens d'embauche chez af83. C'est toujours un exercice délicat que de juger des compétences techniques et de la motivation d'un développeur sur un simple entretien. D'ailleurs, nous faisons très souvent les entretiens à deux justement pour ça.

Pourtant, je n'ai pas à me plaindre : les candidats retenus ont quasiment tous dépassé mes attentes. Il faut dire qu'il y a souvent un truc qui permet d'affiner son jugement.

Ce truc, je vais vous le dire et vous pourrez vous en servir pour m'impressionner si vous le souhaitez : montrer du code.

Que ce code soit des contributions à un projet sous licence libre, un projet complet ou quelques bouts de code dans un dépôt git, cela ne change pas grand chose. L'important est qu'un bout de code est souvent très révélateur du niveau de la personne qui l'a écrit, et si ce code a été diffusé, cela montre généralement que le développeur se sent plus impliqué par son code. Bref, c'est un très bon indicateur pour juger des deux critères importants : le niveau technique et la motivation.

Mon conseil, si vous cherchez un emploi de développeur, est de passer une soirée à écrire une petite application web (ou n'importe quoi d'autres), puis à diffuser ce code sous une licence libre sur github ou gitorious. Ce sera sûrement bien plus efficace et plus intéressant que de passer la même soirée à écrire des lettres de motivation.

Happy 2010

Nous souhaitons à tous nos lecteurs une bonne et heureuse année 2010.