Accueil > Blog > Archives

Archive par auteur

Géolocaliser des utilisateurs sur l’IP en Python

Damien Mercredi 14 octobre 2009

Depuis quelques temps, plusieurs clients nous demandent de pouvoir géolocaliser leurs visiteurs de manière plus ou moins précise.
La plupart du temps, leur but est simplement d’afficher une carte centrée sur la localisation (approximative) de l’utilisateur.

Pour mener cela à bien, nous avons décidé d’utiliser Geolite Country.
Celui-ci permet de géolocaliser l’utilisateur en fonction de son ip sur la base du Pays. Pour une recherche plus affinée, les services sont payants. Mais le client désire uniquement centrer sur le pays de l’utilisateur. L’offre gratuite est donc amplement suffisante.

L’application étant en Python et ayant décidé d’utiliser la base binaire, j’ai donc installé la librairie pygeoip.
Son utilisation est particulièrement simple.

gmaps = urllib.urlopen('http://maps.google.com/maps/geo?q=%s&output=csv' % urllib.quote(country)).read().rsplit(',')

Le fichier GeoIP.dat est la base de données binaire, accessible sur GeoLite via ce lien direct.
Ainsi notre variable « country » est un string contenant le nom du pays. Ici « France ».

Il faut par la suite obtenir la latitude et la longitude de ce pays. Pour cela, Google Maps API est particulièrement utile.

gi = pygeoip.GeoIP('lib/GeoIP.dat')<br />
country = gi.country_name_by_name('o2sources.com')

Notre variable « gmaps » contiendra ainsi un tableau pour lequel les deux derniers éléments sont respectivement la latitude et la longitude.
Il n’y a plus qu’à afficher notre carte Google Maps centrée sur des données :)

Et puisque du code sans son contexte est d’une utilité moyenne, voici la vue permettant d’obtenir ces données

from django.shortcuts import render_to_response
from django.template import RequestContext

import pygeoip
import urllib

def home(request):
  gi = pygeoip.GeoIP('lib/GeoIP.dat')
  country = gi.country_name_by_name(request.META['REMOTE_ADDR'])
  gmaps = urllib.urlopen('http://maps.google.com/maps/geo?q=%s&output=csv' % urllib.quote(country)).read().rsplit(',')
  return render_to_response('centers/home.html', { 'country': country, 'latitude': gmaps[2], 'longitude': gmaps[3] }, context_instance=RequestContext(request))

Et dans notre template nous n’avons plus qu’à traiter ces données comme nous le désirons. Dans mon cas en affichant une carte Google Maps.
Mais vos besoins peuvent varier et les possibilitées sont quasiment illimitées.

Paris Web : nous y serons

Damien Lundi 14 septembre 2009

Thanh annonçait en mai dernier les dates de Paris Web 2009.
Et les 8, 9 et 10 octobre ça arrive rapidement.

Nous serons donc bien présent à Paris Web. Et pas seulement pour assister à l’évènement.
En effet Florent fera une intervention Webdesign et qualité en compagnie de Benjamin de Cock.

Quant à moi j’animerai un atelier Test automatisé d’applications JavaScript avec Qunit et Selenium.

Thanh sera également présent probablement derrière un objectif d’appareil photo.
Alors nous vous attendons à Paris début octobre !

Déployer une application Django avec Capistrano

Damien Mercredi 26 août 2009

Chez O2Sources on aime tout ce qui permet d’améliorer la productivité. Et si en prime ça permet d’éviter des erreurs, on adore !
Malheureusement jusqu’à maintenant, nous déployions toutes nos applications « à la main », en FTP.
Mais grâce à Capistrano, nous remédions maintenant à cela en automatisant le déploiement de nos applications, afin de gagner du temps et surtout, d’éviter les erreurs ou les oublis.

Capistrano est un outil permettant d’automatiser le déploiement des applications développé en Ruby.
Mais il est utilisable avec toutes vos applications. Qu’elles soient développées en Ruby, en PHP, en Python et même, si vous êtes un peu fou, en Java.
Dans l’exemple que je vais donner ci-dessous, l’application est développée en Python avec Django. Et nous avions une problématique majeure : nous désirons pouvoir déployer sur le serveur de développement et/ou sur le serveur de production sans avoir deux tâches différentes (afin d’être DRY évidemment).

Dans un dossier nommé deployment à la base de notre application, j’ai créé deux fichiers.
deploy
Il s’agit d’un script bash, qui permettra d’exécuter le processus sans avoir à taper « cap … ».
En voici le contenu.
#!/bin/bash
ENV=$1 cap deploy -f deployment/deploy.rb

