Revue de presse

Voici une liste des liens qui nous ont intéressés récemment :

Le domain driven design « Vite fait » : 80 pages pour changer votre vie. Ou plutôt changer votre façon d’écrire vos modèles métiers.

Cours sur la concurrence : Une piqure de rappel ne fait pas (de) mal.

Développer avec Comet et Java : Vous rêver d’envoyer des informations au navigateur en mode « push » ? Voici la solution.

Algodeal: Pour tous ceux qui aime inventer des algos, voici une occasion de faire fortune en s’amusant (et en java)  !

Les castcodeurs : Episode spécial « Freelance » avec Mathilde ! A écouter absolument si vous souhaitez vous mettre indépendant !

Problème de concurrence avec SimpleDateFormat

La classe DateUtil utilisée dans mon projet possède de nombreuse méthodes, certaines permettent de créer des identifiants basés sur les dates ensuite insérés en base de données. L’objet simpleDateFormat qui permet le parsage de ces dates est définit comme étant « public static final ».

Dans la plupart des cas, pas de problème, la date est bien parsée et l’identifiant est crée conformément à ce que l’on attends. Néanmoins, dans de rares cas, il est possible que cela se passe beaucoup moins bien. En effet, la classe SimpleDateFormat n’est pas synchronisée. Si 2 threads essaient en même temps d’utiliser cette instance pour un parsage ou un formatage, le résultat est aléatoire.

La classe DateUtil a été simplifiée à l’extrême.

Read more »

Un vent de reprise v2.0

Cet article est en partie une reprise d’un article que j’ai publié fin 2009 lorsque la fin de la crise pointait le bout de son nez dans notre secteur.

Depuis le début de la crise économique mondiale, certains clients finaux ont diminué le nombre de prestataires et ont imposé des baisses de tarif importantes. Résultat : plus de prestataires et moins de mission, loi de l’offre et la demande oblige, les prix ont chuté d’environ 10%.

Pour ceux qui ont la chance d’être resté en mission ou qui n’ont pas vu leur tarif baisser, ce n’était pas le moment de changer. Et pour ceux qui ont subit, le risque est aujourd’hui de continuer à subir alors que le marché a repris. Alors comment avoir une vue globale sur le marché de la prestation Java en France ?

Personnellement j’utilise le baromètre du site hitechpros.com. Apprendre à décrypter ce baromètre permet de se faire une idée des tendances du marché.

Comment décrypter ces données ?

La courbe bleue correspond aux offres de missions (demandes des clients), ramenée à 100% elle sert de base. La courbe rouge correspond aux prestataires disponibles (offres de SSII). Donc plus la courbe rouge baisse, mieux c’est. Pour le mois de Mars, on y est, le nombre de prestataires disponibles est inférieur au nombre de missions ! Champagne !

Voici mon analyse en Mars 2010 :

- La crise est belle est bien terminée, cela fait plusieurs mois qu’on le pressentait avec le nombre d’offres de missions qui explose sur les différents sites d’emplois.
- Cette crise inversée ne va pas durer, les SSII vont se remettre à recruter en masse et le nombre de prestataire va remonter au dessus des offres de missions.
- Toutefois, le marché devrait rester en notre faveur jusqu’à la prochaine crise et les tarifs devraient augmenter fortement.

Mon conseil si vous n’êtes toujours pas freelance :  foncez ! Le temps de démissionner les tarifs seront sur un nouveau « plus haut ». Si vous l’êtes déjà, c’est le moment de changer de mission si vous attendiez une accalmie. Sinon, attendez un peu que cette pénurie atteigne le client avant de demander une revalorisation importante de votre tarif.

Ce qu’était mon analyse fin 2009 :

- Actuellement le nombre d’intercontrat baisse fortement et les clients commencent à avoir du mal à trouver des ressources. Les indépendants trouvent facilement des missions mais mal payées.

