mardi, septembre 22, 2009

Type de données JPA et Hibernate

6 commentaires
DiggIt! Enregistrer sur Del.icio.us

L'efficacité du développement d'une application de gestion et l'efficacité de cette même application (les temps de réponse) repose grandement sur la construction d'un modèle de données "efficace".
Dans ce billet nous allons nous concentrer sur un choix "efficace" des types simples pour une application Java reposant sur JPA et Hibernate.

Cette article complète une série d'autres billets sur JPA de ce même Blog :


Si le mot "efficace" a été mis à plusieurs reprises entre guillemets, c'est que ce mot peut prendre des aspects contradictoires suivant le point de vu :

  • l'efficacité d'un modèle de données pour le DBA (Database Administrateur) va reposer sur l'espace de stockage et la rapidité d'exécution des requêtes,
  • pour un développeur cela reposera en grande partie sur la facilité qu'il a à écrire les requêtes qui correspondent au besoin fonctionnel
  • pour l'utilisateur ce sera les temps de réponses de l'application

Mon soucis dans ce billet, est de proposer un certain équilibre, une sorte de compromis entre ces différentes aspirations sans perdre de vu, le besoin pragmatique auquel nous devons tous faire face, développer une application au meilleur prix pour un client exigeant.
Dans un premier temps, nous énoncerons un certain nombre de règles simples permettant de choisir rapidement les types de données de ses propriétés. Dans un second temps nous expliquerons avec différents exemples les raisons de ces choix. Cette seconde partie devrait permettre une meilleure compréhension du comportement d'Hibernate et des limites de la portabilité des différentes solutions.

Contraintes pour l'efficacité d'un modèle de données

Nous nous concentrons dans ce billet aux seuls aspects du typage des propriétés et colonnes simples.

Pour pouvoir choisir efficacement un type de données il faut :

  • comprendre les nuances entre les différents types
  • être capable pour une donnée du monde réel (la valeur que l'on veut stocker) de distinguer les différentes nuances associées aux différents types


Par exemple, un double et un BigDecimal représentent tout les deux un nombre décimal. Alors que le double ne connaît pas de limite à sa précision : la même variable peut contenir un nombre précis à 2 ou 10 chiffres après la virgule, ce n'est pas le cas d'un BigDecimal, cet objet possède un attribut précision qui indique le nombre de chiffres après la virgule. Pour changer sa précision il faut faire appel à une méthode.

Pour un float, 1,23 et 1,230 sont identiques, ce n'est pas le cas pour un BigDecimal car l'attribut précision n'est pas le même.

De même, si l'on sait aujourd'hui, qu'une valeur en euro sera inférieure disons à 1 000 000 €, on ne peut que difficilement savoir la limite qu'il faudra prendre en compte dans une dizaine d'années surtout s'il faut prendre en compte un changement de monnaie.

En conséquence, vouloir pour chaque montant définir des limites différentes en fonction de l'information n'est pas nécessairement pertinent : cela augmente la difficulté du choix et on n'a pas toujours la possibilité de prévoir les évolutions (on augmente le risque d'erreur en voulant être précis).

Pour que ces choix restent pertinents et efficaces sur la durée de vie de l'application (souvent plusieurs années), il faut que les différents développeurs manipulant ces données sachent les manipuler efficacement. On a donc bien souvent intérêt à :

  • se limiter à un ensemble de types restreint : une trop grande précision peu provoquer dans certain cas des effets de bords néfastes par exemple dans la taille des Strings : à la fin, on ne sait jamais quelle est la taille d'un champ et du coup la probabilité d'un développeur pressé de se tromper dans le contrôle est plus grande.
  • utiliser des types bien connus et maîtrisés par l'ensemble de l'équipe : si un type est mal maîtrisé, son utilisation peut être catastrophique car un des premiers réflexes est bien souvent de revenir à un type connu, ce qui a le double effet de rajouter une surcharge de travail ainsi que des risques d'apparition d'effets de bord lors des conversions. Les effets de bords sont bien évidemment ceux là même qu'on souhaitait éviter avec le choix de ce type.


Mon expérience acquise à travers l'audit de projets montre que bien souvent le mieux est l'ennemi du bien. Une optimisation trop poussée qui force à sortir des sentiers balisés a souvent des effets bien plus pervers pour un projet qu'une optimisation plus raisonnable.

Pour finir, le typage d'une "information" n'est pas intrinsèque à son contenu. Son utilisation a également son importance. Prenant pas exemple un numéro composé exclusivement de chiffres, cela ne veut pas dire qu'il devra être stocké sous forme d'un entier en base. Dans de nombreux cas, il est préférable de le stocker sous forme d'une chaîne de caractères. Cela va dépendre des contrôles que l'on souhaite faire, des recherches que l'on souhaite réaliser...

D'autre part, si une information doit être stockée en base, elle doit également être manipulée en Java et affichée dans un écran. Pour un développement efficace, il faut que le passage d'une représentation à l'autre et les contrôles soient rapides et efficaces. Hibernate et JPA facilitent ce travail, encore ne faut-il pas lui mettre trop de bâtons dans les roues en le forçant à utiliser des types incompatibles.

Les règles retenues sont :

  • limitation du nombre de types
  • des types connus
  • une certaine portabilité à travers les bases de données
  • un typage cohérent de la base à l'affichage en passant par la représentation mémoire en Java

Typage des données

