Styles

samedi 22 décembre 2012

Emacs et Python : flymake pour vérifier le votre code en arrière plan avec pylint, pep8 et pyflakes

Cet article fait suite au premier article sur le sujet Emacs et Python : mon environnement de développement avec virtualenv.

Flymake va permettre de vérifier en arrière plan la validité de votre code ainsi que le respect de bonne pratiques. Les outils réalisant cette analyse sont pylint, pep8 et pyflakes. Flymake fait partie de la distribution standard de emacs et va appeler ces outils pour mettre en exergue les éventuelles erreurs dans votre code.


Tout d'abord, installez pylint, pep8 et pyflakes en utilisant l'outil d'installation pip (cet outil est installé par défaut à la création de votre environnement virtuel virtualenv) : dans une fenêtre shell (ou DOS) activez votre environnement virtuel python si ce n'est pas déjà fait et faites:
pip install pylint
pip install pep8
pip install pyflakes
Ces trois outils vont être appelés par un script shell (ou batch sous windows) unique : pycheckers (ou pycheckers.bat sous windows). C'est celui-ci qui sera appelé par flymakes.

Sous linux, créez un script pycheckers avec les droits d'exécution :
#!/bin/sh
cd /
filename=`readlink -f $*`
pylint -f parseable -r n $filename
pep8 $filename
pyflakes $filename
Sous windows, créez un batch pycheckers.bat :
@@echo off
pylint -f parseable -r n -i y %* | sed -r "s/\\/\//g"
pep8 %*
pyflakes %* | sed -r "s/\\/\//g"
exit /b 0
L'appel à l'outil sed permet de remettre d'aplomb les / du chemin complet des fichiers analysés pour que Flymake n'est pas de problème pour faire correspondre les erreurs aux fichiers ouverts dans Emacs. Sous linux, copiez pycheckers sous monenv/bin , sous windows copiez pycheckers.bat dans monenv\Scripts. Dans votre .emacs, mettre la configuration flymake suivante:
(when (load "flymake" t)
  (defun flymake-pyflakes-init ()
    (let* ((temp-file (flymake-init-create-temp-buffer-copy
                       'flymake-create-temp-with-folder-structure))
           (local-file (file-relative-name
                        temp-file
                        (file-name-directory buffer-file-name))))
      (list "pycheckers"  (list local-file))))
  (add-to-list 'flymake-allowed-file-name-masks
               '("\\.py\\'" flymake-pyflakes-init flymake-simple-cleanup)))

(add-hook 'python-mode-hook 'flymake-mode)
Relancez votre Emacs à partir d'un shell où votre environnement python a été activé : sous linux : nohup emacs > /dev/null 2>&1 et sous windows: start /B emacs

Et voilà, lors de l'édition de programme python (.py) flymake-mode sera automatiquement démarré et fera appel à pycheckers à chaque fois que vous aurez modifié votre code source. Flymake surlignera les lignes où des erreurs ont été reportées par les outils pylint, pep8 et pyflakes. Lisez la documentation flymake pour connaitre l'ensemble de ce qui peut être fait avec cet outil.

mercredi 5 décembre 2012

Emacs et Python : mon environnement de développement sous Windows et Linux avec virtualenv

J'ai passé du temps à peaufiner mon environnement de développement Python sous Emacs, histoire d'être le plus productif possible. Je vais essayer de résumer dans ce billet et les suivants l'ensemble des actions à mener pour configurer Emacs et avoir à disposition l'ensemble des fonctionnalités qu'on est en droit d'attendre d'un IDE moderne. J'ai testé cette configuration sous linux et windows ce qui n'est pas rien car, parfois, la configuration est bien différente. Tout d'abord, voici en gros l'architecture logicielle de cette solution de développement :

- Emacs 23 ou 24 : votre éditeur de texte préféré
- Python 2.6 ou 2.7 mais pas python 3 (et oui, je n'ai pas eu encore le temps de comparer les différentes opérations à mener pour être aussi compatible python 3)
- virtualenv : un outil pour définir des environnements python séparés, très pratique pour avoir des configurations différentes entre les projets
- pylint, pep8 et pyflakes : outils python que nous utiliserons pour faire de l'analyse statique du code en arrière plan dans Emacs via flymake.
- rope, ropemode, ropemacs et pymacs : outils python de refactoring, utilisés aussi pour faire de la "completion" (compléter automatiquement lors de la frappe)
- gnuwin32 : c'est la majorité des outils GNU compilés nativement pour windows. Ils serviront sous windows à corriger certains petits problèmes.
- auto-complete : mode emacs pour compléter les termes lors de la frappe,
- flymake : pour faire de l'analyse statique en arrière plan du code en cours de frappe,
- eldoc : mode emacs pour avoir dans le minibuffer, la signature de la fonction en cours de frappe.


Installation d'emacs

Télécharger la dernière version de Emacs 24 ou 23 et dézipper la : sous windows, prendre la version binaire; sous linux : prendre les sources et recompiler.

Pour information, sous debian, il y a une version emacs 23 qui marche très bien, installez là directement via le "gestionnaire de paquet Synaptic".

S'assurer que l'exécutable "emacs" est dans le PATH et que vous pouvez l'appeler directement à partir de votre invite shell.


Installation de python

Téléchargez python 2.6 ou 2.7 et installez le.

Sous windows, pas la peine de mettre ensuite le répertoire python dans le PATH (on utilisera virtualenv pour "activer" une certaine version de python)


Sous windows : installation de gnuwin32

Gnuwin32 est un ensemble d'outils GNU compilés nativement pour Windows. Ces outils vont nous rendre la vie plus facile sous Windows, car de part sa nature, Emacs s'intègre bien mieux à son environnement quand quelques outils GNU de base sont disponibles.

Téléchargez l'outil de téléchargement des outils gnuwin32 puis avec cet outil, installez tous les outils gnuwin32, puis mettre le répertoire /bin dans la variable PATH.


Installation d'un environnement virtualenv

Télécharger la dernière version de virtualenv.py puis créez votre nouvel environnement virtualenv avec l'instruction suivante :

python ./virtualenv.py monenv

Cela crée un répertoire monenv correspondant à votre environnement virtuel python. A l'intérieur ont été recopié les exécutables python (le même python qui a été utilisé dans la commande précédente) ainsi qu'un sous ensemble de la bibliothèque standard nécessaire pour initier l'environnement virtuel. Il faut ensuite "activer" votre environnement virtuel en invoquant la commande suivante: sous linux :

. ./monenv/bin/activate

sous windows :

.\monenv\Scripts\activate

Vous pouvez voir que votre environnement virtuel est activé sur votre invite de commande qui a du changer d'aspect et doit maintenant indiquer entre parenthèse le nom de l'environnement virtuel actif.

Faites un which python (même sous windows, grâce à gnuwin32 !) pour voir que vous utilisez bien le python (ou python.exe) de votre environnement virtuel et pas le python global. Il est à noter qu'on ne retrouve pas toutes les libraries standard python dans monenv/lib (monenv\Lib sous windows), et lors de l'exécution de python, le répertoire des librairies standards de l'installation globale se retrouve aussi dans le sys.path python, comme le prouve ces quelques lignes :

(monenv) F:\jrx\src\jrxemacs>python
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', 'F:\\jrx\\src\\virtualenvs\\monenv\\lib\\site-packages\\setuptools-0.6c11-py2.7.egg', 'F:\\jrx\\src\\virtualenvs\\monenv\\lib\\site-packages\\pip-1.2.1-py2.7.egg', 'C:\\WINDOWS\\system32\\python27.zip', 'F:\\jrx\\src\\virtualenvs\\monenv\\DLLs', 'F:\\jrx\\src\\virtualenvs\\monenv\\lib', 'F:\\jrx\\src\\virtualenvs\\monenv\\lib\\plat-win', 'F:\\jrx\\src\\virtualenvs\\monenv\\lib\\lib-tk', 'F:\\jrx\\src\\virtualenvs\\monenv\\Scripts', 'c:\\soft\\python-2.7\\Lib', 'c:\\soft\\python-2.7\\DLLs', 'c:\\soft\\python-2.7\\Lib\\lib-tk', 'F:\\jrx\\src\\virtualenvs\\monenv', 'F:\\jrx\\src\\virtualenvs\\monenv\\lib\\site-packages']
>>>

L'intérêt de virtualenv vient aussi du fait que les outils pip et easy_install sont installés automatiquement dès la création de l'environnement virtuel.

Voilà, nous avons ici les bases de l'installation Emacs et Python pour développer. Reste à configurer Emacs pour fonctionner avec Python. Dans un prochain billet, nous verrons comment outiller cet environnement pour faire fonctionner la superbe librairie flymake de Emacs et avoir de l'analyse statique de votre code en temps réel!

lundi 13 août 2012

Eclipse : un thème de couleur qui sert à quelque chose

On pourrait se dire que la coloration syntaxique n'est qu'une distraction parmi d'autres et que finalement ça n'apporte pas grand chose à la programmation. Bien utilisée, elle peut se révéler une aide précieuse, notamment lors de la lecture de code (activité on ne peut plus importante).

La coloration syntaxique offerte par Eclipse est puissante car elle permet d'attribuer un style à des éléments selon leur type. Par exemple, on peut donner des styles de couleurs et de polices de caractère différents aux méthodes abstraites, aux méthodes héritées, aux méthodes de la classe, aux champs paramètres et aux variables locales, aux énumérations, etc.

On peut même surligner différemment chaque occurrence d'une variable selon qu'on écrit dedans ou qu'on la lit.

Je me suis créé mon thème Eclipse sur la base de ce que j'ai dans Emacs. Je l'ai stocké sur Eclipse Color Themes et il s'appelle Robin Des Bois.


jeudi 24 mai 2012

LCOM4 : "Lack Of Cohesion" (quatrième variante) ou "Manque de Cohésion"

Un des principes fondamentaux de l'Orienté-Objet est qu'une classe doit avoir une et une seule responsabilité. Les anglo-saxons appellent cela le « Single Responsibility Principle » ou « Principe de Responsabilité Unique » :
IL NE DOIT PAS Y AVOIR PLUS D'UNE RAISON POUR UNE CLASSE DE DEVOIR CHANGER
Ce principe a été énoncé pour la première fois par Tom DeMarco et Meilir Page-Jones. Robert C. Martin en a décrit les aspects dans un excellent article. Ce n'est pas un principe sorti de nul part, édicté comme cela par maniérisme ou pédantisme. Cela provient du fait qu'au niveau d'une classe, on peut voir les propriétés (d'instance ou de classe) comme des variables globales. Et vous connaissez aussi ce vieil adage :
N'UTILISEZ JAMAIS DE VARIABLES GLOBALES
Cela provient du fait qu'une variable globale n'indique pas, par définition dans quel périmètre elle doit être utilisée. Ce qui fait qu'un programmeur non scrupuleux sera tenter de l'utiliser directement dans n'importe quelle circonstance, sans jamais se demander si elle est utilisée/modifiée par ailleurs. Toutes ces dépendances sur ces même variables globales créent rapidement des dépendances implicites entre toutes les parties du code source de l'application.

Ainsi, les variables globales d'une classe finissent toujours par être utilisées par tous les membres de cette classes. Il est donc important de détecter, lors de la programmation, si, dans une même classe, il n'y a pas plusieurs ensembles de méthodes et variables qui ont des vies complètement séparées. C'est-à-dire qu'il faut tracer un graphe des dépendances entre membres de la classe et déterminer le nombre de graphes indépendants les uns des autres.

Ce nombre est dénommé LCOM4, de la technique développée par Hitz et Montazeri dans leur article « Measuring Coupling and Cohesion In Object-Oriented Systems ». L'aide en ligne de l'outil Project Analyzer explique le calcul de ce nombre par un exemple graphique :



L'exemple sur la gauche montre une classe constituée des méthodes A à E et des variables x et y. A appelle B et B accède à x. C et D accèdent à y. D appelle E mais E n'accède à aucune variable.
Cette classe a 2 composants non reliés (ici deux graphes distincts) donc LCOM4 = 2. Il faut diviser la classe en {A, B, x} et {C, D, E, y}.

Sur l'exemple de droite, nous avons changé C pour qu'elle accède à x pour augmenter la « cohésion ». Maintenant la classe n'est constituée que d'un seul composant. (LCOM4 = 1). C'est une classe cohésive.
Étudions un exemple concret. Bizarrement, je n'ai pas trouvé de plugin Eclipse réalisant le calcul de LCOM4. Le plugin « Eclipse Metrics Plugin » calcule d'autres métriques de cohésion (moins intéressantes à mon goût) mais pas LCOM4. Dommage.

A ma connaissance, seul Sonar calcule automatiquement LCOM4. Voici comment faire pour obtenir cette métrique Sonar dans Eclipse. Reprenons l'exemple précédent, et implémentons-le en Java, cela nous donne :
public class Foo {
 
 private int x;
 private int y;
 
 public void methodA() { methodB(); } 
 public void methodB() { x = x + 1; } 
 public void methodC() { y = y + 1; }
 public void methodD() { y = y - 1; methodE(); }
 public void methodE() { }
}
Quand le plugin Sonar est configuré dans Eclipse pour calculer localement les métriques, on peut afficher toutes les métriques à l'écran :




samedi 12 mai 2012

Qu'est-ce que la métrique "Feature Envy" ou "Jalousie de Fonctionnalité" ?

Saviez-vous que le code source d'un programme a une odeur ? C'est souvent quand le code sent mauvais qu'on la remarque (« code smells »). L'analyse du code permet de détecter des mauvaises pratiques de l'orienté-objet ou plus globalement, des paradigmes à disposition dans le langage de programmation.

Aujourd'hui penchons-nous sur cette odeur nauséabonde du code que les anglo-saxons appellent « feature envy », et que je traduirais par « jalousie de fonctionnalité ».

La « jalousie de fonctionnalité » survient quand une méthode est plus intéressée par les fonctionnalités (méthodes et champs) d'autres classes que les siennes propres. La solution la plus simple est de déplacer la méthode dans ces autres classes, tout du moins, une partie de la méthode, celle qui a le plus de « jalousie ».

Le greffon Eclipse « Eclipse Metrics Plugin » calcule cette métrique avec la formule suivante :

Etant donné :

m, la méthode pour laquelle nous souhaitons calculer la « jalousie de fonctionnalité »
Fc, l'ensemble des fonctionnalités utilisées par m et appartenant au type c
cm, la classe dans laquelle m est définie

Alors

JalousieDeFonctionnalité(m) = maxc ≠ cm(|Fc|) - |Fcm|

Prenons un exemple :

Etant donné la classe Foo suivante :

package com.jeromeradix;

public class Foo {
 public void methodA() { } 
 public void methodB() { } 
 public void methodC() { }
}

et la classe Velo suivante :

package com.jeromeradix;

public class Velo {
 public void methodX() { }
 public void methodY() { }
}

Examinons le classe Bar suivante pour établir la métrique JalousieDeFonctionnalité(Bar.method1) :

package com.jeromeradix;

public class Bar {
 public void method1(Foo f, Velo v) {
  f.methodA();
  f.methodA();
  f.methodB();
  v.methodX();
 }
}

Comme method1() appelle deux méthodes différentes de Foo, on obtient |FFoo| = 2.
Comme method1() appelle une seule méthode de Velo, on obtient |FVelo| = 1.

Ainsi maxc ≠ Bar(|Fc|) = 2

La méthode method1() n'utilise pas d'autres méthodes de Bar, donc |FBar| = 0

Ainsi, JalousieDeFonctionnalité(Bar.method1) = maxc ≠ Bar(|Fc|) - |FBar| = 2 – 0 = 2.


Ce que nous confirme l'export HTML de l'Eclipse Metrics Plugin :
Le plugin Eclipse Metrics part sur une valeur max de JalousieDeFonctionalité = 2. Cela veut dire qu'au delà de 2, un message d'avertissement sera affiché dans la fenêtre "Problème" d'Eclipse, message qu'il sera donc intéressant de suivre en reconcevant la méthode si jalouse de ses voisines.

jeudi 1 mars 2012

Android SDK et SIM Alliance Open Mobile API

Parce que j'ai mis du temps à trouver comment faire, je note ici comment installer SmartCardAPI (SIM Alliance Open Mobile API) dans le android SDK local.


  1. Ouvrir le SDK Manager (SDK Manager.exe)
  2. Ouvrir le menu Tools / Manage Add-on sites...
  3. Cliquer sur le bouton New et saisir l'URL suivante : http://seek-for-android.googlecode.com/svn/trunk/repository/addon.xml


et Voilà, reste plus qu'à cocher "SIMalliance APIs by Giesecke & Devrient GmbH" au niveau de l'API 10, et cliquer sur le bouton "Install 1 package".