- Si la tendance se confirme, les SSII vont recommencer à recruter afin de répondre aux exigences des clients, les débutants et chômeurs vont réussir à trouver du travail mais moins bien payé qu’avant 2007, car les tarifs n’auront pas encore remontés.

- Lorsque le vivier d’inter-contrats et de jeunes diplômés sera absorbé, les prix commenceront à remonter et les salaires feront de même. Il sera temps pour les indépendants de profiter de cette dynamique avant la prochaine crise.

Pour conclure, n’oubliez pas que le meilleur moyen de rester employable, crise ou pas crise est de se former ! En mission comme à la maison ou en dehors. Ainsi que de bien choisir ses missions ! Pas forcément chercher une « niche rentable » mais faire quelquechose qui nous passionne est le meilleur moyen d’y exceller.

Et vous comment vivez vous ou avez vous vécu cette crise ? Quelle est votre stratégie pour les mois à venir ?

EasyMock – Techniques avancées

Easymock est un framework de test offrant une API permettant de tester plus facilement le code. Cet article ne constitue pas une présentation d’easymock et s’adresse aux développeurs souhaitant progresser sur l’utilisation de cette API.

Lorsque l’on met en place les mocks, il est fréquent que l’on ait besoin de tester qu’un objet créé à l’intérieur de la méthode testée correspond bien à ce que l’on attend, cet objet étant passé en tant que paramètre à une méthode d’un objet mocké.

Prenons pour exemple, la classe Service et sa méthode processRequest. La méthode processRequest prend en entrée deux paramètres et se sert de ces paramètres pour créer un objet Bond, qui sera passé ensuite à la méthode persist du service BondDao.

package fr.java.freelance.easymock;

import java.math.BigDecimal;

public class Service {
	private BondDao bondDao;

	public String processRequest(String name,BigDecimal quantity) {
		Bond bond = new Bond(name,quantity);
		return bondDao.persist(bond);
	}

	public void setBondDao(BondDao bondDao) {
		this.bondDao = bondDao;
	}
}

package fr.java.freelance.easymock;

public interface BondDao {
	String persist(Bond bond);
}

package fr.java.freelance.easymock;

import java.math.BigDecimal;

public class Bond {
	private String name;
	private BigDecimal quantity;

	public Bond(String name, BigDecimal quantity) {
		super();
		this.name = name;
		this.quantity = quantity;
	}
	public String getName() {
		return name;
	}
	public BigDecimal getQuantity() {
		return quantity;
	}
}

Il est a priori impossible pour un test unitaire d’accèder à l’objet « bond » pour le vérifier.

Ce que l’on cherche à garantir, c’est que la méthode processRequest construit un objet de type Bond ayant comme attributs name et quantity les 2 valeurs passées en paramètres, qu’elle le transmette à la méthode persist de ServiceDao et retourne le paramètre de retour de cette méthode persist.

Utilisation d’EasyMock.anyObject()

La première méthode pour tester ceci est d’utiliser la méthode anyObject de l’objet EasyMock.

Service service = new Service();
BondDao bondDaoMock = EasyMock.createMock(BondDao.class);
service.setBondDao(bondDaoMock);

final String persist_return = "123AX";
final String name = "Name 5%";
final BigDecimal quantity = BigDecimal.TEN;

EasyMock.expect(bondDaoMock.persist((Bond) EasyMock.anyObject()))
.andReturn(persist_return);

EasyMock.replay(bondDaoMock);
String idInternal = service.processRequest(name, quantity);
Assert.assertEquals(persist_return,idInternal);
EasyMock.verify(bondDaoMock);

Le test fonctionne, néanmoins rien ne garantit que l’objet que l’on transmet à la méthode persist de BondDao est conforme à ce que l’on attend.

Pour pouvoir analyser l’objet Bond transmis, il existe plusieurs possibilités, dont une utilisant la redéfinition de la méthode equals de l’objet Bond et deux fournies par la librairie EasyMock, l’utilisation d’un IArgumentMatcher ou de EasyMock.capture.