Vous pouvez noter que avant d’exécuter le script, je définis une variable d’environnement à la valeur du premier argument passé en paramètres.
Cela nous permettra de choisir si nous désirons pousser en développement ou en production.

Puis un fichier deploy.rb.
Vous pouvez en voir le contenu complet. Mais je vais également le détailler dans la suite de cet article.

Nous définissons plusieurs valeurs de configuration.
set :deploy_to, {'dev' => '/chemin/vers/le/site/en/developpement', 'prod' => '/chemin/vers/le/site/en/production'}
set :domain, {'dev' => 'host.developpement', 'prod' => 'host.production'}

La première variable contient le chemin de notre application, en développement et en production.
Le second contient les hosts de nos serveurs de développement et de production.

Puis nous définissons le serveur sur lequel nous voulons déployer.
ENV['ENV'] = 'dev' if domain[ENV['ENV']].nil?
role :web, domain[ENV['ENV']], :master => true

Si le paramètre « ENV » est à la valeur « prod », nous déployons en production. Sinon, nous déployons en développement.

Ainsi pour déployer en développement, vous n’aurez qu’à appeller votre script bash :
deployment/deploy
Et en production, il faudra préciser le paramètre.
deployment/deploy prod

Notre tâche capistrano contient ensuite les directives de déploiement.
La tâche deploy:default est appellée automatiquement. Elle fait un svn update, mettant ainsi à jour les fichiers de l’application.
desc "Updating the repository files in " + ENV['ENV'] + " environment"
task :default do
  stream "cd #{deploy_to[ENV['ENV']]}; svn update"
end

Nous avons ensuite une seconde tâche qui supprime tous les fichiers .pyc de notre application, afin d’éviter un quelconque problème de cache avec ceux-ci (ils sont générés automatiquement par Python).
desc "Remove *.pyc files"
task :delpyc do
  stream 'cd ' + deploy_to[ENV['ENV']] + ';find . -type f -name "*.pyc" -exec rm -fv {} \;'
end

Puis nous mettons à jour la base de données de notre application en faisant un syncdb.
desc "Make sure database is in sync with models"
task :syncdb do
  stream "cd #{deploy_to[ENV['ENV']]}; python manage.py syncdb"
end

Et enfin, puisque c’est un projet Django, il faut, afin que les modifications soient prises en compte, recharger Apache.
desc "We reload apache"
task :restart do
  stream "/etc/init.d/apache2 reload"
end

Nous avons maintenant défini nos tâches. Et comme dit précédemment, la tâche default est exécutée automatiquement.
Mais il faut tout de même définir l’ordre d’exécution des tâches. C’est la que viennent les instructions « after ».
after 'deploy', 'deploy:delpyc'
after 'deploy:delpyc', 'deploy:syncdb'
after 'deploy:syncdb', 'deploy:restart'

Notre tâche Capistrano fera donc, dans l’ordre :

  1. Un SVN update afin de récupérer la dernière version du projet
  2. Une suppression de tous les fichiers .pyc
  3. Une remise à jour de la base de données
  4. Un rechargement du serveur

Pour rappel, vous pouvez voir la tâche complète et colorisée sur github.

Votre application est à jour. Ici, ça prends 2 minutes chrono. Et on est sur que ça fonctionne (et si ça ne fonctionne pas quand même, cela nous prévient) :)
Et vous, vous déployez vos applications comment ?

O2Tweet : afficher vos derniers tweets sur votre blog Wordpress

Damien Vendredi 19 juin 2009

Chez O2Sources quand on trouve qu’il manque quelque chose pour rendre le web encore mieux qu’il ne l’est déjà, on a pas peur de prendre un peu de temps pour palier à ce manque.
Et vu qu’on est pas fermés on partage ce qu’on fait :)
C’est le cas pour O2Tweet, un tout nouveau plugin wordpress qui faisait défaut à tout ce qui existe déjà.

Vous vous en douterez au nom, ce plugin interargit avec Twitter !
Il ajoute un widget à la sidebar de votre blog wordpress, vous permettant d’afficher les derniers tweets postés sur votre compte.
Vous pouvez même ignorer les @reply et ne placer que les tweets qui contiennent un ou plusieurs termes.

Et pour éviter de surcharger votre machine, c’est vous qui décidez toutes les combien de minutes les tweets sont rechargés, voir placer une crontab qui vous permettra d’éviter de ralentir le chargement d’une page utilisateur toutes les x minutes.

Alors à vous de tester O2Tweet.
Et si vous avez des remarques ou suggestions, on vous écoute :)

Oracle rachète Sun. Et MySQL ?

Damien Jeudi 23 avril 2009

