4
fév
Posted in Java by Mathilde |
Au cours de mes revues de code, je tombe sur des problèmes plus ou moins réguliers. Outre les problèmes de designs, certains aspects techniques sont récurrents.
Comparaison avec == sur des java.lang.Integer
Le problème, c’est que sur des integers entre -128 et 127, cela peut marcher. Dans la suite de l’exemple, integer1 et integer2 seront de type java.lang.Integer, int1 sera de type primitif int.
Integer integer1 = 127;
Integer integer2 = 127;
System.out.println(integer1 == integer2); // true
integer1 = 128;
integer2 = 128;
System.out.println(integer1 == integer2); // false
Par contre, on a bien pour toutes les valeurs, y compris celles entre -128 et 127 :
integer1 = new Integer(127);
integer2 = new Integer(127);
System.out.println(integer1 == integer2); // false - normal on a instancié 2 objects différents
integer1 = new Integer(129);
int1 = 129;
System.out.println(integer1 == integer2); // true
Si on regarde la doc de Sun, pour tous les objets entre -128 et 127, l’autoboxing garantit que l’objet renvoyé Integer sera identique pour un même entier primitif. Ce qui ne sera pas le cas au delà de l’intervalle. De plus, rien ne garantit qu’une implémentation étende l’intervalle de cache, raison pour laquelle il est risqué de se baser dessus.
Byte, Short, Long ont également le même type de cache. Character a également un cache mais de 0 à 127 (un nombre négatif n’aurait pas eu de sens).
d. Autoboxing is guaranteed to return the same object for integral
values in the range [-128, 127], but an implementation may, at its
discretion, cache values outside of that range. It would be bad style
http://java.sun.com/developer/JDCTechTips/2005/tt0405.html#1
Ainsi, utiliser == en se fiant à l’autoboxing et au cache est une mauvaise pratique, même pour comparer des constantes de faible valeur.
Utiliser plutôt valueOf() plutôt que new
Il est préferable d’utiliser un valueOf plutôt qu’une nouvelle instanciation à l’aide du constructeur. Valable pour la certains objets immutables.
Exemple avec des types java.lang.Integer, si on regarde la javadoc pour la méthode Integer.valueOf(int i) :
public static Integer valueOf(int i)
- Returns a Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor
Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values.
-
Idem pour les Byte, Long, Character, BigInteger … Par contre, préférer quand c’est possible de construire les valeurs accessibles directement via une méthode statique (BigInteger.ONE plutôt que BigInteger.valueOf(1), Boolean.FALSE plutôt que Boolean.valueOf(false) …)
Éviter d’utiliser new String
String test1 = "abc";
String test2 = "abc";
String test3 = new String("abc");
String test4 = new String("abc");
System.out.println(test1 == test2); // true
System.out.println(test1 == test3); //false
System.out.println(test3 == test4); //false
Utiliser new String implique de créer un nouvel object en mémoire. Les String étant immutables, avoir 2 objets différents ayant la même valeur ne fait que consommer de la mémoire. Attention à bien noter le cas 2, “abc” est différent de new String(”abc”). Cet exemple permet également de montrer l’importance d’utiliser la méthode equals pour comparer les valeurs des objets java.lang.String .
Comme précisé par Jérôme et Nicolas Le Coz en commentaire, l’instanciation d’un nouvel objet String est conseillée lors de l’utilisation de substring sur des très grandes chaînes de caractères. En effet, la valeur stockée avec un substring n’est pas uniquement la substring, mais la chaîne entière avec un offset (premier caractère à utiliser) et un compteur (nombre de caractères à utiliser).
C’est clair si l’on regarde la classe java.lang.String
public final class String
implements java.io.Serializable, Comparable, CharSequence
{
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
[...]
public String substring(int beginIndex, int endIndex) {
[...]
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
Plus d’infos ici http://blog.xebia.fr/2009/08/03/revue-de-presse-xebia-120/#AttentionvotremmoireavecString et dans les autres liens en commentaires.
Se méfier de la construction des BigDecimal.
On utilise ici 3 manières de faire pour créer un BigDecimal que l’on souhaite égal à 4.12. Néanmoins, les résultats ne sont pas conformes à ce qu’on pourrait en attendre.
Double myDouble = 4.12D;
BigDecimal bd1 = new BigDecimal(myDouble);
BigDecimal bd2 = new BigDecimal(String.valueOf(myDouble));
BigDecimal bd3 = BigDecimal.valueOf(myDouble);
System.out.println(bd1.equals(bd2)); // false !
System.out.println(bd1.equals(bd3)); // false !
System.out.println(bd2.equals(bd3)); // true
Il n’y a donc pas égalité de valeur entre l’object construit à partir du double et les 2 autres objets. En effet, si on affiche les différentes valeurs des 3 BigDecimal, le problème est facilement visible :
RESULT 1: 4.12000000000000010658141036401502788066864013671875
RESULT 2: 4.12
RESULT 3: 4.12
Il vaut mieux donc éviter d’utiliser le constructeur BigDecimal(double double) et de lui préférer les deux autres méthodes.
public BigDecimal(double val)
- Translates a
double into a BigDecimal which is the exact decimal representation of the double’s binary floating-point value. The scale of the returned BigDecimal is the smallest value such that (10scale × val) is an integer.Notes:
- The results of this constructor can be somewhat unpredictable. One might assume that writing
new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
- The
String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one.
- When a
double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method.
26
jan
Posted in Formation by Mathilde |
Il n’y a pas à dire, Février est un mois chargé vu l’ensemble des conférences et rencontres qui nous sont proposées gratuitement autour de Java et du Web.
MAJ : la date de l’évènement Clojure a été avancée au 8 février !
Ajout événement noSQL 17 février
Le KawaCampParis1 - 3 février - Décalé en mars
Les BarCamp sont des rencontres, non formelles sous forme d’ateliers-événements participatifs ou simplement de discussions libres autour d’un thème. Chacun arrive avec son propre contenu. Comme lors des JavaCamps les participants finissaient la plupart du temps par parler d’autres choses que Java, l’idée d’un KawaCamp, plus large, a germé
Les sujets seront donc nombreux, de NoSQL à Groovy en passant par les technos Google, sans oublier HTML5, les frameworks Javascript etc ..
Site web : http://barcamp.org/KawaCampParis1
Wave publique : with:public KawaCampParis1
Clojure : Vers l’essence de la programmation - 8 février
Clojure est un langage fonctionnel apparu en 2007 de type Lisp et tournant sur la JVM. Howard Lewis Ship , créateur de Tapestry, présentera le langage, ses atouts ainsi que les concepts fondamentaux de la programmation fonctionnelle.
Site web : http://www.zenika.com/conference/web_ria/clojure-essence-de-programmation-par-howard-lewis-ship
2ème Anniversaire du Paris Jug - 9 février
Le Paris JUG fête ses deux ans en grand ! Un amphi de 500 places nous accueillera entre 18h45 et 19h (donc 30 minutes plus tôt que d’habitude) sur le sujet de l’open-source en France. Au moins 6 présentations sur des thèmes variés :
- Keynote de Sacha Labourey
- Obeo : exemple d’un éditeur d’outils de développements Open Source ayant réussi à se développer
- Les licences permettant la diffusion libre de la documentation
- Le framework Play!
- jCaptcha
- jax-doclet , permettant de génèrer de la JavaDoc à partir des des commentaires JavaDoc et des annotations de manières spécifiques (notamment pour JAX-RS et JAXB)
Et toujours suivi d’une 3ème mi-temps pour des discussions plus informelles mais tout aussi intéressantes !
Comme au mois de Décembre, la salle est à la faculté de la Sorbonne : http://www.parisjug.org/xwiki/bin/view/Location/SorbonneParisIV
Site web : http://www.parisjug.org/xwiki/bin/view/Meeting/20100209
Les secrets de la concurrence Java - 11 février
Heinz Kabuts est un des premiers Java Champion. Il publie régulièrement une newsletter très pointue sur Java et la JVM sur http://www.javaspecialists.eu/ suivie par approximativement 30 000 développeurs Java. Il abordera au cours de cette soirée 10 lois pour nous apprendre à mieux gérer le multi-threading.
Site web : http://www.zenika.com/conference/java/secret-de-la-concurrence-java-par-heinz-kabutz
Domain Driven Design : Les modèles en action - 17 février
Eric Evans est de retour à Paris. Auteur de Domain-Driven Design, il présentera les différents modèles (comment les choisir, les faire cohabiter …). Cette conférence s’adresse plutôt aux développeurs expérimentés.
Site web : http://www.zenika.com/conference/architecture/domain-driven-design-par-Eric-Evans
Deuxième rencontre noSQL - 16 février
Les sujets de cette deuxième conférence sont “noSQL for Fun and Profit” et Redis.
Site web : http://sites.google.com/a/octo.com/nosql/project-updates/usergroupparis-round2
Création du Spring User Group - 25 février
La première conférence du Spring User Group balayera les différentes nouveautés de la version 3.0 de Spring par Arnaud Cogoluègnes. La migration vers Spring 3.0, les nouveautés (Spring Expression Language, Support Rest) ainsi que le rapport avec Java EE seront abordés.
Site web : http://groups.google.fr/group/sugfr/web/evnements
Src image : Iulian Nistea
3
jan
Posted in Java by Jean Baptiste |
Je suis tombé amoureux de Scala. Et je suis fier de vous présenter mes premières lignes de code en Scala :
import java.io._
class Reader(dir: String) {
// Concatène les contenus de n fichiers dans une liste
def readAll() = {
// Mets toutes les lignes d'un fichier dans une liste
def readLines (name : String) = {
// Mets toutes les lignes d'un bufferedReader dans une liste
def read(buf : BufferedReader, acc : List[String] ) : List[String] = buf.readLine match {
case null => acc
case s => read(buf, s::acc) // Appel recursif optimisé par Scala
}
// Compose le nom complet du fichier et appel read
read(new BufferedReader(new FileReader(dir + "/" + name)), Nil).reverse
}
// Applique readLine sur tous les fichiers et renvoi la concaténation des listes
// Pas de return : En scala c'est la derniere expression qui fait office de retour
new File(dir).list.flatMap(readLines)
}
}
13 lignes de code, pour lire tous les fichiers d’un répertoire puis concaténer l’ensemble des lignes dans une liste chaîné.
Une compatibilité à 100% avec Java
Ce qui n’est pas une surprise, car Scala est compilé en ByteCode.
Cela se traduit par la possibilité d’importer n’importe quelle classe pourvu qu’elle soit dans le classpath :
import java.io._
Et d’appeler des méthodes Java dans le code Scala :
buf.readLine
new BufferedReader(new FileReader(dir + "/" + name))
Et même d’utiliser très simplement un framework comme JUnit :
import org.junit.Test
class ReaderTest() {
@Test
def unTest() : Unit = {
val read = new Reader("src/test/resources/cotations")
read.readAll().map((x) =>println(x));
}
}
Oui je sais, ce test n’est pas un test, c’est juste un exemple
Chaque méthode que j’ai écrite ne fait qu’un seul traitement. Cela les rends faciles à comprendre, à maintenir et à tester. La programmation fonctionnelle n’étant pas “impérative”, il est de toute façon très difficile d’écrire une méthode sur 1000 lignes alors qu’il est malheureusement très fréquent d’en trouver dans du code Java…
Pas de boucle
En programmation fonctionnelle il est tout à fait possible, et même conseillé de ne pas utiliser de boucle. La façon de penser et de concevoir son programme n’est plus la même. C’est je pense, la principale raison qui rend les langages fonctionnel “obscurs” pour un développeur impératif.
En programmation impérative, on pense “enchaînements d’instructions”, c’est un peu comme écrire une recette de cuisine : faire ci, puis ça, puis ça.
En programmation fonctionnelle on s’attache au “comment”. Comment transformer tel fichier en liste et tel liste en table de base de données. C’est le principe d’une fonction : transformer une entrée en “autre chose”. Les éléments impératifs, comme les boucles ne sont utiles que dans un langage impératif (encore que..).
On utilisera plutôt la récursion :
def read(buf : BufferedReader, acc : List[String] ) : List[String] = buf.readLine match {
case null => acc
case s => read(buf, s::acc) // Appel recursif optimisé par Scala
}
// Compose le nom complet du fichier et appel read
read(new BufferedReader(new FileReader(dir + "/" + name)), Nil).reverse
Notez qu’il ne se produira pas de StackOverflowError car ce code récursif est traduit par une boucle. Oui ne riez pas, c’est vrai. Un code récursif identique en java produira un beau StackOverflowError lorsque les fichiers dépasseront un certain nombre de lignes.
Scala a quand même une petite faiblesse, il n’optimisera que si l’appel récursif est direct. Une pile {read, read, read, read, read} sera optimisée alors qu’une pile {read2, read1, read2, read1} ne le sera pas. Ce qui nous empêche d’écrire ce code qui aurait été plus élégant :
def read(buf : BufferedReader) : List[String] = buf.readLine match {
case null => Nil
case s => s::read(buf) // Appel recursif
}
// Compose le nom complet du fichier et appel read
read(new BufferedReader(new FileReader(dir + "/" + name)))
La stack ici est {read, ::, read, ::, read, ..} “::” est la fonction d’ajout d’élément à une liste en Scala !
En fait, Java nous interdit carrément d’utiliser la récursion sur une trop grande profondeur, ce qui est clairement une énorme lacune du compilateur Java, qui pourrait très bien optimiser les fonctions récursives pour éviter les stackOverflow. Scala à une longueur d’avance sur ce point. Ceci dit je pense que cela donnera des idées pour Java7.
Cette traduction en Java ne sera pas optimisée malgré une pile d’appel optimisable :
private List readLines(final BufferedReader buf, final List acc) {
String line;
try {
line = buf.readLine();
if (line != null) {
acc.add(line);
return readLines(buf, acc);
}
} catch (IOException e) {
e.printStackTrace();
}
return acc;
}
Voici une autre façon de ne pas utiliser de boucle :
// flatMap est une méthode native.
new File(dir).list.flatMap(readLines)
Ici on créé un objet java.io.File, on appel la fonction list() puis on appel la fonction readLines sur chacun des fichiers.
La méthode “map” applique la méthode readLines à tous éléments de la liste et retourne cette nouvelle liste. On effectue donc bien un mapping d’une liste de valeurs vers une nouvelle liste de valeurs : List<FileName> => List<ContenuDuFichierFileName>. Le tout, sans boucle !
La méthode flatMap() diffère de la méthode map() car au lieu de renvoyer une List<List<String>> (ReadLines renvoie une List<String>, elle va “aplanir” (ou concaténer) les listes, ce qui donnera une simple List<String> contenant toutes les lignes de tous les fichiers situés dans le répertoire “dir”.
Alors en vérité, et je pense que c’est une lacune du langage Scala, il existe un mot clé “for” qui permet d’écrire certaine ligne de mon code d’une autre manière faisant grandement penser à une boucle “for” Java… mais sans l’être.. bref, je conseil d’éviter cette écriture, Scala étant déjà assez difficile à appréhender pour un programmeur impératif, inutile d’ajouter de la confusion en codant un truc ressemblant à de l’impératif..
Et pas de variable
Scala encourage l’utilisation d’objet immutable. C’est à dire avec un état fixe, sans setters par exemple. Je vous renvoie à la lecture de l’excellent livre “Effective Java” pour en savoir plus sur les avantages de l’immutabilité en Java, et donc a fortiori en Scala. Et bien entendu il beaucoup plus simple de faire de l’immutable en Scala qu’en Java !
Scala permet de différencier très clairement les valeurs des variables via les mots clé “val” et “var”. “val s : MyObject ” est l’équivalent de “final MyObject o;” alors que “var s : MyObject ” sera l’équivalent de “MyObject o;” En Scala les paramètres des fonctions sont des “val”. Un objet immutable sera forcément une valeur.
Il est donc tout à fait possible et même conseillé de ne jamais utiliser de variables. En fait, lorsqu’on aura besoin d’un objet avec état changeant on utilisera le pattern “Actor”, dont Scala fourni le support et qui permet d’avoir des objets mutables “sans risques”.
Développer avec le Bloc-notes : Facile !
Le gros défaut de Scala, c’est qu’il n’existe pas d’IDE aussi avancé que pour Java. Ceci dit, je n’ai pas du tout souffert de ce manque. J’utilise le plugin eclipse fourni sur le site officiel, qui permet l’auto complétion et rajoute de la couleur et honnêtement, ça suffit largement. C’est à se demander si une grosse partie de l’outillage nécessaire en Java n’était finalement pas lié aux lacunes de Java !
Pour comparer voici les 2 codes Java et Scala mis côte à côte. J’ai essayé de réduire au maximum le code Java ! On remarquera qu’en Java, j’ai été obligé d’avoir une variable non final.
import java.io.*;
import java.util.*;
public class Reader {
private final String directory;
public Reader(final String dir) {
this.directory = dir;
}
public final List<String> readAll() {
final String[] fileNames = new File(directory).list();
final List<String> ret = new LinkedList<String>();
for (String name : fileNames) {
try {
BufferedReader buf = new BufferedReader(new FileReader(directory + "/" + name));
String line = buf.readLine();
while (line != null) {
ret.add(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return ret;
}
}
No comment :
import java.io._
class Reader(dir: String) {
def readAll() = {
def readLines (name : String) = {
def read(buf : BufferedReader, acc : List[String] ) : List[String] = buf.readLine match {
case null => acc
case s => read(buf, s::acc)
}
read(new BufferedReader(new FileReader(dir + "/" + name)), Nil).reverse
}
new File(dir).list.flatMap(readLines)
}
}
Réactiver votre cerveau
Apprendre un nouveau langage, c’est apprendre à penser autrement, cela bouscule nos neurones et comment dire : Ça fait du bien !
Scala offre beaucoup d’autres choses intéressantes, comme les traits, les actors, sa gestion native du XML, son framework web “Lift”, Comet etc. J’espère avoir le temps d’approfondir tout ça et d’en faire quelques articles.
Plus généralement, la programmation fonctionnelle offre d’énormes avantages, rendant obsolète bon nombre de patterns et de framework qui n’existent finalement que parce que, Java et les langages impératifs en général ont de nombreuses imperfections.
Source : http://www.scala-lang.org/
24
déc
Posted in Gestion by Jean Baptiste |
C’est malheureux, mais j’ai discuté récemment avec un indépendant qui m’a démontré par A+B qu’entre le statut de TNS et celui de salarié, il pouvait ne pas y avoir de différence en terme de taux de cotisations obligatoires.
Voici son calcul de charges obligatoires :
TNS RSI (Commerçant / Artisan) : 45,2 %
TNS Prof. Libérale : 33%
Salarié : 22% de cotisations salariales et 30% de charges patronales donc : charges = 50%.
Vu comme ça, et étant donné la différence de prestation entre un salarié et un TNS (indemnités journalières, retraite, chômage..), il est plus souvent avantageux d’être salarié, voir complétement préférable pour un artisan au RSI.
Où est l’erreur ?
Alors pourquoi tout le monde ne se met pas salarié ? Les solutions pour le faire sont pourtant multiples ! L’erreur est simple, les taux sont corrects mais la base de calcul n’est absolument pas la même.
Pour le régime salarié, on applique les taux sur le brut versé alors qu’en TNS on applique le taux sur le net versé.
Petit rappel mathématique : y * taux = x n’est pas égal a x * taux = y.
D’un coté on a brut * (1-taux) = net
de l’autre coté on a : net * (1 + taux) = brut (<=> net = brut * (1/(1+taux)) )
Jusqu’à preuve du contraire 1/(1+taux) n’est pas égal a (1-taux). On compare donc des choux et des carottes.
Pour être plus clair, voici un tableau comparatif avec des exemples facile à comprendre :

Attention, les taux ne sont qu’un ordre de grandeur, en réalité cela varie un peu en fonction des situations.
La comparaison entre salarié et TNS pour un indépendant en informatique, donc en profession libérale, se fera soit en comparant 81% à 33% de charges sur le net, soit en comparant 45% à 25% de charges sur le brut.
En passant, attention au simulateur que l’on trouve sur http://www.freelance-info.fr, il est faux pour les mêmes raisons. Utilisez plutôt notre simulateur.
26
nov
Posted in Formation, Java by Mathilde |

La troisième journée est assez différente des deux précédentes. Le planning des journées change. Le matin, plus de session de 3 heures mais une Keynote de deux heures suivie par une conférence d’une heure.
Après un rappel de quelques chiffres (2500+participants, 56 jugs …), Stephan Janssen, l’organisateur de Devoxx nous présente la prochaine version de parleys.com . Parleys.com permet de voir de chez soi l’ensemble des conférences de devoxx mais également d’autres évènements, comme par exemple certaines présentations des différents JUG. Le service est également proposé aux entreprises pour héberger leurs vidéos. Outre cette nouvelle version, les présentations de devoxx 2009 sont déjà arrivées en grand nombre, les versions gratuites des conférences seront disponibles au compte goutte tout au long de l’année. Toutes les conférences seront disponibles gratuitement à la fin 2010. A noter qu’il est possible de télécharger les présentations sur son PC très facilement avec ce site et de les revoir à volonté.
Oracle
Le deuxième sujet est une présentation d’Oracle. J’avoue avoir envisagé quelque chose de plus grand, mais l’acquisition de Sun par Oracle n’étant pas finalisé, il n’y aura rien de croustillant de ce côté là. On a le droit à la place d’une démo du moteur de module dynamique de Weblogic.
Sun
La présentation de Sun a été plus intéressante. Outre le fait que la final release sortira le 10 décembre 2009, une belle démo, bien rodée, a pu démontrer la puissance de JEE6. Création d’une Servlet, intéraction avec EJB et ensuite avec un service OSGi. La simplicité de l’ensemble est vraiment à remarquer, aucun plantage lors de la démo. Certaines fonctionnalités de Glassfish V3 notamment le rechargement à chaud … sans perte de session a vraiment eu un impact chez tous ceux qui auront essayés de debugger un problème liée à une session.
Flash Catalyst
La dernière présentation fut celle d’Adobe. Une démonstration de Flash Catalyst et son intégration avec les différents outils Adobe très bien ficelée, avec un vrai show des deux présentateurs. La puissance de Flash Catalyst et son intégration avec la suite Adobe donnent une réelle impression de simplicité, que ce soit pour mapper deux vues, pour modifier un bouton, pour permettre d’envoyer le code vers Flash Builder, qui est plus à destination des développeurs. A voir ce que cela donne dans la réalité.
JDK 7 Update
Place ensuite à JDK7 update. Les plus grandes nouveautés sont le project Jigsaw, qui permet une grande modularité de la jdk, avec la possibilité de n’embarquer que les librairies utiles à notre application. Le project coin qui regroupe quelques évolutions du langage :
L’apparition de l’opérateur diamond qui nous permet d’écrire :
Map<String,String> myMap = new Hashmap<>();
Il sera également plus simple de construire des collections sans avoir des myList.add(…) à la chaine, la solution implémentée aura une syntaxe proche de celle des tableaux. D’autres nouveautés, comme la possibilité de faire un switch sur des String ou l’apparition de closures (simples). Un point à également été clarifié sur la différence entre Java SE et le jdk, le Java SE représentant la spécification, le jdk7 l’implémentation. A noter que bien qu’il y ait un open jdk 7, il n’y a pas de Java SE 7.
Comet
Jean-Francois Arcand présente ensuite le framework Atmosphère qui permet de pousser un message du serveur vers le client.
Il existe trois types de méthodes pour pousser ce message :
- Le Polling
- Le long Polling
- Http Streaming, souvent utilisé dans les jeux mais qui devient compliqué dans certaines situations.
Atmosphère se veut un framework simple, basée essentiellement sur des pojos et disponibles sur de nombreux serveurs (de tomcat à google app engine) et supporte certains frameworks de présentations (GWT/Wicket). La démo, très simple, se déroule bien. Encore une fois, il faut voir ce que cela donne dans la réalité de nos environnements.
Distributed programming the google way
Gregor Hohpes présente ensuite une conférence d’une heure sur “Distributed programming the google way”. Cette conférence se révèle être une des plus intéressantes conférences de Devoxx. Il détaille le fonctionnement de BigTable, de MapReduce, de Sawzall et de Google File System au travers de 8 recommandations :
- Utilisez la fragmentation, ne pas hésiter à partionner les données.
- Rester simple et n’implémentez que les fonctions de base
- S’attendre à l’échec
- Faites des processus autonome, pouvant poursuivre sans supervision
- Le runtime est le plus important. Mieux vaut une circulation fluide à des règles très strictes.
- Préférer la vitesse à la précision. Plus c’est rapide, mieux c’est.
- Privilégier tout ce qui est sans état. Les processes qui conservent un état sont plus couteux que les opérations sans états
- Tout est affaire de compromis
L’importance de ces 8 règles permettent d’avoir une bonne scalabilité. Il n’est souvent pas nécessaire de produire toutes les fonctions possibles pour avoir un outil scalable. Ainsi, les différents outils présentés ont chacun leurs limites : par exemple, Sawzall permet de faire des aggrégations extrêmement rapide mais ne permet pas de faire de traiter la duplication.
Les deux BOFs auquel j’ai assisté de la soirée n’ont pas été interessante du tout. Trop de monde, impossible à entendre.