Rédéfinition de la méthode equals()

Supposons que l’objet bond redéfinisse la méthode equals de manière à tester l’égalité des paramètres name et quantity.

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Bond other = (Bond) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (quantity == null) {
			if (other.quantity != null)
				return false;
		} else if (quantity.compareTo(other.quantity)!=0)
			return false;
		return true;
	}

Il suffit alors d’écrire le test suivant pour garantir que l’objet passé à la méthode persist est bien égal au bond attendu :

        @Test
	public void testProcessRequestWithEquals() {
		Service service = new Service();
		BondDao bondDaoMock = EasyMock.createMock(BondDao.class);
		service.setBondDao(bondDaoMock);

		final String persist_return = "123AX";
		final String name = "Name 5%";
		final BigDecimal quantity = BigDecimal.TEN;
		final Bond bondExpected = new Bond(name,quantity);

		EasyMock.expect(bondDaoMock.persist(bondExpected))
				.andReturn(persist_return);
		EasyMock.replay(bondDaoMock);
  	        String idInternal = service.processRequest(name, quantity);
		Assert.assertEquals(persist_return,idInternal);
		EasyMock.verify(bondDaoMock);
	}

Cette démarche est la plus naturelle, néanmoins elle ne s’applique pas dans le cas où la méthode equals n’est n’ai pas redéfinie (dans ce cas, c’est la méthode equals de Object qui est prise en compte et donc, les deux objets ne seraient pas égaux (pas la même instance)). Elle ne s’applique pas non plus dans le cas où la méthode equals ne correspondrait pas à ce que l’on a définit comme étant utile pour tester l’égalité. Par exemple une méthode equals qui ne testerait que l’égalité de l’attribut name dans l’objet Bond alors que nous souhaitons garantir les valeurs des deux paramètres. On ne peut évidement pas modifier la méthode equals d’un objet pour le tester, cela changerai son comportement !!
Il faut donc se tourner vers d’autres solutions.

Utilisation d’un IArgumentMatcher

EasyMock permet d’utiliser un certain nombre de matcher déjà définit ( eq, isNull, matches ..). Néanmoins dans le cas présent, il nous faut définir notre propre matcher pour pouvoir tester l’égalité des paramètres name et quantity.
La redéfinition d’un matcher s’effectue en deux temps.
D’abord, il faut créer une classe implémentant IArgumentMatcher.

package fr.java.freelance.easymock;

import org.easymock.EasyMock;
import org.easymock.IArgumentMatcher;

public class BondEquals implements IArgumentMatcher {
	private final Bond expected;

	public BondEquals(Bond expected) {
		this.expected = expected;
	}

	public boolean matches(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (expected.getClass() != obj.getClass())
			return false;
		Bond other = (Bond) obj;
		if (this.expected.getName() == null) {
			if (other.getName() != null)
				return false;
		} else if (!this.expected.getName().equals(other.getName()))
			return false;
		if (this.expected.getQuantity() == null) {
			if (other.getQuantity() != null)
				return false;
		} else if (this.expected.getQuantity().compareTo(other.getQuantity()) != 0)
			return false;
		return true;
	}

	public void appendTo(StringBuffer buffer) {
		buffer.append("eqException ").append(expected.toString());
	}

	public static Bond eqBond(Bond in) {
	    EasyMock.reportMatcher(new BondEquals(in));
	    return null;
	}
}

Pour pouvoir utiliser le BondEquals ainsi crée, la méthode persist de l’interface BondDao n’acceptant que les objets de type Bond, on utilise l’astuce suivante :

public static Bond eqBond(Bond in) {
	    EasyMock.reportMatcher(new BondEquals(in));
	    return null;
	}