La nouvelle a déjà fait le tour du web. Oracle vient de racheter Sun.
Et MySQL dans tout cela, que va-t-il devenir ? Il s’agit de l’un des plus grands (si ce n’est le plus grand) concurrents d’Oracle.

Marten Mickos, ancien « chef exécutif » de MySQL a répondu aux questions de Forbes à ce propos.

Le but d’Oracle, selon lui, serait surtout de concurrencer Microsoft et SQL Server.
Et quoi de mieux que de posséder les deux géants du marché (Oracle et MySQL) pour cela …

Par ailleurs Oracle et MySQL ont tous deux des publics différents. Le premier s’adresse plus à des applications lourdes tandis que MySQL est plus adapté pour des applications plus légères et notamment les applications web.
Tuer MySQL serait idiot de la part de Oracle. Les utilisateurs de la solution open source n’en profiteraient pas pour passer sous la solution fermée de l’éditeur et cela aurait pour seul effet de leur faire perdre des parts de marché.

La seule crainte à avoir serait que MySQL devienne, à terme, une partie de la branche bases de données et qu’il soit fermé.
La puissance de MySQL vient de son ouverture et c’est ce qui pourrait tuer le SGBDR.

Mais comme Marten Mickos le dit dans le lien donné plus haut, les décideurs chez Oracle ne sont pas idiots et ils réalisent plus que probablement cela.
Alors soyons optimistes quant à ce rachat. Et regardons du côté de PostgreSQL tout de même, qui pourrait devenir une solution attrayante dans quelques temps.

O2Sources est mort. Vive O3Sources

Damien Mercredi 1 avril 2009

Nous sommes heureux de vous annoncer que nous fêtons aujourd’hui nos 3 ans.
Depuis 3 ans, notre société a beaucoup changé. En partant de 4, nous sommes aujourd’hui 50, dont 41 petits chinois qui travaillent en sous sol.

Nous avions donc envie de marquer cet anniversaire, notre entrée à l’école.
C’est pourquoi nous avons décidé de changer de nom. Nous nous appellerons désormais, et ce pour la durée d’un an, O3Sources.

Notre ancien site internet, O2Sources redirigera bientôt vers cette nouvelle version.
Et puis à l’an prochain pour le passage en O4Sources !