Nous avons cinq grands types de données que nous subdivisons en des types plus proches des utilisations :
  • Les types numériques
    • Les montants monétaires : il s'agit des valeurs dans une monnaies comme les prix, soldes, montant, commissions...
    • Les mesures : il s'agit d'une valeur décimale qui correspond à la mesure d'un objet qu'il s'agissent d'une distance, d'un poids...
    • Les taux et pourcentages : il s'agit de valeurs décimales faibles (inférieur à 100) et nécessitant parfois une précision un peu plus grande (certains taux possèdent 4 chiffres après la virgule)
    • Les quantités : il s'agit de valeurs entières permettant de donner un nombre d'unités d'un produit.
  • Les valeurs alphanumériques
    • Les chaînes de caractères : les chaînes de caractères classiques qui stockent une information en claire (non codée)
    • Les codes : il s'agit d'une information courte (moins d'une dizaine de caractères) qui est codé.
    • Les commentaires : il s'agit d'un texte composé de plusieurs mots.
  • Les valeurs énumérées
    • Les valeurs Vrai-Fausse : cela correspond aux cases à cocher
    • Les listes déroulantes et énumérations : il s'agit d'information dont la sélection se fait dans une liste déroulante. on stocke en base un code et on affiche un libellé grâce à une table de paramètre qui assure la correspondance.
  • Les dates et timestamp
    • Les dates traditionnelles précises au jour près
    • les heures : une heure dans la journée indépendante de la date
    • les tags horaires (TimeStamp) qui permettent de conserver la trace de l'heure précise d'un événement. Ceux sont des dates précises à la milliseconde
  • Les identifiants
    • les numéro de dossier
    • les séquences

Type Montant Monétaire

Les montants monétaires ont une particularité : le nombre de chiffres après la virgule est une constante (souvent 2). Les problèmes d'arrondis doivent toujours être résolu avec cette contrainte : il n'est pas possible d'augmenter temporairement le nombre de chiffres après la virgule.

D'autre part, le BigDecimal est d'une précision absolue dans les comparaisons de nombre décimaux ce qui est impératif pour les montants monétaires.

Pour plus de détail sur l'intérêt de l'utilisation des BigDecimal vous pouvez lire mon billet : Tutorial sur les BigDecimal

Le stockage par hibernate d'un BigDecimal est un Number de 19 chiffres avec 2 chiffres après la virgule. Nous utiliserons ce format pour tous les montants.

Le nombre de chiffres (19) peut paraître excessif si on compte en Euro, mais en Yen cela se réduit et encore plus pour d'autres monnaies.

Il me parait donc plus sage de rester sur la taille par défaut.

Exemple de définition d'un montant :


    @Column(name="JLTS_AMOUNT", precision=19, scale=2)
    private BigDecimal amountDefault;


Le BigDecimal étant un objet, il peut être Null comme les colonnes correspondantes en base. Il n'aura donc aucun problème à s'adapter au cas où la valeur peut être Null.

Base de données Type Base Remarque
Oracle NUMBER(19,2) Le nombre est tronqué si la précision est plus grande
MySql decimal(19,2) Une exception est envoyée si la précision est plus grande
HSqlDb

numeric

Le stockage ne connaît ni précision ni contrôle on stocke exactement ce que l'on a reçu
Sql Server numeric(19,2) Le nombre est tronqué si la précision est plus grande, le nombre est complété pour respecter la précision

 

Type Mesure

Une mesure ressemble à un Montant monétaire, à une différence près : la précision des chiffres après la virgule n'est pas d'une grande importance (il ne faut pas oublier que la précision d'une mesure physique est rarement supérieure à 1%).

Il peut donc être judicieux de stocker une mesure dans un double ou Double, ce qui facilite la programmation.

Exemple de définition d'un montant :

 

    @Column(name="JLTS_MESURE", nullable=false)

    private double mesure;

 

Base de données Type Base Remarque
Oracle double precision  
MySql double precision  
HsqlDb double  
Sql Server double precision  

 

Type Taux et Pourcentage

Les taux et pourcentage sont généralement associés aux données de type monétaire. Il s'agit souvent de réaliser des multiplications d'un montant monétaire afin d'obtenir une nouvelle somme. Généralement, un taux pourcentage peut être stockées avec 2 ou 4 chiffres après la virgule et ne dépasse pas les 3 chiffres avant la virgule. Afin de simplifier la modélisation, on utilisera donc la définition suivante :


    @Column(name="JLTS_TAUX", precision=7, scale=4, nullable=false)
    private BigDecimal taux;


Notez l'attribut nulllable positionné à false par défaut : il est fort probable que par défaut, un taux soit positionné à 0 et non pas laissé à Null. La valeur Null rend délicat les opérations réalisée par défaut alors qu'avec la valeur 0, le résultat serait fonctionnellement correct dans de nombreux cas.

 

Base de données Type Base Remarque
Oracle NUMBER(7,4) Le nombre est tronqué si la précision est plus grande
MySql decimal(7,4) Une exception est envoyée si la précision est plus grande
HsqlDb numeric  
Sql Server numeric(7,4) Le nombre est tronqué si la précision est plus grande, le nombre est complété pour respecter la précision

 

Type Quantité entière

Il s'agit de valeurs entières comme le nombre d'articles achetés. On optera pour un type Long si la valeur peut être Null autrement on optera pour un long. Attention ! dans ce cas, il faut préciser l'attribut nullable à false. Il est fort probable que dans de nombreux cas, le défaut d'une quantité soit la valeur 0 : Dans ce cas, le long sera plus approprié.


    @Column(name="JLTS_QUANTITY", nullable=false)
    private long longNumeric;

ou bien

    @Column(name="JLTS_QUANTITYNULL")
    private Long longObject;

 

Base de données Type Base Remarque
Oracle NUMBER(19,0) Le nombre est tronqué si la précision est plus grande
MySql bigint  
HsqlDb bigint  
Sql Server numeric(19,0) Le nombre est tronqué si la précision est plus grande

Type Chaîne de caractères

Il s'agit de toutes les chaînes de caractères classiques qui correspondent à une information relativement structurée comme un nom, un prénom, un nom de rue... Ces chaînes sont d'une taille raisonnable : inférieure à 250 caractères. Au delà, ce sera probablement une donnée de type Commentaire.

Le stockage d'une chaîne de caractères est des plus simples : une String.

@Column(name="JLTS_NAME", length=40)

private String name;

 

Base de données Type Base Remarque
Oracle varchar2(40 char) Où 40 est la length. Oracle ne distingue pas les chaînes vide des chaînes Null. Il ne stocke que des chaînes Null. L'attribut char après la longueur indique la prise en compte des caractères UTF-8.
MySql varchar(40) MySql fait la différence entre une chaîne vide et une chaîne Null.
HsqlDb varchar(40) Il n'envoie aucune exception en cas de chaine trop grande
Sql Server varchar(40)  

 

Type Code

Certaines informations sont stockées sous la forme d'un code :

  • code postaux
  • code monnaie
  • code d'un état
  • code d'une banque
  • Siren
  • Siret

En règle général les codes ont une longueur fixe et relativement courte (inférieur à 10 caractères). Ils peuvent être alphanumériques ou numériques.

Ils peuvent également correspondre au type "Liste déroulante" décris plus loin. Les distinguer n'a pas d'intérêt car le résultat sera le même. On utilise un type String.

 

@Column(name="JLTS_SHORTCODE", nullable=true, length=2)
private String ShortCode;

 

Base de données Type Base Remarque
Oracle varchar2(2 char)  
MySql varchar(2)  
HsqlDb varchar(2)  
Sql Server varchar(2)  

 

Type Commentaire

Il y a de forte chance que toute information qui dépasse la centaine de caractères soit un champ de type commentaire. Même s'il est confortable de limiter ce champ à un type String et un stockage en base limité à un ou deux milles caractères, cette approche à de forte chance de ne pas résister aux besoins futures des utilisateurs. Il est donc préférable d'utiliser une représentation sous forme de CLOB.

    @Lob 

    @Column(name="JLTS_COMMENT")

    private String commentaire;

 

 

Base de données Type Base Remarque
Oracle CLOB  
MySql longtext  
HsqlDb longvarchar  
Sql Server text  

 

 

Type Booléen Vrai-Faux

Il s'agit des informations qui sont affichées généralement sous forme de case à cocher (CheckBox). La valeur peut être Vrai ou Fausse.

Toutes les bases mais surtout la plus connue et la plus employée (Oracle) ne possèdent pas de type Booléen. L'information devra être stockée sous forme d'un caractère (Y,N par exemple) ou d'un nombre (0,1).

L'annotation standard JPA est celle là.

@Column(name="JLTS_BOOLEAN")
private boolean booleanType;

 

Base de données Type Base Remarque
Oracle number(1,0) 0 pour false et 1 pour true
MySql bit correspondance directe avec true et false
HsqlDb bit  
Sql Server tinyint 0 pour false et 1 pour true

 

Il existe une annotation propre à Hibernate (non JPA) qui permet d'indiquer le stockage en base :

@Type(type="yes_no")
@Column(name="JLTS_YESNO")
public boolean yesNo;

 

@Type(type="true_false")
@Column(name="JLTS_TF")
public boolean trueFalse;

 

Base de données Type Base Remarque
Oracle char(1 char) Stockage sous forme de lettre Y et N pour yes_no
MySql CHAR(1) T et F pour true_false,
HsqlDb    
Sql Server char(1)  

 

Type Liste déroulante et énumération

Il s'agit du cas représenté généralement par une liste déroulante (ComboBox ou composant SELECT HTML). Il y a une série de libellés qui correspondent à un code.

Le stockage en base est un code.

Généralement le code appartient à une autre colonne (notion de Foreign Key).

Le stockage aura lieu sous forme de chaîne de caractère classique :

@Column(name="JLTS_COMBOBOX", nullable=true, length=2)
private String selection;

Je ne recommande pas l'utilisation de many-to-one pour ce type de relation : ce type de relation alourdit l'affichage quand il s'agit d'une information qui correspond à une table de paramètre. Le many-to-one doit être réservé aux liaisons entre véritables objets.

 

Base de données Type Base Remarque
Oracle varchar2(2 char)  
MySql varchar(2)  
HsqlDb varchar(2)  
Sql Server varchar(2)  

   

Type Date précise au jour

Le cas des dates est très particulier, le type Date est d'une précision bien supérieure au besoin de stockage des dates qui se limite à une précision au jour près.

JPA définit une annotation Temporal qui permet de limiter la précision au jour (DATE), à l'heure (TIME) où une précision extrême et complète (TIMESTAMP)

La précision est importante au niveau des dates : il est souhaitable qu'une recherche sur les enregistrements ayant une colonne Date qui correspond à la date du jour 22/09/2009 renvoie tous les enregistrements en passant par une égalité.

Si la précision est trop grande (au niveau de la seconde) cela ne fonctionnera pas.

@Temporal(TemporalType.DATE)
@Column(name="JLTS_DATE", nullable=true)
private Date dayDate;

 

Base de données Type Base Remarque
Oracle date Le stockage est sous une précision dd/MM/yyyy. L'égalité au niveau jour fonctionne dans les requêtes Oracle (en utilisant To_Date)
MySql date L'égalité au niveau jour fonctionne dans les requêtes MySql (en utilisant str_to_date)
HsqlDb date  
Sql Server datetime Le stockage est sous une précision dd/MM/yyyy. L'égalité au niveau jour fonctionne dans les requêtes Sql Server(en utilisant Cast)

 

Type Heure

Il s'agit d'une heure dans la journée, indépendante du jour. Ce type est rarement utilisé. Son manque de portabilité me pousse à préférer le TimeStamp.

 

@Temporal(TemporalType.TIME)

@Column(name="JLTS_TIME", nullable=true)

private Date time;

 

Base de données Type Base Remarque
Oracle date Ce format ne fonctionne pas en Oracle
MySql time  
HsqlDb time  
Sql Server datetime  

 

Type TimeStamp

Il s'agit d'une date précise souvent à la milliseconde qui permet de conserver une trace d'un événement. Ce type de colonne est souvent dans des tables d'historiques ou d'audit qui conservent une trace des modifications faites par les utilisateurs.

Ce type de trace sert principalement au besoin d'audit et de traçabilité de l'information.

Sa précision à la seconde ne permet pas de rechercher simplement les enregistrements dont la valeur du TimeStamp est égale à une date. 

@Temporal(TemporalType.TIMESTAMP)
@Column(name="JLTS_TIMESTAMP", nullable=true)
private Date timeStampAudit;

 

 

Base de données Type Base Remarque
Oracle timestamp  
MySql datetime La précision de ce format est plus faible qu'en Oracle
HsqlDb timestamp  
Sql Server datetime La précision de ce format est plus faible qu'en Oracle

 

Type Identifiant Séquence

L'identifiant le plus simple est une clé numérique automatique. Oracle possède la notion de séquence pour cela. Dans d'autre cas, il faut passer par une autre table qui permet de stocker le compteur.

Pour la portabilité, il est souhaitable d'utiliser le type automatique suivant : GenerationType.AUTO.

GenerationType.SEQUENCE fonctionne bien avec Oracle mais pas avec MySql.

GenerationType.IDENTITY : fonctionne bien avec MySql mais pas avec Oracle.

 

@Id

@GeneratedValue(strategy=GenerationType.AUTO)

@Column(name="LONG_ID", nullable=false)

private long id=0;

 

Cela correspond à une séquence 

Base de données Type Base Remarque
Oracle number(19,0) Il y a création est utilisation d'une Séquence Oracle hibernate_sequence.
MySql bigint  
HsqlDb bigint generated by default as identity (start with 1)  
Sql Server numeric(19,0) identity  

 

Type Numéro de dossier

Il existe des informations qui sous une apparence numérique (elles ne sont composées que de chiffres) sont plus souvent manipulées comme une chaîne de caractères que comme un nombre.

Par exemple, on ne fait pas d'opération arithmétique sur un numéro de dossier ou le numéro de sécurité sociale : additionner un nombre, le multiplier, le diviser ou le comparer non pas de sens.

Il est plus courant de faire des concaténations de chaînes : le code sexe, le code département pour un numéro de sécurité sociale.

Pour un numéro de dossier, on peut trouver pratique de faire une recherche en ne tapant qu'une partie du numéro en utilisant un Like.

Pour ces champs, il est souhaitable d'utiliser un type String.

@Column(name="JLTS_NUMERO", nullable=true, length=10)
private String NumeroDossier;

 

Base de données Type Base Remarque
Oracle varchar2(10 char)  
MySql varchar(10)  
HsqlDb varchar(10)  
Sql Server varchar(10)  

 

Nullité d'une colonne

Une colonne peut être nulle ce qui est différent de la valeur 0 pour un nombre et d'une chaîne vide "" pour une String. Oracle est une exception notoire pour les String : Oracle insère un Null dans une colonne quand on lui passe une chaîne vide. Ce point est encore d'actualité avec un Oracle 10G et le driver ojdc14.jar.

Les types Java acceptent s'ils sont d'un type objets (BigDecimal, Double, Long...) la valeur Null ce qui n'est pas le cas des types natifs (double, long, integer...). Le type String accepte la valeur Null.

D'un point de vu technique, il n'est pas judicieux d'utiliser un type natif si la colonne ne possède pas l'attribut Not Null : on risque des problèmes ou des incohérences si on récupère une valeur Null.

 

D'un point de vu fonctionnel, le Null doit servir à distinguer une valeur non saisie des autres : On utilisera le Null s'il est pertinent de distinguer 0 de l'absence de saisie.

Par exemple, il n'est pas souhaitable que la note d'un enfant soit par défaut 0. Il est important d'être capable de distinguer l'absence de notation (le Null) d'une note nulle (0).

Dans le cas, d'un rabais, c'est probablement l'inverse, on souhaite que par défaut la valeur soit 0. Cela permet de faire simplement les calculs. La valeur peut rester à 0 sans grand impact. En règle générale, le changement de cette valeur nécessite des attributions spéciales (par exemple être manager). 

 

Pour les chaînes de caractères on évitera de distinguer le cas des null des chaînes vides afin de conserver la portabilité vers Oracle. Cela n'est pas nécessairement un problème important. Le statut d'un objet (qui peut être détecté par la différence entre un champ Null et vide) peut également et probablement mieux rendu par une colonne spécifique STATUT/ETAT (il s'agit du type Code).

Pour les nombres, le choix est plus délicat :

  • l'absence de null facilite les calculs : le calcul n'a pas beson de tester l'existence d'un Null
  • le 0 peut souvent être pris comme une valeur par défaut
  • il existe des cas (comme pour une note) ou le 0 ne peut être considéré comme une valeur par défaut, dans ce cas, le Null est indispensable.

 

Il ne faut pas perdre de vu que le créateur de l'objet métier n'a pas nécessairement tous les droits pour saisir toutes les valeurs. il peut s'agir d'un opérateur de saisi qui n'a pas les habilitations pour remplir certaines valeurs sensibles. Dans ce type de process, il peut être important que la personne qui possède les droits pour compléter le dossier puisse distinguer d'un rapide coup d'oeil les informations qui lui reste à saisir. Dans ce cas, les Null peuvent être utiles même si dans d'autres cas, la valeur 0 sera très pertinente.

Dans notre exemple précédent, le rabais pourra rester à 0.

S'il faut une règle simple : je donnerai la règle suivante : Le null est utile si la valeur par défaut du champ ne peut pas être 0, dans les autres cas, il sera préférable de ne pas utiliser de Null.

Conclusion

La phase de conception du modèle de données peut être grandement simplifiée en limitant la définition des types à la liste précédemment donnée :

Type Notation JPA Oracle Mysql HsqlDb Sql Server

Montant monétaires

@Column(name="JLTS_AMOUNT", nullable=true, precision=19, scale=2)

private BigDecimal amount;

NUMBER(19,2)

decimal(19,2)

numeric

numeric(19,2)

Mesure

@Column(name="JLTS_MESURE", nullable=false)

private double mesure;

double precision

double precision

double

double precision

Taux et pourcentages

@Column(name="JLTS_TAUX", nullable=true, precision=7, scale=4)

private BigDecimal taux;

NUMBER(7,4)

decimal(7,4)

numeric

numeric(7, 4)

Quantité

@Column(name="JLTS_LONG", nullable=false)

private long longNumeric;

NUMBER(19,0)

bigint

bigint

numeric(19,0)

Chaînes de caractères

@Column(name="JLTS_STRING",  length=40)

private String textString;

VARCHAR2(40 CHAR)

varchar(40)

varchar(40)

varchar(40)

Code

@Column(name="JLTS_SHORTCODE", nullable=true, length=2)

private String shortCode;

VARCHAR2(2 CHAR)

varchar(2)

varchar(2)

varchar(2)

Commentaire

@Lob

@Column(name="JLTS_COMMENT")

private String commentaire;

CLOB

longtext

longvarchar

text

Vrai-Fausse et Booléen

@Column(name="JLTS_BOOLEAN")

private boolean booleanType;

NUMBER(1,0)

bit

bit

tinyint

Liste déroulante

@Column(name="JLTS_SHORTCODE", nullable=true, length=2)

private String shortCode;

VARCHAR2(2 CHAR)

varchar(2)

varchar(2)

varchar(2)

Date

@Temporal(TemporalType.DATE)

@Column(name="JLTS_DATE", nullable=true)

private Date dayDate;

DATE

date

date

datetime

Heure

@Temporal(TemporalType.TIME)

@Column(name="JLTS_TIME", nullable=true)

private Date time;

DATE

time

time

datetime

Tags horaires (TimeStamp)

@Temporal(TemporalType.TIMESTAMP)

@Column(name="JLTS_TIMESTAMP", nullable=true)

private Date timeStampAudit;

TIMESTAMP

datetime

timestamp

datetime

Numéro de dossier

@Column(name="JLTS_NUMERO", nullable=true, length=10)

private String numero;

VARCHAR2(10 CHAR)

varchar(10)

varchar(10)

varchar(10)

Séquence

@Id

@GeneratedValue(strategy=GenerationType.AUTO)

@Column(name="LONG_ID", nullable=false)

private long id=0;

NUMBER(19,0)

bigint

bigint

numeric(19,0) identity

 

Dans le cas d'une phase de ré-ingénierie d'un modèle de données existant, il sera probablement possible de se baser sur les mêmes types en changeant peut être leur représentation JPA afin de l'adapter à l'existant en base.

Par exemple, si en base les montants sont des NUMBER(11,2), le type montant pourra être de type

   @Column(name="JLTS_MONTANT", precision=11, scale=2, nullable=false)
    private BigDecimal montant;

Dans la pratique, on ne devrait pas voir apparaître plus de deux déclinaisons d'un même type dans un modèle existant.

J'espère que ce tutorial simplifiera la conception de vos prochains modèles de données. Un prochain billet présentera un projet de test permettant de mieux appréhender les différents comportements.


DiggIt! Enregistrer sur Del.icio.us

mardi, juillet 07, 2009

Tutorial sur les montants et l'utilisation des BigDecimal en Java :

3 commentaires
DiggIt! Enregistrer sur Del.icio.us

L'objectif de ce billet est double. Premièrement, il s'agit d'une sensibilisation au besoin impérieux d'utiliser des BigDecimal à la place des double dans les applications de gestion.

Secondement, nous allons donner quelques recommandations pour l'utilisation efficace des BigDecimal.

Pourquoi utiliser des BigDecimal et non des double

La manipulation de montant en programmation s'est souvent heurtée à quelques problèmes de comparaison : deux chiffres censés être égaux sont testés comme différents : par exemple 7273.27x10 est différent de 72732.7.

Le mécanisme de stockage traditionnel des nombres en binaire : une somme de puissance de 2, est responsable de ce problème.

Des nombres aussi simple que 0,1 ne peuvent pas être stockés précisément sous cette forme. En conséquence 0,1 n'est jamais exactement égale à 0,1. Donc 0,1x10 n'est pas exactement égale à 1. Hors 1 = 2^0, donc 1 possède lui une représentation exacte. Si on faisait 0,1x10 une comparaison avec 1 donne dans ce cas un résultat erronée.

N.B. Il semble que le cas du 0,1 soit mieux traité maintenant puisqu'en Java, si on utilise des double, on a bien 0,1x10=1.0.

Dans les applications de gestion, les nombres sont souvent des montants ou des pourcentages : le nombre de chiffres après la virgule est généralement connu (entre 2 et 4 voir 6 ou 8 pour certaines applications financières).

En cas de division, il existe des règles d'arrondies et il n'est pas souhaitable de modifier le stockage pour gagner en "précision". Ces applications ne connaissent pas les réels : 1/3 va être égale à 0,33.

Le BigDecimal en Java

En Java, il existe un type BigDecimal qui permet de prendre en compte ce type de problématique : il repose sur le fait qu'un entier possède une représentation binaire exacte.

Pour un montant, il suffit de définir le nombre de chiffres après la virgule et de stocker le nombre sous forme entière : par exemple on stockera 7273.27 sous la forme d'une valeur de 727327  possédant 2 chiffres après la virgule. Le nombre de chiffres après la virgule correspond à la propriété scale du BigDecimal.

L'utilisation de BigDecimal entraîne une petite contrainte : il ne s'agit pas d'un type natif mais d'un objet. Il n'est donc pas possible d'utiliser les opérateurs +, -, * et /.

Par exemple

7273.27*10.0 qui avec des doubles s'écrit :

double doubleApproche=7273.27;       
double resultat=10*doubleApproche;

devient en BigDecimal :

BigDecimal doubleApproche=new BigDecimal("7273.27");       
BigDecimal resultat=doubleApproche.multiply(new BigDecimal(10));

Exemple de projet

Nous allons créer un projet Eclipse simple afin d'illustrer les différents cas.

Dans le menu : File -> New Project

Choisir ensuite dans le noeud Java : Java Project.

Le nom du projet sera TestBigDecimal.

Appuyer sur le bouton Finish.

Sur le noeud src, clique droit et choisir New -> New Junit Test Case

Chosir le radio button New JUnit 4 test.

Package : fr.j2ltho.test.bigdecimal

Name : TestDifferences

Puis appuyer sur le bouton Finish.

 

Une boite de dialogue apparaît : "JUnit 4 is not on the build path. Do you want to add it ?".

Choisir le radio bouton : Perform the following action:

Et vérifier qu'il y a bien : Add JUnit 4 library to the build path.

Valider en appuyant sur le bouton OK.

 

On ajoute le code suivant :

package fr.j2ltho.test.bigdecimal;

import static org.junit.Assert.assertEquals;

import java.math.BigDecimal;

import org.junit.Test;

public class TestDifferences {
    @Test(timeout=1000)
    public void testProblemeDouble() {
        double doubleApproche=7273.27;       
        double resultat=10*doubleApproche;
        assertEquals("Double fois 10", 72732.7, resultat);
        if (resultat==72732.7) {
            System.out.println("Egale:  " + resultat);
        }
        else {
            System.out.println("Ecart:  " + (resultat-72732.7));           
        }       
    }
    @Test(timeout=1000)
    public void testProblemeBigDecimal() {
        BigDecimal doubleApproche=new BigDecimal("7273.27");       
        BigDecimal resultat=doubleApproche.multiply(new BigDecimal(10));
        assertEquals("BigDecimal fois 10", new BigDecimal("72732.7"), resultat);
        if (resultat.compareTo(new BigDecimal("72732.7")) ==0){
            System.out.println("Egale:  " + resultat);
        }
        else {
            System.out.println("Ecart:  " + (resultat.subtract(new BigDecimal("72732.7"))));           
        }       
    }
    @Test(timeout=1000)
    public void testDixiemeDouble() {
        double doubleApproche=0.1;       
        double resultat=10*doubleApproche;
        assertEquals("Double fois 10", 1.0, resultat);
        if (resultat==1.0) {
            System.out.println("Egale:  " + resultat);
        }
        else {
            System.out.println("Ecart:  " + (resultat-1.0));           
        }       
    }
    @Test(timeout=1000)
    public void testCentiemeDouble() {
        double doubleApproche=0.01;       
        double resultat=10*doubleApproche;
        assertEquals("Double fois 10", 0.10, resultat);
        if (resultat==0.10) {
            System.out.println("Egale:  " + resultat);
        }
        else {
            System.out.println("Ecart:  " + (resultat-0.10));           
        }       
    }
    @Test(timeout=1000)
    public void testDixiemmeCentiemeDouble() {
        double doubleApproche=0.11;       
        double resultat=10*doubleApproche;
        assertEquals("Double fois 10", 1.10, resultat);
        if (resultat==1.10) {
            System.out.println("Egale:  " + resultat);
        }
        else {
            System.out.println("Ecart:  " + (resultat-1.10));           
        }       
    }
}

 

L'éxécution du test : Run As -> JUnit Test donne un test réussi à 100% mais avec le résultat suivant dans la Console :

Ecart:  1.4551915228366852E-11
Egale:  72732.70
Egale:  1.0
Egale:  0.1
Egale:  1.1

On constate donc que la comparaison JUnit assertEquals : assertEquals("Double fois 10", 72732.7, resultat); renvoie un résultat juste alors que la comparaison des doubles renvoient une erreur et que la différence renvoie un écart.

Si on manipule des doubles Java, il faut se méfier de assertEquals qui semblent prendre en compte un écart d'arrondi.

Création d'un BigDecimal

Le BigDecimal est un objet, il est créé avec un new. Son constructeur accepte une String, un long ou un double.

Il ne faut jamais utiliser le constructeur du double car on réintroduit le problème de l'arrondie.

Le test suivant illustre le problème :

@Test(timeout=1000)
public void testProblemeConstructeurDouble() {
    BigDecimal doubleApproche=new BigDecimal(7273.27);       
    BigDecimal stringApproche=new BigDecimal("7273.27");       
    assertEquals("BigDecimal fois 10", doubleApproche, stringApproche);
    if (doubleApproche.compareTo(stringApproche) ==0){
        System.out.println("Egale:  " + doubleApproche);
    }
    else {
        System.out.println("Ecart:  " + (doubleApproche.subtract(stringApproche)));           
    }       
}

La console affiche :

Ecart:  4.3655745685100555419921875E-13

Là encore, on constate que le assertEquals pour les BigDecimals n'est pas fiable puisqu'il indique une égalité qui n'est pas réelle.

Pour les entiers, il est préférable d'utiliser la méthode static valueOf() qui est plus lisible :

BigDecimal.valueOf(40)

Il existe trois méthodes statiques pour créer un BigDecimal de valeur 1 ou 0 ou 10.

  • BigDecimal.ONE
  • BigDecimal.ZERO
  • BigDecimal.TEN

 

En bref, on recommande d'utiliser :

  • Pour un montant, un taux ou un pourcentage, le constructeur avec un paramètre String :  BigDecimal stringApproche=new BigDecimal("7273.27");
  • Pour un nombre d'unités, la méthode static valueOf : BigDecimal.valueOf(40)
  • Pour les valeurs remarquables 0, 1 et 10 : on utilise les méthodes statics : BigDecimal.ZERO, BigDecimal.ONE et BigDecimal.TEN          

Addition et soustraction avec BigDecimal.

L'addition et la soustraction ne présentent pas de particularité en dehors de l'obligation d'utiliser une méthode :

  • subtract
  • add

On aura par exemple

    BigDecimal valeur=new BigDecimal("70.36")
    // resAddition = valeur + 1
    BigDecimal resAddition = valeur.add(BigDecimal.ONE);
    // resSoustraction = valeur -10
    BigDecimal resSoustraction = valeur.subtract(BigDecimal.TEN);

Multiplication et Division de BigDecimal

La multiplication répond au même principe que l'addition et la soustraction avec la méthode : multiply.

BigDecimal pricePerShare=new BigDecimal("70.36");
// coutTotal = pricePerShare * 3
BigDecimal coutTotal =pricePerShare.multiply(BigDecimal.valueOf(3));


Pour la division, c'est plus compliqué car il faut indiquer :

  1. le nombre par lequel on divise
  2. mais surtout le nombre de chiffre après la virgule que l'on souhaite conserver pour le résultat (une division ne tombe pas toujours juste)
  3. et pour finir le mécanisme d'arrondi : nous utiliserons généralement BigDecimal.ROUND_HALF_UP

Par exemple, le nombre de parts achetées :

BigDecimal pricePerShare=new BigDecimal("70.36");
BigDecimal purchaseAmount=BigDecimal.valueOf(200);
// nbPart = purchaseAmount/pricePerShare
BigDecimal nbPart = purchaseAmount.divide(pricePerShare, 4, BigDecimal.ROUND_HALF_UP);       

Il existe deux méthodes qui permettent de simplifier les multiplications et les divisions par des multiples de 10 :

  • movePointLeft(2) on déplace la virgule de 2 vers la gauche ce qui correspond à une division par 100.
  • movePointRight(1) on déplace la virgule de 1 vers la droite ce qui correspond à une multiplication par 10.

Ces deux méthodes sont particulièrement utiles lorsqu'on calcule des taux ou des pourcentages.

BigDecimal total=BigDecimal.valueOf(950);
BigDecimal percentage=BigDecimal.valueOf(20);
// On veut 20% de 950
// montant = (total*percentage)/100
BigDecimal montant = total.multiply(percentage).movePointLeft(2);       

Comparaison

il faut favoriser la méthode : compareTo qui fait abstraction du nombre de chiffres après la virgule. compareTo considère que 15.2 et 15.200 sont identiques. Ce n'est pas le cas avec equals().

La méthode compareTo renvoie un entier et non pas un booléen :

  • 0 si la valeur est identique
  • 1 si la valeur est supérieure à celle du paramètre
  • -1 si la valeur est inférieure à celle du paramètre

Dans le cadre de l'utilisation de JUnit nous recommandons d'utiliser :

assertEquals("Comparaison", 0, doubleApproche.compareTo( stringApproche));   

à la place de :

assertEquals("Comparaison imprécise", doubleApproche, stringApproche);

En effet dans certain cas (petit écart) : la première indiquera bien une différence alors que la seconde indiquera une égalité.

Affichage

Pour afficher un BigDecimal, il existe deux méthodes :

  • plainString
  • toString

Nous recommandons l'utilisation d'une troisième solution : l'utilisation du formatage avec DecimalFormat. ce mécanisme permet de forcer la représentation du BigDecimal suivant un format défini.

L'exemple suivant est significatif : nous avons volontairement utilisé le constructeur double pour montrer la différence.

BigDecimal doubleApproche=new BigDecimal(7273.27);       

System.out.println("7273.27 toPlainString:  " + doubleApproche.toPlainString());
System.out.println("7273.27 toString :  " + doubleApproche.toString());

DecimalFormat decimalFormat = new DecimalFormat("##,###,###,##0.00");
System.out.println("7273.27 DecimalFormat :  " + decimalFormat.format(doubleApproche));

Conclusion

L'utilisation de BigDecimal est un peu plus lourde que celle de double. Mais on retrouve un ensemble de méthodes qui simplifie le travail et surtout l'assurance de ne pas avoir de problème d'arrondi à la fin.

Cela nous force à lever l'ambiguïté du choix des arrondis très tôt : Cela permet d'éviter des déconvenues avec les équipes métiers lors des phases de recette. Les équipes métiers connaissent parfaitement ces règles, elles leur sont tellement naturelles qu'ils en oublient de les spécifier. L'utilisation de BigDecimal nous force à déterminer dés le début de la programmation ce qu'il faut faire.


DiggIt! Enregistrer sur Del.icio.us

lundi, mai 25, 2009

AppStore : Analyse d'un succès

0 commentaires
DiggIt! Enregistrer sur Del.icio.us

Ce billet fait parti d'une réflexion plus large sur les aspects révolutionnaires de l'iPhone. Il se concentre sur l'AppStore dont le succès dépasse les simples chiffres fournis par Apple : 35 000 applications et 1 milliard de téléchargements en date de mai 2009 (le communiqué de presse d'Apple : http://www.apple.com/fr/pr/library/2009/04/24appstore.html?sr=hotnews).

Cette approche de place de marché a été reprise depuis par Google, Nokia, Microsoft et RIM (pour les BlackBerry). Le concept semble être suffisamment novateur et intéressant pour être repris par la concurrence.

Depuis avril 2009, les publicités pour l'iPhone se concentre exclusivement sur les applications disponibles sur l'AppStore et non plus sur l'iPhone lui-même. C'est un signe de l'importance de l'écosystème iPhone dans la décision d'achat. Et qui mieux que l'AppStore symbolise cet écosystème.

L'AppStore

Commençant par présenter rapidement l'AppStore surtout pour les lecteurs qui ne sont pas familier avec l'iPhone. L'AppStore est un super marché d'applications pour iPhone et iPod Touch. On y trouve des applications payantes et des applications gratuites.

L'AppStore est un département du fameux iTunes Store (leader mondial de la vente de musique). Il est accessible à partir du logiciel iTunes : Pour naviguer à travers l'AppStore, il n'est donc pas nécessaire de posséder un iPhone, il suffit d'utiliser iTunes. Il existe une version de l'AppStore pour iPhone, il est donc possible de consulter et charger des applications directement depuis l'iPhone.

L'AppStore possède différent classement des applications : en règle générale il existe deux classements séparés : un pour les applications gratuites et un pour les applications payantes. Les applications gratuites ne sont ni cachées ni enterrées au fond du site : elles disposent de la même visibilité que les applications payantes.

Ampleur du succès de l'AppStore

Apple annonce 35 000 applications dans le monde, 10 000 disponibles pour la France. Le chiffre est éloquent et il est difficile de ne pas trouver l'application dont on a besoin.

Sur les 10 000 applications on va trouver dans la rubrique Actualité une application par journal et cela pour l'ensemble de la presse mondiale. On y trouvera donc une application permettant :

  • la lecture du Monde
  • la lecture du New York Times
  • la lecture d'El Pais (Espagne)

Et bien d'autres encore. On notera que cela fait trois applications différentes.

L'iPhone peut également servir de lecteur de livre : il est possible d'acheter des livres au format éléctronique : dans ce cas, un livre est une application.

Ces exemples sont donnés pour montrer que le nombre effectif d'applications est dans la pratique inférieur à 10 000. Néanmoins, il reste très important et dépasse probablement ce qui est disponible sur les plates-formes concurrentes.

Apple annonce un milliard de téléchargements : on peut estimer le nombre d'iPhones vendus aux alentours de 20 millions. On aurait donc en moyenne 50 téléchargement par iPhone. Cela me parait excessif. Je pense qu'Apple compte un téléchargement par mise à jour. Par exemple, le lecteur du New York Times que j'utilise a du être mis à jour une dizaine de fois : Apple compte probablement 10 téléchargements.

Ceci étant dit, toutes les applications n'ont pas plusieurs versions et qui plus est : un utilisateur n'est pas obligé de faire la mise à jour. L'un dans l'autre, j'estime qu'un utilisateur a du chargé en moyenne une petite vingtaine d'applications différentes. Ce chiffre reste très important si l'on considère qu'il s'agit d'une moyenne pour un produit grand public composé majoritairement de non informaticien.

A l'époque sur mon Palm j'avais chargé 4 ou 5 applications en 4 années d'utilisation. Sur l'iPhone et grâce à l'AppStore, un utilisateur moyen a téléchargé une vingtaine d'applications en 9 mois d'utilisation.

Une telle augmentation (facteur 4) sur une population aussi large ne peut être le fait que d'un changement majeur, révolutionnaire. C'est ce ou ces changements que nous allons identifier.

Mes Applications

Avant d'aller plus loin dans l'analyse, je vais lister les 29 applications que j'ai installé sur mon iPhone : cela permettra d'illustrer les différents types d'application.

  • Les sites actualités :
    • ElPais.com : l'application du journal El Pais (Espagne)
    • Le Monde.fr : l'application du Monde. Elle permet une lecture Hors connexion des articles du site. Attention les articles sont plus courts que ceux de journal papier.
    • NYTimes : l'application du journal New York Times (Etats-Unis). Les articles semblent complets (ils sont beaucoup plus longs que ceux du Monde) mais le mode Hors Connexion fonctionne moins bien.
    • Sports.fr : Un journal sportif avec un mode Live qui permet de suivre les événements sportifs (comme une journée de championnat de foot) en direct.
  • Les Jeux
    • Crash Bandicoot Nitro : Une sorte de Mario Kart qui utilise l'accéléromètre. Pour moi du niveau de Mario Kart pour Nintendo DS à l'exception du mode multi-joueur qui n'est pas disponible.
    • Hanoi : le casse tête des tours de Hanoï
    • iChess (Free) : un jeux d'échec
    • Mastermind : le jeux du MasterMind
    • TouchMines : une version du démineur. Un peu difficile à jouer car les cases sont trop petites.
    • Virtual Pool Lite : un très bon jeu de billard américain qui rend très bien les sensations du véritable billard.
  • Les applications de productivité
    • SimpleMind Xpress : Une application de brainstorming
    • Evernote : une très bonne application de prise de notes quelles soient vocales, écrites ou également des photo prises avec l'iPhone. Il existe également un pendant Windows ainsi qu'un plug-in Firefox pour noter des morceaux de site Internet.
  • Les références et dictionnaires
    • Dictionnaire Littré : une version très ancienne et un peu passé du dictionnaire Littré que j'utilise pour expliquer des mots aux enfants
    • PagesJaunes : cette application étend le site Web en rendant disponible l'utilisation de la localisation.
    • Wapedia - Wiki mobile : Une version très conviviale de Wikipedia pour iPhone.
    • 160 000 Recipes : Un site de recette de cuisines (en anglais)
  • Aide aux déplacements
    • Wikango : un excellent avertisseur de Radar
    • PanameTraffic : Permet de visualiser l'état du trafic sur la région parisienne, devenu un peu moins utile depuis que le trafic est également disponible directement sur l'application Plan (Google Map)
    • GoVelib : Permet de connaître les stations Velib autour de vous et leur disponibilité en vélo.
    • Locly : permet de connaître quelques types de commerces ou services (comme les guichets carte bleu) autour de vous.
  • Divertissements
    • Liveradio d'Orange : permet d'écouter des stations radio à travers internet.
    • Première : les dernières critiques de cinéma avec les séances près de chez vous.
    • Stanza : un lecteur de livres pour iPhone. L'application permet le téléchargement d'une grande quantité de livres français ou anglais (tous anciens).
  • Utilitaires
    • Orange spot'finder : Permet de connaître les Hot Spot Wifi autour de vous.
    • Speedtest : Permet de mesurer le débit de votre connexion internet. Une des applications qui a permis en août/septembre 2009 de mettre en évidence le bridage de la 3G par Orange.
    • 9 - Toolbox (Free Event) : une série de petits utilitaires qui va du convertisseur d'unités au niveau à bulle
  • Réseaux sociaux
    • LinkedIn : l'application qui permet de se connecter au site social professionnel LinkedIn
  • Les applications ludiques
    • LightSaber Unleashed : un sabre laser Star War. Idéal pour épater les jeunes enfants.
  • Les applications publicitaires
    • Angoulême 2009 : Application créé pour le festival de la BD d'Angoulême qui permet de feuilleter une série de BD.

De cette liste d'applications seule Crash Bandicoot Nitro Kart 3D est payante : au tarif de 5 € son prix est très compétitif par rapport à un jeu Nintendo DS à 35 €.

Avantages du concept AppStore

L'AppStore peut être considérée comme une déclinaison de l'iTunes Store : une place de marché pour des applications. On bénéficie des mêmes avantages :

  • simplifie la recherche : il n'est pas nécessaire de rechercher dans plusieurs magasins ou sur différents sites quelles applications est la meilleure ou quelle application est disponible. Il suffit d'aller sur l'AppStore et regarder s'il y a une nouvelle application susceptible de nous intéresser.

Mais l'AppStore ajoute une caractéristique propre aux marchés des applications :

  • la confiance dans les applications : les applications sont "validées" par Apple. Même si on ne sait pas ce que cela sous entend réellement, on a la certitude que cela exclu les virus.
  • La création d'une place de marché a eu un autre effet bénéfique pour les utilisateurs : la concurrence entre producteurs d'applications à provoquer une baisse des prix significatives : la majorité des éditeurs de jeux ont lancé leurs jeux à des prix proches des 17$, quelques jours plus tard ont retrouvé les mêmes jeux autour des 7$. Du coup, on retrouve de nombreuses applications à des prix significativement plus faibles sur l'iPhone que sur les plate-formes concurrentes. Dans ma liste Crash Bandicoot Nitro Kart est un excellent exemple : pour 5 € on a un jeu qui vaudrait 35 € sur Nintendo DS.

Ces trois points expliquent certainement le milliard de téléchargements réalisés en moins d'un an.

L'AppStore comme un lien social

La confiance et la simplicité poussent aux téléchargements "ludiques" : j'entends par là, le téléchargement d'applications (bien souvent gratuites) juste pour voir ce qu'elles font. On ne cherche pas forcément l'utilité mais le coté "ludique" : un mélange de surprise et de "fun", voir un certain décalage. Ceux sont des applications que l'on va montrer qui vont servir à amorcer une discussion : elle serve à créer un lien social entre deux personnes comme on utilise parfois un article de journal, un événement où plus systématiquement un événement sportif.

Parmi ces applications on retrouvera l'emblématique Shazam qui permet de reconnaître un morceau de musique et qui est régulièrement utilisée dans les pub Apple. Dans ma liste, on trouvera Light Saber qui permet de lier la conversation avec des enfants. Certains petits jeux sont également idéals pour peu qu'ils soient simples courts et drôles.

Dans la liste des applications farfelues on retrouvera une boite à meuh (qui fait meuh quand on la retourne), un coussin péteur, des aquariums...

Ces téléchargements "ludiques" constituent un véritable phénomène parmi les utilisateurs d'iPhone et peuvent facilement compter pour un bon tiers des téléchargements. Ce phénomène est d'autant plus fort que grâce à la version iPhone de l'AppStore, le spectateur conquis peut s'empresser de télécharger la nouvelle application immédiatement et cela en toute confiance car hébergée sur un site contrôlé par Apple.

Ce type de comportement ne pourrait pas être aussi important (une demi-douzaine de téléchargement par personne en moyenne) sans le sentiment de confiance qu'inspire l'AppStore : c'est le coup de génie d'Apple. Il s'agit d'une véritable révolution du comportement des utilisateurs même si j'en convient son utilité me parait limité.

Au delà de cet aspect ludique, le choix d'un lot d'applications doit également constituer une certaine affirmation identitaire du possesseur de l'iPhone : le choix d'un journal n'est pas neutre par exemple. On retrouve un équivalent moderne des bibliothèques familiales qui permet d'afficher à travers le choix des livres disposés bien en vue sur les étagères un statut social. Il en est des applications comme pour les livres : ce n'est pas parce qu'elle est présente sur un iPhone qu'elle est utilisée.

Conclusion

L'AppStore est un élément révolutionnaire de l'offre iPhone par les changements de comportements qu'il a provoqué. Ce changement n'a été possible que parce que les utilisateurs se sont sentis en confiance grâce à l 'existence d'une place de marché sous le contrôle du constructeur.

Ce qui est également révolutionnaire, c'est l'attention et l'importance que porte Apple à son écosystème : de nombreux analystes ont expliqué la défaite du MacOs sur Windows par le peu d'attention qu'Apple avaient porter aux développeurs alors que ceux-ci ont toujours été choyé par Microsoft. La leçon semble avoir bien été retenue par Steve Jobs et le milliers de nouvelle API attendue avec le firmware 3.0 de l'iPhone ne devrait pas démentir ce revirement.


DiggIt! Enregistrer sur Del.icio.us

mercredi, février 25, 2009

Initialisation d'une propriété de type Date ou Enum avec Spring

0 commentaires
DiggIt! Enregistrer sur Del.icio.us

Le framework Spring permet de construire des objets par configuration. Les objets sont créés et peuvent être initialisés.

Cela marche bien et simplement pour des types simples String ou int par exemple quand il s'agit d'Enum c'est simple mais il faut savoir quand il s'agit de date c'est bien plus difficile.

Je me propose d'expliquer rapidement comment faire pour ces deux cas.

Le cas des Enum dans Spring

L'exemple fonctionne pour la version 2.5.6 de Spring avec un JDK 1.5. Je pense que la version 2.0 ou 2.5 ont apporté des simplifications que j'utilise dans cette exemple.

Pour une propriété simple d'un bean. Si cette propriété est de type RoleStatAppel qui est une énumération qui prend les valeurs : RoleStatAppel.ECOUTANT ou RoleStatAppel.ADMINISTRATEUR. Pour définir, la valeur de cette propriété roleUtilisateur, il suffit d'ajouter dans la définition du Bean :

<property name="roleUtilisateur" value="ECOUTANT" />

Spring prend tout en charge, il connaît le type de la propriété et il est capable de faire la correspondance avec la valeur indiquée dans value.

La même règle est applicable pour un objet créé avec des arguments dans son constructeur :

Le code initial est :

new NsGUIFactory(NsGUIFactory.NsImplementationMode.GuiEcho2);

  • NsGUIFactory est un singleton que l'on souhaite créé
  • GuiEcho2 est une valeur de l'énumération NsImplementationMode qui est prise en paramètre du constructeur.

La solution pour créer cet objet via Spring est tout simplement :

<bean id="FactoryBean" class="fr.natsystem.natjet.application.NsGUIFactory">
  <constructor-arg><value>GuiEcho2</value></constructor-arg>
</bean>

Pour information, dans le dernier exemple, il s'agissait dans mon cas d'une énumération définie dans la classe NsGUIFactory.

Le cas des Date dans Spring

Pour les dates, le problème est un peu plus compliqué :

  • Spring n'est pas capable de convertir automatiquement une valeur 01/02/2009 dans une propriété de type Date
  • il existe un format. C'est d'ailleurs pour cette raison que Spring n'est pas capable de faire la conversion tout seul.
  • il peut être intéressant de récupérer la date du jour sans avoir besoin de modifier son fichier de configuration.

Pour résoudre le problème des valeurs de types complexes pour lesquelles la conversion d'une String simple n'est pas immédiate ou ambiguë, Spring met à disposition ce qu'il appelle une bean factory post-processor qui permet de compléter les mécanismes standards pour ces types.

C'est cette solution que nous allons étudier pour traiter le cas des dates. La factory Spring CustomEditorConfigurer va être paramétrée grace à une interface dans le fichier de configuration Spring applicationContext.xml.

<bean id="customEditorConfigurer"
    class="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name="customEditors">
        <map>
            <entry key="java.util.Date">
            <bean class="org.springframework.beans.propertyeditors.CustomDateEditor">
                <constructor-arg index="0">
                    <bean class="java.text.SimpleDateFormat">
                        <constructor-arg><value>dd/MM/yyyy</value></constructor-arg>
                    </bean>
                </constructor-arg>
                <constructor-arg index="1"><value>true</value></constructor-arg>
            </bean>
            </entry>
        </map>
    </property>
</bean>

Le tag map permet de lister, si nécessaire, plusieurs conversion pour différents types. Il s'agit une liste de Entry.

  • Le entry possède une clé : key qui indique le type Java qui sera concerné par la conversion : dans notre cas, c'est le type java.util.Date. cela veut dire que dès que Spring rencontre une propriété de type Date, il appellera automatiquement notre PropertyEditor.
  • Le PropertyEditor pour ce type est défini dans le tag bean en indiquant la classe utilisée. Spring met à disposition une classe pour les Date. Cet objet prend deux arguments en entrée, un SimpleDateFormat qui permet de définir le format à utiliser pour la conversion et un second argument qui prend la valeur true. je ne sais pas à quoi correspond cette avleur (il s'agit peut être de la propriété lenient qui permet de forcer ou non une erreur sur une date invalide)

On choisit le format que l'on souhaite utilisé dans <constructor-arg><value>dd/MM/yyyy</value></constructor-arg>.

Je rappelle que mm en java fait référence aux minutes alors que MM fait référence aux mois.

Une fois cette déclaration ajoutée dans le fichier applicationContext.xml, il suffit de définir la valeur comme cela :

<property name="dateArrivee" value="22/02/2009" />

Maintenant si je souhaite utiliser automatqiuement la valeur du jour, il est possible de définir un bean dateJour de la façon suivante :

<bean id="dateJour" class="java.util.Date" scope="prototype"/>

Puis d'utiliser cet objet comme valeur de la propriété, ce qui donne dans notre cas :

<property name="dateArrivee">
     <ref bean="dateJour" /> 
</property>


DiggIt! Enregistrer sur Del.icio.us

lundi, février 23, 2009

Microsoft TechDays 2009

0 commentaires
DiggIt! Enregistrer sur Del.icio.us

Du 10 au 12 février, se tenait au palais des Congrès de Paris, la troisième édition des  Microsoft Techdays.
Vous pouvez consulter mes comptes rendus des versions précédentes :

Cette année nous avons eu droit à moins de superlatif pour qualifier les TechDays : les années passées il s'agissait de l'événement Microsoft le plus important dans le monde. Cette année on parlait d'événement le plus important pour l'Europe.

Le format

Il n'a pas changé, je reprends en grande partie mes commentaires de l'année dernière : Il s'agit d'une série de conférences sur 3 jours, ouvertes chaque jour par une conférence plénières.

Chaque plénière possède son propre thème qui donne une connotation aux sessions de la journée :

  • 1ère : le Développement
  • 2nde : IT
  • 3ème : R&D

Les sessions

Les conférences ou sessions durent chacune une heure. Plusieurs ont lieu en parallèle : il y avait une vingtaine de salles plus trois amphi (le nombre de sessions est constant par rapport à  l'année dernière). Il n'est donc absolument pas envisageable d'assister à toutes les conférences. Mais celles-ci sont enregistrées et devrait être disponibles en webcast sur le site Microsoft.

Lors de l'inscription en ligne (gratuite), il était possible de s'inscrire aux différents sessions. Ces inscriptions ne donnent aucune garantie d'avoir une place. Les places sont servies aux premiers arrivés. On note une nette amélioration par rapport aux années précédentes : l'attribution des salles semble avoir pris en compte les pré-inscriptions, on a pu constaté qu'afin de faire face aux 3000 pré-inscriptions à la présentation de Windows 7, celle-ci a été programmée deux fois par jours en grand amphi. Cette année je n'ai pas eu l'impression qu'il y ait eu des gens refoulés à l'entrée, et je n'ai assisté qu'à une seule session dans laquelle il y a eu quelques personnes debout. 

Chaque conférence dure une heure. Le niveau technique des intervenants est très élevé. Le discours n'est pas pollué par le marketing : c'est de la technique brute. De toute manière, l'auditoire est également très technique et ne laisserait pas passer le moindre déviation marketting.
Une heure c'est court pour faire une présentation technique d'un produit : chaque présentation est donc accès sur un aspect technique d'un produit. Il ne faut pas s'attendre à une formation sur cet aspect du produit : en revanche il est tout a fait possible de savoir ce que le produit est capable de faire, ses limites et le travail à fournir pour l'utiliser.
Pour moi, cette possibilité de bien comprendre à la fois l'adaptation d'un produit à un besoin et les efforts nécessaires à leur mise en oeuvre font des techdays un événement extrêmement intéressant.
Au vu du succès persistant des séances (y compris encore lors du troisième jour), j'en déduis que cet avis était partagé par le grand nombre.

Cette année les séances de questions/réponses à la fin des sessions ont quasiment disparu : la salle se vide rapidement à la fin de l'exposé, et ne reste que quelques irréductibles.

Les stands

Il y a avait un grand espace stands (sur un seul niveau). Les stands partenaires étaient moins nombreux cette année. J'ai pu constater le bon niveau des interlocuteurs sur les stands.

J'ai l'impression que l'espace qui permettait de manipuler les différents produits a disparu.

Affluence

C'est sans aucun doute un succès indéniable de Microsoft : un monde impressionnant et des sessions pleines. Le second jour, Microsoft annonçait 6000 participants à la séance plénière initiale (à comparer au 5400 de l'année précédente et aux 4500 de la première édition). De fait l'amphi a été les 3 jours plein.

L'organisation étant en nette amélioration et Microsoft tirant profit des deux premières années a mieux calibré les salles et les sessions. L'impression de fouillis et de trop grande affluence a complètement disparu.

Thèmes

Les thèmes couverts sont très nombreux : cela va de la production à la méthodologie.  On va des produits de développement jusqu'aux produits d'exploitation. Il m'a semblé cette année, il n'y avait pas de sessions de R&D

La variété est grande et une session n'aborde qu'un aspect du produit. Un produit est généralement couvert par une série de plusieurs sessions.

Les produits en vogue cette année :

  • Windows 7 et Internet Explorer 8.
  • WPF et Silverlight
  • Windows Azure : l'OS pour le Cloud Computing de Microsoft

Ces trois produits ont retenu mon attention car ils apparaissent quasi systématiquement dans chaque session. Bien sur, on parle de Visual Studio, SharePoint, Biztalk... mais ces trois premiers produits semblent être omniprésents.

WPF et Silverlight

Le choix d'une techno pour développer une interface utilisateur parait un grand challenge avec Microsoft. On dispose de pas moins de 4 solutions différents :

  • WindowsForm
  • WPF et sa déclinaison WPF Browser Application
  • ASP.net avec ou sans Ajax
  • Silverlight

Dans tous les cas, il faudra probablement utiliser Visual Studio (qui aurait 60% de part de marché) pour le développement des règles de gestion. On peut être amené à utiliser des solutions de la gamme Expression si on souhaite faire ses propres contrôles ou faire des animations. Ma compréhension est que pour un développement d'une application de gestion standard Visual Studio suffit quelle que soit la solution.

Les critères influant le choix sont :

  • Le contrôle de l' environnement client : accès aux ressources du poste
  • Le besoin du mode déconnecté et la possibilité d'une synchronisation
  • Le degré d'interactivité
  • Le besoin d'utiliser des animations et des transformations
  • L'expérience des équipes de développement
  • Les contraintes de déploiement : type de poste et possibilité d'installation en local

Le critère le plus discriminant est le besoin de déploiement :

  • Asp.Net peut être déployé sur tout poste possédant un navigateur web. Le développement est susceptible de tourner dans un mobile.
  • Silverlight : il nécessite l'installation d'un plug-in dans le navigateur (sa taille est de 4 à 5 Mo). Un plug-in existe pour IE, Firefox et Safari. Il tourne sur Windows et MacOs. Un portage est en cours pour Linux. A priori un développement SilverLight ne tournera pas sur un iPhone ou un Blackberry. Le portage sous Windows Mobile est en cours de route.
  • WindowsForm : Il faut déployer l'application et se limiter aux postes windows
  • WPF : il faut également déployer l'application ainsi que le framework .Net
  • WPF Browser Application tourne dans un navigateur web mais nécessite l'installation du framework .Net en local. Cela exclu donc la plateforme MacOs.

De mon point de vu, si vous n'avez pas besoin d'accéder aux ressources locales du poste (fichier ou autres applications par exemple) j'opterai pour une solution web.

Silverlight permet d'avoir des animations très puissantes, de faire du temps réel mais le temps de chargement d'une application m'a paru long. Je ne suis pas sur que cette solution soit viable à travers un réseau bas débit (genre Edge). Silverlight depuis la v2, semble plus mature : il possède plus de contrôles.

ASP.Net enrichi par Ajax permet de construire une application HTML Javascript avec du fenétrage et du drag & drop. Je suis surpris de voir que pour ASP.Net on découvre l'intérêt du MVC.

Dans le cas contraire, la solution que pousse actuellement Microsoft est WPF (les WindowsForm ne sont plus censées évoluer). Malheureusement la solution semble manquer de maturité même s'il y a eu une grosse amélioration depuis la sortie de Visual Studio 2008 SP1. Par exemple, il manque le DataGrid et le DatePicker même s'ils sont disponibles sur CodePlex.

WPF nécessite le framework 3.0 de .NET. Il repose sur DirectX et permet un affichage vectoriel. C'est cette solution qui permet de construire des présentations à base de carrousel.

Travaillant principalement sous Java, le pattern MVC est pour moi un acquis, j'ai donc été fort surpris de voir plusieurs sessions insister sur ce pattern pour les développements ASP.Net ou Silverlight.

Silverlight avancée

Il s'agit d'une série de trucs pour la programmation avancée de Silverlight. Ces aspects sont liés à une approche MVC et la volonté de conserver un historique et du deeplinking (possibilité d'accéder directement à une page par son url).

On a deux services ASPX :

  • une page qui contient l'application Silverlight. Cette page contient un code Javascript et le code HTML. Le code Javascript cache le code HTML.
  • un service REST qui renvoie les données à l'application Silverlight

La correspondance entre les noms des urls permet de passer de l'un à l'autre sans difficulté.

Un autre élément est le framework Unity qui permet de faire de l'injection de dépendances. Son mécanisme associé à la notion de Weak Event permet de faire du bootstrapping et donc du chargement de modules à la demande. Il est également possible de remplacer un service ce qui permet de faire des tests unitaires.

Cette solution ressemble beaucoup dans les objectifs au framework J2EE Spring. Néanmoins l'approche de Unity est moins configurable que celle de Spring. Avec Unity tout se passe par programmation, là où Spring fonctionne par fichier de configuration.

Internet Explorer 8

L'élément le plus important de IE 8 pour un développeur est son nouveau moteur de rendu : le parsing et le rendu ont été modifié afin de respecter les standards et l'amélioration de la rapidité.

Cette évolution qui permet à IE 8 de passer le test ACID2 casse la compatibilité des nombreux sites conçues pour IE 6. Un mode de compatibilité a été prévu il est activable à plusieurs niveaux :

  • Il est possible d'activer le mode compatibilité en cliquant sur un bouton au bout de l'url. Cela rétablit le rendu du moteur IE 6.
  • Il est possible d'ajouter un tag X-UA-compatible dans la page afin d'indiquer à IE 8 d'utiliser le moteur de rendu d'IE 6.
  • Il est possible d'ajouter le tag pour toutes les pages du site en modifiant le web.config de IIS. Cette opération est également possible dans Apache.
  • Microsoft maintient une liste des sites non compatibles, il est possible d'indiquer au navigateur d'utiliser cette liste et de compléter cette liste.

IE 8 rejoint l'approche de Google Chrome avec l'isolation des onglets dans des processus distincts.

  • il est possible d'avoir une authentification séparée pas onglet
  • le crash d'un onglet n'a pas d'impact sur les autres onglets

Autre nouveauté de IE 8 pour les développeurs : une toolbar de profiling et déboggage.

Cette toolbar reprend la MS Dev Toolbar de IE 7.0 mais est cette fois directement intégrée dans IE 8. Elle ajoute des fonctionnalités de profiling et déboggage.

Pour les utilisateurs IE 8.0 introduit deux nouvelles fonctionnalités :

  • WebSlice : permet de définir comme favori un morceau de page. Le navigateur traite le WebSlice comme un flux RSS en allant vérifier la présence d'une mise à jour.
  • Accelerator : permet de déclencher des actions sur une sélection comme afficher une adresse sur une carte. Cette fonctionnalité permet d'éviter le copier/coller.

Ces fonctionnalités ne peuvent apparaître que si le site met à disposition le service des utilisateurs, ce service nécessitant du développement :

  • WebSlice : il faut modifier la page HTML en ajoutant l'attribut Class HSLICE. Il existe deux autres attributs de class qui vont permettre la définition du titre et du contenu. L'activation pourra être réalisé en modifiant un attribut de class en ajoutant les nouveaux attributs ou en ajoutant de nouveaux tags class.
  • Accelerator : il faut définir le service dans un fichier xml Open Service. Ce fichier disponible au niveau du navigateur permet l'apparition du menu sur le clic droit et indique au navigateur le service qu'il va devoir appeler avec la sélection.

Ces deux services ont donc tous les deux la particularité de nécessiter des développement spécifiques qui ne pourront être utilisés que par des utilisateurs de IE 8.0

Windows 7

C'est le thème qui a connu le plus fort engouement : 6 sessions en grand amphi.

Pour Microsoft les 3 thèmes principaux de cette nouvelle version qu'ils appellent Windows Sept (le marketing a frappé) sont :

  • Expérience utilisateur
  • Sécurité et le contrôle
  • Gestion des postes de travail

Coté expérience utilisateur, Microsoft est parti de la constatation que 75% des utilisateurs avaient 5 à 9 fenêtres ouvertes en même temps. La refonte de la barre des taches doit permettre de résoudre cette problématique tout comme la possibilité de docker une fenêtre sur un coté de l'écran.

Honnêtement ces deux fonctionnalités doivent pouvoir amener des gains de productivité intéressant dans l'utilisation de windows.

Autre élément pour l'expérience utilisateur, la recherche "unifiée" avec la Desktop Search de Vista. La présentation de cette fonctionnalité ne m'a pas paru d'une grande clarté et je n'ai pas très bien compris son principe au delà de la soupe marketing.

Pour finir le coté expérience utilisateur, Windows 7 est tactile sans programmation. J'ai pu jouer sur le stand Dell avec le Latitude XT2 (un tablet PC tactile présenté sous Windows 7) : c'est très agréable et efficace : la réactivité est bonne et on retrouve des sensations proches de l'iPhone.

Néanmoins, au delà de l'aspect tactile, l'interface n'a pas été pensé pour cela : les menus et boutons continuent d'avoir leur bonne vieille taille adaptée à une souris mais pas du tout en accord avec un doigt. Microsoft gagnerait à lire les conseils d'Apple pour le développement d'application iPhone : la taille d'un doigt étant globalement connu, cela amène un certain nombre de contraintes immédiates qu'énumère le document Apple.

Peut-être faut-il prévoir au niveau de Windows une modification de l'interface dès qu'elle perçoit qu'on est passé en mode tactile.

Pour le moment, je pense que pour un tablet PC comme le altitude XT2 de Dell, l'aspect tactile de Windows 7 est quelque chose de génial : on peut le prendre chez soi comme un livre et parcourir le web du doigt (l'iPhone se montre redoutablement efficace dans cette tâche). Pour d'autres utilisations comme la prise de note, le bon vieux stylets (également disponible sur le XT2) reste supérieur.

 

Pour la gestion du poste de travail, on notera tout d'abord une meilleure gestion de l'énergie qui permet un accroissement de 15% de l'autonomie. Les personnes de Dell, semblait très surprise (agréablement) de l'autonomie du XT2. Windows 7 réalise cette prouesse en désactivant les services inutiles.

il faut noter que Windows 7 tourne sur un netbook et que le démarrage semblait rapide : certe il s'agit d'une machine de démonstration avec 1 Go de RAM. on sait que les temps de démarrage des différents Windows se dégradent au fur et à mesure des installations et de son utilisation. Donc le test de démarrage ne peut pas être considéré comme significatif en dehors du fait que Windows 7 tourne sur un Netbook.

Pour les déploiements, Microsoft indique que les mêmes outils de déploiement et d'administration qui marchent avec Vista (pas avec XP) fonctionneront avec Seven. Microsoft compte également sur 3  autres solutions (qui m'ont paru nécessiter un petit supplément financier) pour faciliter la phase de transition et de déploiement :

  • App-V : Les applications sont virtualisées et déployer en central. L'application tourne sur le poste Windows 7 normalement.
  • MED-V on ouvre une machine virtuelle pour lancer l'application. Cette machine virtuelle peut être de type XP. Cette solution permet de réduire les problèmes de compatibilité entre une application et le système d'exploitation. L'utilisateur ne se rend compte de rien : il ne passe par sur un bureau XP. Il voit son application comme tout autre application Windows 7.
  • VDI (Virtual Desktop Infrastructure) : Le PC est juste un terminal graphique comme avec Citrix.

Pour la sécurité, Windows 7 amène 4 nouveautés :

  • Amélioration de User account control : mais je n'ai pas vu quelles améliorations
  • Bitlocker : il permet d'encrypter le contenu d'une clé USB
  • AppLocker : élimine les applications interdites en permettant la définition d'une liste d'applications autorisées ou interdites. Il est possible de se limiter à une version ou de l'étendre à toutes les application d'un éditeur
  • IE 8 permet d'autoriser un activex a un site

Du coté de la mobilité

J'ai assisté à deux présentations sur le sujet toutes les deux fort décevantes. Microsoft est très en retard sur Apple (c'est l'utilisateur d'iPhone qui parle).

Une des présentations essayait de montrer différentes applications pour Mobile toute de pale clone de version existante sur l'iPhone.

Le plus gros reproche que l'on peut faire à Microsoft est de ne pas comprendre les enjeux du tactiles : certes toutes les applications et terminaux étaient tactiles et cela semble être une direction irrémédiable du monde mobile, mais leur interface est inadaptée : un pouce à une certaine taille et il faut accepter de faire tout les boutons d'une certaine taille, tout comme les menus et les listes clicables. C'est la règle. On a l'impression que Blackberry et Palm ont fait évoluer leur OS afin de prendre cela en considération (il suffit somme toute de copier Apple) mais Microsoft reste à la traîne obligeant les constructeur à rhabiller l'OS afin de le rendre utilisable.

Windows Azure et le cloud computing

Il s'agit d'un des sujets phare de ces TechDays et l'affluence était au rendez-vous.

Le Cloud Computing c'est globalement faire héberger ses applications dans un gros datacenter chez un fournisseur d'infrastructure. Cela diffère de l'hébergement classique par l'accent qui est mis sur la virtuallisation : il ne s'agit pas d'espace partagé ou d'une machine physique dédiée mais d'un environnement virtuel. On voit la boucle de la virtualisation se fermer avec l'intéret majeur que représente la virtuallisation pour le cloud computing.

Le Cloud Computing est marketé en mettant l'accent sur le on-demand cher à IBM : je ne sais pas de quelle puissance je vais avoir besoin ou si j'ai besoin d'une forte puissance ponctuelle, le cloud computing est la solution adaptée car l'allocation est dynamique et l'on paye à la consommation.

Le Cloud computing rejoint pour Microsoft leur slogan Software + Service qui reste pour moi une vaste fumisterie du Marketing Microsoft : vous pouvez tout faire, où plutôt tout nous acheter : acheter de bon vieux logiciel comme Windows, Word, SharePoint ou bien nous acheter des services comme Azure mais également Microsoft Live ou Microsoft Live Office dans laquelle on retrouvera SharePoint en service. N'ayez pas peur Monsieur le client, tout est légitime et stratégique.

En langage marketing S+S c'est mélanger les différentes approches : se faire héberger et payer un service dans certain cas (offre Windows Live pour les particuliers et Office Live pour les entreprises) et acheter ses propres logiciels dans d'autres cas.

Un point récurrent des présentations d'Azure, c'est l'importance que Microsoft accorde et met en avant sur son savoir faire en gestion de très grosses infrastructures :

  • 240 milliard de messages MS Messenger envoyés par mois
  • 10 milliard de page MSM consultés par mois
  • 10 000 serveurs ajoutés par mois à son infrastructure

On apprend que Microsoft prévoit l'ouverture de 3 nouveaux datacenter (500 M$ chacun d'investissement) et que Microsoft est maintenant capable de construire en 3 mois un DataCenter, là ou il y a deux ans il leur fallait 18 mois.

Microsoft veut être perçu comme un acteur majeur de l'hébergement avec en ligne de mire Google et Amazon. Pour ceux qui ne le savent pas, Amazon avec son offre Amazon ec2 est probablement le premier arrivé dans ce domaine du Cloud Computing.

Le Cloud Computing est un secteur à gros investissement (un datacenter de l'ordre de 500 M$) qui nécessite un savoir faire dans l'administration et la gestion de ce type d'infrastructure.

Windows Azure est une offre en construction : ce que l'on peut dire c'est qu'il s'agit de service car c'est Microsoft qui héberge vos applications. Microsoft prend à sa charge les coûts d'exploitation et d'administration. L'approche est de permettre grâce à la virtuallisation des gains d'échelle sur l'exploitation grâce à un meilleur savoir faire notamment en gestion de l'énergie.

Le service comprend à la fois l'hébergement physique mais également ce qui conviendrait d'appeler un "système d'exploitation virtuel" : c'est probablement ce qu'il convient d'appeler Azure. Au dessus de ce système d'exploitation, il y a une série de services techniques (comme le stockage de données) qui s'appelle Azure Services Platform.

Contrairement à de l'hébergement dédié où l'on doit gérer sa plate-forme et ses mises à jour, là tout est compris mais il n'est pas possible d'espérer rester sur une version antérieur : on retrouve le principe de la beta permanente du Web 2.0. Il faudra donc bien gérer ses différentes interfaces.

Aujourd'hui Azure est en beta, il est possible de demander un jeton qui donne droit à un projet et 50 Go de stockage. Attention, il faut des jetons pour chaque service comme l'identification ou le stockage.

Nous allons maintenant nous concentrer sur Azure l'OS pour le cloud et le développement d'application.

Un projet correspond à une machine virtuelle dont la création a été pris en charge par Microsoft : vous disposez de deux environnement : production et pré-production avec pour ce dernier une url temporaire.

La programmation est pour l'heure exclusivement en .Net : il existe des templates de projet dans Visual Studio qui sont dédié à Azure. Microsoft fait miroiter l'ouverture dans le futur au développement PHP, Ruby ou même Java. Il est vrai qu'un hébergeur se doit d'être "ouvert" et beaucoup d'intervenants (je ne parle pas que de Azure) ont pris soin de montrer que certaines solutions Microsft s'interfacer parfaitement avec d'autres technologies. Il sera peut-être même possible d'héberger grâce à la virtuallisation des applications en code non-managé.

Néanmoins aujourd'hui pour développer pour Azure, se sera avec Visual Studio en .Net sous Vista. XP n'est pas et ne sera pas supporté : il est possible de tester le développement en local mais cela nécessite IIS 7 qui ne tourne pas sous XP.

Les API de Azure sont orientées Cloud computing on retrouve notamment les services suivants :

  • Stockage : même si cela repose sur une version de SQL server, il ne s'agit pas de SQL. On retrouve des tables et des blobs.
  • Identification : on utilise la connexion Windows Live. Il travaille actuellement sur le support de la norme OpenId
  • Communication par messages avec des services de queue
  • Des services pour le déploiement avec la production et préproduction
  • Des services d'administrations avec notamment un service de log. Les logs sont stockées comme un BLOB qu'il est ensuite facile de récupérer pour analyse.
  • Data Sync : un service pour utilisateur occasionnel
  • Workflow qui assure le support de scénario
  • ESB qui est une sorte de bus dans le cloud.

Tous les services sont accessibles à travers un service REST (il est donc possible de les appeler depuis du Java) y compris le service de stockage.

La programmation doit tenir compte d'un premier aspect primordial : on doit travailler en mode medium trust (le mode de mutualisation des applications web). Il faudra ensuite faire très attention à la Retry Policies : c'est le comportement d'une application quand un utilisateur plus ou moins patient clique plusieurs fois sur un même bouton. Ce point est très important en Web et donc sur le cloud.

Azure distingue 2 rôles :

  • Rôles web aspx : création d'une interface web
  • Rôle worker .cs batch : création d'un traitement

L'offre Azure semble être quelque chose de très intéressant : on sent toute la puissance et la cohérence des investissements de Microsoft. Il s'agit probablement pour Microsoft d'un enjeux majeur voir de l'enjeux majeur et identifier comme tel.

La Programmation fonctionnelle

La programmation fonctionnelle est un des axes de réflexion de la R&D de Microsoft. Sa déclinaison "commerciale" est le langage F#.

Les langages classiques sont des langages impératifs : on donne des ordres explicites à la machine. On programme la machine : on lui dit ce qu'elle doit faire et dans quel ordre. Cette approche nécessite de déclarer les variables. Cette approche est difficilement parallelisable : on pilote la machine étape par étape.

La programmation fonctionnelle se veut déclarative : le compilateur ou la machine virtuelle pourra plus facilement optimiser la parallelisation des traitements. Je pense que l'importance que revêt pour Microsoft cette approche repose principalement sur cette possibilité de parallélisation accrue : pour Microsoft, il n'est plus possible de pousser le cadencement des processeurs, il faut s'orienter vers des approches multi-coeur ou multi-processeurs : dans ces deux cas, la parallélisation est importante pour profiter pleinement des nouvelles architectures. C'est pour cette raison que la programmation focntionnelle a besoin de définir de l'asynchronisme et des points de rencontre/synchronisation.

Microsoft semble considérer linq (solution de mapping objet/relationnel proche de hibernate et de jpa) comme une approche de type déclarative alors que le SQL repose sur une approche impérative.

Le F# est loin de me paraître plus compréhensible que le C# (sachant que je ne connais ni l'un ni l'autre et qu'ils sont très proche en terme de syntaxe). De mon point de vu, le F# est un projet de long haleine pour Microsoft qui n'a pas réellement d'utilité immédiate aujourd'hui.

La présentation a mis l'accent sur la possibilité et les intérêts de ne pas typer en F# : le var du C# (solution qui permet de ne pas définir le type d'une variable en lui disant de prendre le type du coté gauche de l'expression).

Le typage en F# permet une approche générique qui permet de travailler avec un type inconnu qui est résolu plus tard dans le code ou ailleurs. Attention ! le type est connu par l'éditeur, l'intellisense fonctionne !

Dans cette perspective de typage, le Let doit être vu comme un binding permettant de résoudre un typage et non pas comme une affectation simple.

Conclusion

les Techdays ont été comme les années précédentes à la hauteur de mes attentes. Microsoft a su améliorer son organisation rendant moins sensible la grande affluence de cet événement.

Les deux axes futures à moyen terme qui m'ont paru intéressant sont : Silverlight et Azure. La programmation fonctionnelle est quelque chose qui reste pour moi très lointain et Windows 7 est du présent.


DiggIt! Enregistrer sur Del.icio.us

samedi, novembre 22, 2008

StreetView de l'iPhone 2.2

0 commentaires
DiggIt! Enregistrer sur Del.icio.us

La dernière mise à jour (au 22/11/2008) du firmware de l'iPhone inclus une évolution majeure du logiciel de cartographie Google Map : Plans.

La fonctionnalité StreetView de Google a été ajouté. Cette fonctionnalité est réellement surprenante et permet de visualiser la rue, un rond point comme si on y était.

L'utilisation de StreetView n'est pas des plus intuitives c'est pourquoi je vous propose un rapide tutorial illustré.

La première étape est d'ouvrir l'application Plan. On se place sur le lieux qui nous intéresse : disons par exemple la place de l'Etoile à Paris

S1GooglePlan

StreetView est accessible depuis le mode Plan ou le mode Satellite (c'est au choix). Pour l'activer, il faut placer un repère. Pour cela, il faut que le lieux visé soit si possible au centre de l'écran. On appuie sur l'image en bas à droite de la page qui se soulève.

S2PlacerRepere

On appuie sur Replacer le repère et on obtient :

s3Repere

Notez, le petit icône orange à gauche de Faite glisser le repère. Si vous attendez quelques secondes, le nom du lieu apparaît sous Faite glisser le repère.

Si vous appuyez sur l'icone Orange vous basculer en mode StreetView (j'imagine que le petit bonhomme blanc symbolise le piéton qui se promène pour nous dans les rues de Paris).

S4StreetView

Le mode StreetView nécessite de tenir l'iPhone en mode paysage. Le petit cercle en bas à droite indique notre position sur le plan. La zone plus clair indique notre angle de vue.

Vous pouvez utiliser votre doigt pour faire tourner la vue et découvrir l'arc de Triomphe :

S5ArcTriomphe

Par moment quand vous tourner vous voyez apparaître une ligne au sol avec des flèches.

S6NomRue

Ceux sont les axes que vous pouvez parcourir avec StreetView : vous allez pouvoir avancer en le suivant. Il y a également le nom de la rue qui est inscrit : cela nécessite de regarder vers le bas : Utilisez pour cela votre doigt (un mouvement du haut vers le bas).

S7NomRue

Pour avancer, appuyer sur la flèche que vous voyez au loin. Attention, on avance doucement et il faut patienter un petit peu entre chaque coup.

S8Wagram

Si vous voulez avancer plus vite n'attendez pas que l'image s'affiche et appuyez de nouveau sur la flèche. Vous pouvez appuyer plusieurs fois d'affilées et progresser ainsi plus rapidement. Le petit cercle est mise à jour, vous pouvez ainsi surveiller votre progression.

Pour sortir du mode StreetView il suffit d'appuyer sur le cercle. On revient à la vue du Plan.

Et voila, on a fait un tour de la fonctionnalité StreetView du firmware 2.2 de l'iPhone.


DiggIt! Enregistrer sur Del.icio.us

vendredi, août 29, 2008

Comment desimlocker légalement son iPhone v1 ?

0 commentaires
DiggIt! Enregistrer sur Del.icio.us

Un grand nombre d'iPhone v1 ont été acheté il y a plus de 6 mois. Si c'est votre cas vous pouvez le déverrouiller en toute légalité. Une fois déverrouillé vous pourrez utiliser votre iPhone avec une autre carte SIM d'un autre opérateur.

La procédure est relativement simple :

  1. elle commence par un appel au service client d'Orange : le 700 depuis votre mobile ou 3970 depuis une ligne fixe. Tapez le 9 pour parler à un conseiller.
  2. Le conseiller va vous demander le numéro de la ligne et le code IMEI de l'iPhone. Il est accessible dans Réglage -> Générale -> Informations et IMEI ou tout simplement au dos de votre iPhone.
  3. Après vérification que cela fait bien plus de 6 mois que l'iPhone est en votre possession, il demande un email. C'est à cet email qu'Apple enverra la procédure pour déverrouiller l'iPhone
  4. Quelques jours après cet appel (1 jour dans mon cas) vous recevrez un email décrivant la procédure.

Avant de suivre la procédure, il est souhaitable de faire une synchronisation avec votre PC. Il peut être utile au préalable de vous assurer d'avoir installé la dernière version du Firmware de l'iPhone. Je ne l'avais pas fait et la procédure a différé de celle décrite dans l'email et je n'ai pu éviter l'installation de la 2.0.2.

La procédure de synchronisation consiste :

  1. Connecter son PC à Internet. Cela est fondamentale car je pense que iTunes va vérifier sur un site d'Apple qu'il peut bien desimlocker voter iPhone.
  2. Il faut brancher son iPhone au PC.
  3. Il faut appuyer sur le bouton Restaurer
  4. Si comme moi la version de l'iPhone est ancienne, il affiche le message ci-dessous, vous n'avez que le choix d'opter pour une Restauration et mise à jour. Il va installer la nouvelle version.


A la fin du processus, il indique que la SIM est Locked. Il faut la déverrouiller en tapant votre code.

A la fin du processus, vous devriez voir apparaître le message suivant :

Vous n'aurez que le choix de continuer, il propose de reconfigurer votre iPhone :

Pour ma part, j'ai choisi l'option Restaurer à partir de la sauvegarde.

Après quelques minutes, votre iPhone est enfin déverrouillé.

Maintenant si vous éteignez votre iPhone vous pouvez changer de carte SIM et mettre celle d'un autre opérateur. Vous pouvez le rallumer, vous pouvez utiliser pour appeler, votre carnet d'adresse et votre calendrier son toujours présent. En fait seul le réseau a changé.

Vous pouvez synchroniser et mettre à jour votre iPhone avec iTunes sans problème.

En conclusion, la procédure est simple même si elle peut être un peu longue. J'ai été fort surpris de la bonne volonté du conseiller Orange. Il suffit juste de demander.

Attention ! La procédure peut laisser penser qu'on peut déverrouiller son iPhone en faisant un Restaurer. Ce n'est pas le cas, la procédure, doit vérifier dans une base de données qu'il est possible de le déverrouiller.

Dans la série iPhone, vous pouvez consulter ces autres billets :



DiggIt! Enregistrer sur Del.icio.us