On peut alors utiliser le test suivant, pour garantir d’une part le bon retour de la méthode processRequest ainsi que le passage du bond ayant les caractéristiques souhaitées à la méthode persist du BondDao.

        @Test
	public void testProcessRequestWithArgumentMatcher() {
		Service service = new Service();
		BondDao bondDaoMock = EasyMock.createMock(BondDao.class);
		service.setBondDao(bondDaoMock);

		final String persist_return = "123AX";
		final String name = "Name 5%";
		final BigDecimal quantity = BigDecimal.TEN;

		final Bond bondExpected = new Bond(name,quantity);
		EasyMock.expect(bondDaoMock.persist(BondEquals.eqBond(bondExpected)))
				.andReturn(persist_return);
		EasyMock.replay(bondDaoMock);
		String idInternal = service.processRequest(name, quantity);
		Assert.assertEquals(persist_return,idInternal);
		EasyMock.verify(bondDaoMock);
	}

Utilisation de org.easymock.Capture

Une autre méthode consiste à capturer l’objet bond passé à la méthode persist du DAO et de faire des tests dessus dans un deuxième temps.
Une capture s’effectue en 3 temps.
1. Déclaration de la capture : Capture capture = new Capture();
2. Capture du paramètre lors de l’exécution via : EasyMock.expect(bondDaoMock.persist(EasyMock.and(EasyMock.isA(Bond.class), EasyMock.capture(capture))))
3. Récupération de l’objet capturé : Bond captured = capture.getValue();

	@Test
	public void testProcessRequestWithCapture() {
		Service service = new Service();
		BondDao bondDaoMock = EasyMock.createMock(BondDao.class);
		service.setBondDao(bondDaoMock);

		final String persist_return = "123AX";
		final String name = "Name 5%";
		final BigDecimal quantity = BigDecimal.TEN;

               Capture capture = new Capture();

		EasyMock.expect(bondDaoMock.persist(EasyMock.and(EasyMock
                          .isA(Bond.class), EasyMock.capture(capture))))
                .andReturn(persist_return);

		EasyMock.replay(bondDaoMock);
		String idInternal = service.processRequest(name, quantity);
		Assert.assertEquals(persist_return,idInternal);

		Bond captured = capture.getValue();
		Assert.assertEquals(name,captured.getName());
		Assert.assertTrue(quantity.compareTo(captured.getQuantity())==0);
		EasyMock.verify(bondDaoMock);
	}

Il existe également d’autres méthodes utilisant des outils externes pour atteindre un but similaire mais je n’ai pas encore trouvé de limitation à la création d’un nouveau matcher ou la capture de l’élément à tester. Si il y a besoin plusieurs fois de tester l’objet de manière identique, j’ai tendance à créer un nouveau matcher et à utiliser la capture dans le cadre d’objets plus petits ou de besoin spécifique à un test.

Création du groupe DuchessFr

duchessfrUn nouveau groupe autour de Java se lance en France ! DuchessFr est un groupe destiné à mettre en relation et à promouvoir les femmes dans le monde du développement Java. Originaire des Pays Bas, JDuchess s’étend petit à petit avec des antennes en France et au Brésil.



Les actions menées en France seront de plusieurs types :
- La création d’un réseau virtuel, via twitter, linkedin, une mailing list …
- Inciter les femmes à participer à des évènements locaux, comme les soirées JUG ou les autres conférences.
- Se rencontrer pour échanger, avant ou après les soirées JUGs, autour d’un apéro ou d’un repas.
- Lister les différents évènements en France pour ne pas les rater et éventuellement trouver quelqu’un avec qui y aller.

Pour se tenir informer des évènements de ce groupe, vous pouvez nous rejoindre sur twitter @duchessfr , sur LinkedIn ou via notre mailing list.

Le premier évènement aura lieu le 9 mars à 18h30 , juste avant le paris JUG au Vavin Café (18 rue Vavin 75006 Paris). Lorsque vous serez inscrites au JUG, contactez ellene(dot)dijoux(at)jduchess(dot)org qui vous accueillera Mardi prochain.