[Edité : Ce billet est bien évidemment un poisson d'avril]

Recrutement : chef de projet J2EE à Dubaï

Damien Mardi 31 mars 2009

Parce que toute entreprise qui se respecte doit savoir investir à l’international, nous avons décidé d’attaquer de nouveaux marchés.
Pour cela, nous allons avoir besoin de main d’oeuvre rapidement dans une zone en pleine expansion, qui sera la place de tous les marchés (et même les autres) très bientôt.

Chef de projet

Mission : rattaché à nos bureaux en France, vous aurez à charge de gérer nos projets de développement Java et J2EE à Dubaï.
Seul membre de l’équipe lors du lancement du projet, vous aurez ensuite à charge de trouver de nouveaux collaborateurs afin d’assoir O2Sources sur le marché doubianiais et ce dans un grand bureaux avec un bouton rouge.
Tags : cheap, (doubiai)niais, rouge, dubai, quake (en VPN)
Contrat : dans un premier temps, nous ne pourrons vous proposer de contrat ni de rémunération. Une fois les bureaux correctement établis en revanche, une part sur les bénéfices effectués dans cette zone géographique (3%) vous sera reversée.

Chez nous on recrute des gens fortement motivés pour travailler, même sans récompense ou salaire à la clé. Parce que la réussite d’une entreprise, cela passe aussi par le don de soi et qu’il n’y a pas de bonne ou de mauvaise situation.
Si vous aussi, si vous deviez résumer votre vie, vous diriez qu’il s’agit de rencontres et de gens qui vous ont tendu la main alors n’hésitez plus et contactez nous !

[Edité : Ce billet est bien évidemment un poisson d'avril]

Have You Met 5.3 ?

Damien Mercredi 25 mars 2009

Le véritable développement en PHP va bientôt pouvoir commencer.
En effet, environ un an après la sortie de la première version alpha et quatre mois après la sortie de la version alpha4, l’équipe PHP nous annonce aujourd’hui la sortie de la RC1 de PHP 5.3.

On peut donc espérer une version finale aux alentours de la fin de l’été ou le début de l’automne.
Je ne vous rappelle pas la liste des fonctionnalités. Celle-ci est connue depuis des lustres. Et vous pouvez l’annonce officielle donnée dans le lien plus haut.

Attention, encore une fois, il ne s’agit pas d’une version finale mais seulement d’une RC.
L’installer sur un serveur de production ne serait vraiment pas une bonne idée.

Celui qui voulait écrire du code testable

Damien Lundi 23 mars 2009

Même si vous n’avez pas forcément entendu parler de TDD (Test Driven Development), vous avez à coup sur déjà entendu parler de tests, unitaires et/ou fonctionnels.

Et peut-être que vous avez déjà cherché un petit peu comment écrire des tests pour votre code.
Et la, peut-être que vous vous êtes dit « ouais, super, ça fonctionne bien dans les codes des autres. Mais sur le mien, ça ne s’applique pas ».
Dans ce cas, le problème vient surement de votre code, qui n’est pas testable.

Voici donc 10 conseils pour rédiger du code testable, fortement inspirée de l’article du Google Testing Blog « Writing Testable Code« .

  1. Ne pas mélanger le constructeur avec le code logique

    Chacune de vos classes doit être indépendantalisable des autres.
    Si vous faites, par exemple
    class myClass {
      private $secondClass = new secondClass();
    }

    Votre code est difficilement testable. En effet, vous allez avoir besoin d’instancier la classe myClass afin de la tester, en lui passant un objet secondClass factice et que vous devrez modifier de la manière que vous désirez.

    Mieux vaut donc faire la chose de la manière suivante :
    class myClass {
      private $secondClass;
      public function __construct(secondClass $second) {
        $this->secondClass = $second;
      }
    }

  2. Demandez les choses. N’allez pas les chercher vous même

    Aka respecter la loi de Déméter.
    Supposons la classe suivante
    class myClass {
      private $second;
      public function __construct(Context $context) {
        $this->second = $context->second;
      }
    }

    Vous êtes mal parti :)

    Ce n’est pas à myClass de se préoccuper du contexte. La preuve : elle ne l’utilise pas, ne fait que en récupérer la valeur « second » et la stocker.
    Autant y passer directement cette valeur, dont la classe a réellement besoin.
    class myClass {
      private $second;
      public function __construct(Second $second) {
        $this->second = $second;
      }
    }

  3. Ne faites pas tout le travail dans le constructeur

    Lorsque vous testez un objet, vous allez avoir toute une floppée de tests instanciant chacun votre objet, et testant une fonctionnalité précise de cet objet pour ensuite vérifier que la valeur rendue et que l’action effectuée par celle-ci sont correctes.
    Si vous avez placé tout votre code dans le constructeur, vous devrez d’abord passer avec succès toutes les assertions de celui-ci, et ce à chaque test.
    Cela peut être bénin ou très complexe. Qui plus est, cela ne vous posera pas des problèmes que dans les tests de la classe en question mais dans tous les tests des classes faisant appel à celle-ci.

  4. Evitez les singletons et variables globales

    Chaque test doit être vu comme une instanciation de votre application.
    Utiliser des singletons ou des variables globales a pour effet la perte de cette notion.
    Du coup vos tests ne sont plus fait dans un environnement que vous définissez mais dans l’environnement déjà défini par les tests précédents. Vous allez à l’encontre de tests qui échouent à cause d’éléments définis dans un test précédent.
    Par ailleurs les frameworks de tests ne sont jamais très clair sur l’ordre d’exécution de ces tests. Par ordre alphabétique, de déclaration, …

  5. Evitez les méthodes statiques

    Parce que le procédural c’est mieux !
    Et surtout parce que la clé pour tester est de pouvoir sortir du flot d’éxecution « normal », afin de tester des parties de code et celles-ci uniquement.
    Avoir une méthode statique Math.abs n’est pas un problème car celle-ci est uniquement finale. Mais avoir une méthode statique qui fera appel à diverses méthodes privées à l’intérieur de la classe rendra le test de ces mêmes méthodes impossible.

  6. Favoriser les compositions aux héritages

    Beaucoup de développeurs utilisent l’héritage dans le seul but de réutiliser les méthodes disponibles dans une autre classe. Ce qui est une erreur.
    Hériter un contrôleur de votre classe d’identification va rendre le test impossible car vous devrez faire un mock de cette classe d’identification dans chaque test. Et naviguer dans la classe parente pour chacun de ces tests.
    Mais supposez que, en plus de cela, votre classe d’identification hérite de votre classe de transactions avec la base de données. Vive le cauchemar.

  7. Favoriser le polymorphisme aux conditions

    Si vous voyez un switch ou (pire) plein de if imbriqués, vous devriez penser polymorphisme.
    Le polymorphisme consistera à faire diverses classes et méthodes effectuant chacune une action spécifique et appellée par la classe ou méthode principale.
    Cela vous aidera fortement car une méthode plus petite/simple est beaucoup plus aisée à tester.

  8. Mélanger des objets de valeur et des objets de service

    Votre application devrait comporter deux types d’objets.

    • Des objets valeur. Par exemple, Ville, CodePostal, CarteBancaire, … Ces objets n’ont généralement que des méthodes set et get. Ils sont particulièrement simple à tester.
    • Des objets de service. Par exemple, MailServeur, AdresseValidateur, … Ces objets sont beaucoup plus complexes et contiennent toute la logique métier.

    Un objet valeur ne doit jamais utiliser un objet service. En revanche un objet service doit utiliser l’objet valeur.
    Les objets valeur étant simple à instancier, ils peuvent l’être avec la méthode new, et ce plusieurs fois par application si besoin.
    Un objet service sera plus compliqué à instancier et pourra nécessiter de le passage multiples paramètres de configuration. Il est donc mieux de passer par une « Factory », qui permettra de n’instancier l’objet qu’une seule fois dans l’application puis d’utiliser toujours le même par la suite.
    Ainsi par ailleurs, vous pourrez vous même l’instancier avec les paramètres de votre choix dans vos tests et le réutiliser par la suite.

  9. Ne mélangez pas tout

    Si lorsque vous résumez l’utilité d’une classe, vous devez utiliser le terme « et », que cette classe est difficile à lire et à comprendre pour les nouveaux membres de votre projet, qu’elle des paramètres qui ne sont utilisés que dans quelques méthodes alors vous pouvez considérer que vous avez un problème de mélange des fonctionnalités.
    Ces classes sont très difficiles à tester car elles cachent de multiples objets et que vous êtes par conséquent obligé de tester tous les objets en même temps.

  10. Pensez deux fois, n’agissez qu’une

    Si vous foncez dans le tas, développez sans réfléchir avant, vous courrez vers des répétitions de votre code. Et par conséquent de vos tests.
    Et par le même conséquent, augmentez les risques de régression et donc faire des tests perds de tout son intérêt.
    Mieux vaut donc réfléchir deux fois à quelque chose avant de le développer. Vous avez peut-être déjà, dans votre application, fait la moitié du travail qu’il suffit juste d’utiliser.

Voici donc une liste de dix conseils pour vous permettre de mieux tester votre code. Vous aurez peut-être d’autres conseils à fournir.
Ne vous en privez pas.

Deux lectures (en anglais) que je vous recommande si vous souhaitez aller plus loin :

  • xUnit Test Patterns : Refactoring Test Code
    Il s’agit de la bible de tout développeur désirant faire des tests et ne sachant pas très bien comment s’y prendre. Il fournit diverses solutions permettant de tester divers patterns d’application.
  • The Pragmatic Programmer
    Celui-ci ne concerne pas que les tests. Mais donne de multiples conseils afin d’améliorer la lisibilité de son code, sa productivité et ce, notamment en faisant des tests.

Le zéro papier, une utopie ?

Damien Mercredi 18 mars 2009

Les employés sont comme l’électricité : quand ils veulent que quelque chose fonctionne, ils suivent le chemin de la moindre résistance

Explique le professeur David Karger, du laboratoire d’informatique et d’intelligence artificielle (CSAIL au MIT) à propos de l’utilisation des Post-It au lieu de l’informatique.
Ceux-ci (les post-its) s’avèrent en effet avoir toujours le vent en poupe malgré le fait que les services proposés par l’informatique soient de plus en plus sophistiqués, performants etc.
Le zéro papier serait-il donc une utopie ?

C’est justement ce qu’il détaille dans un article sur Forbes.
David Karger et ses collègues ont en effet étudié la manière dont nous utilisons les post-its afin d’élaborer un modèle de cycle de vie de nos débris d’information.
Et ils ont constaté que ces post-its se divisent en plusieurs catégories :

  • Liste des tâches à accomplir (environ 1/5).
  • Adresses de sites, informations de contact et notes de réunion.
  • Mots de passe et informations d’identification.
  • « Autres » : calculs de salaire, schémas, …

Ainsi, et c’est ce que montre l’étude, nous utilisons nos post-its pour noter des informations de manière rapide, sans avoir à se préoccuper d’une interface ayant de multiples champs tel que la date, une catégorie, …

Ces interfaces sophistiquées et permettant de gérer tout plein de choses sont donc justement le problème à l’utilisation du papier au lieu de celles-ci.
Avoir une interface à accès très rapide, ne nécessitant pas d’avoir un ordinateur allumé et disponible toujours sous la main serait donc la solution.
Du coup le post-it est probablement le meilleur killer app pour les post-its.

Source : Forbes, via Internet Actu.