lundi 27 juin 2011

Code Retreat #1

Ce 24 juin, j'ai assisté à un code retreat, organisé par Jean-Laurent de Morlhon et Simon Caplette, chez Xebia.
Avant de m'inscrire, je n'en connaissais pas le principe. Je me réfère donc à la définition donnée par les organisateurs :
"Le principe est le suivant: sur la journée coder en binôme sur plusieurs sessions de 30-45 minutes chacune afin de résoudre un problème. A l’issue de chaque session on change de binôme et tout le code produit est effacé. Drastique mais efficace pour rester créatif. C’est aussi le lieu privilégié pour tester de nouvelles techniques et algorithmes."
C'est un concept de coding dojo que je n'avais essayé, d'où mon envie de tester.

Le temps que tout le monde soit là et installé, un traditionnel petit déjeuner nous attendait.
Avant de commencer, l'organisation de la journée nous est présenté :
- Le but n'est pas de finir, mais de faire ce que l'on peut
- Par recommmencement on finit par s'améliorer, on cherche à améliorer la façon de faire.
- Une session est composé de 40 min de développement en pair programming et 20 min de débriefing général.
- Ici c'est différent du boulot, on a le temps, inutile de rusher. Nous sommes ici pour apprendre, tester d'autres façons de faire, essayer un autre langage ou un autre ide, découvrir des plugins d'ide, ...
- Procéder par TDD et suivi les principes de YAGNI. Si ce sont des pratiques que l'on ne fait pas au quotidien dans notre travail, c'est justement l'occasion de s'y exercer
- Une session est composé d'une partie de développement de 40 min en pair programming, suivi de 10-15 min de retrospective globale.
- Une retrospective globale en fin de journée

Souvent le jeu de la vie est utilisé en code retreat, ici pour changer ce sera TicTacToe dont les spécification nous sont fournis en 6 règles :
1/ Une partie est finie lorsque tous les champs sont pris.
2/ Une partie est finie lorsque une colonne est prise par un joueur.
3/ Une partie est finie lorsque une ligne est prise par un joueur.
4/ Une partie est finie lorsque une diagonale est prise par un joueur.
5/ Un joueur peut jouer lorsque un champ n'est pas pris.
6/ Les joueurs jouent à tour de role jusqu'à ce que la partie soit finie.

Au total, sur la journée 5 sessions auront lieu.


Session 1


Au bilan de cette première session, certains remonte l'usage de plugins Eclipse :
- Pair Hero : duels en pair programming où chacun code à tour de role jusqu'à ce qu'un test échoue. Des points sont gagnés en fonction de refacto ou rapidité à faire passer le clavier.
- Infinitest : lance les tests unitaire à chaque enregistrement du code, économise ainsi des switch test/code.
Beaucoup prennent les régles dans l'ordre, mais est ce bien utile ?
Quant à l'implémentation, le plateau est codé sous diverse forme : tableau à 2 dimensions, chaine simple, ...


Session 2


Les noms de classes eux aussi sont variés : TicTacToe, Party, Board, ... tout comme les méthodes de fin : checOver, isOver(), ....
Des questions sur le moment où refactorer se posent. Le mieux est quand on veux, quand celà nous semble un moment logique, une étape. Et il ne faut pas oublier que la refacto concerne aussi bien, le code métier que les tests.
Quelques personnes pense qu'ils ont introduit la notion de joueur trop tôt, ils auraient pu refactorer lorsqu'ils en auraients eu besoine.
Profitant de l'occasion de pouvoir refactorer, certains ont changé leur design, parfois avec regret. Mais y trouve tous l'avantage du recommencement, qu'ils ne peuvent pas faire au boulot.


Session 3


Quelques-uns trouvent un avantage dans l'implémentation de chaine de caractère, pour une raison de facilité de recherche interne.
Pour ma part, après 2 sessions tournées sur la détection de fin de partie, cette fois ci, mon code était plutôt orienté vers la le tour par tour des joueurs.
Une problématique courante remonte : placer le jeu dans un état précis pour tester par exemple des configuration de plateau. Une solution possible serait d'avoir une méthode d'initialisation.
Les animateurs remontent qu'ils entendent parler d'architecture, mais qu'il s'agit là d'une notion bien poussée, car la seule voulue, c'est un simple jeu.

Pause repas


Après toutes ces aventures de la matinée, nous avons le droit à un repas geek : pizza/coca !
Pour l'après midi, pour ceux qui souhaitent, on monte le niveau avec des objectifs :
- No Mouse : souris interdite, uniquement clavier.
- 5 min par personne : on alterne le clavier toutes les 5 minutes.
- Tdd as if you meant it : Tdd encore plus poussé avec des régles telle que coder son code métier dans la classe de test.

Session 4


Pour cette session, 2 groupes ont testé un autre langage :
- JavaScript (Mathilde Lemée et Eric Le Merdy) : Utilisation de JQuery, structure de données portée par la page. QUnit ne semble pas super pour tester du js.
- Ioke (David Gageot et moi même) : Je ne connaissais absolument pas ce langage, j'ai donc était volontaire pour le découvrir. C'est un langage entre lisp, ruby et smalltalk qui tourne aussi bien sur une VM java que .Net. Nos tests sont assez très lisible, au contraire du code. En effet, de refacto en refacto et par jeu, nous avons réduit de façon très importante le code en utilisant toute la puissance du langage. Si bien que notre code pour les régles lignes et colonnes tient en 3 lignes.
Ceux qui avaient l'objectif, Tdd as if you meant it sont satisfaits, par le fait d'avoir pu repousser le moment de décider où placer son code.

Session 5


Le groupe JS a poursuivi ce qu'il avait commencé et nous montre leur réalisation. Le js a permit de connecter facilement à une ihm html, la structure de données est directement dans le dom plutôt que dans des objets js.
David a continué en Ioke avec un autre volontaire pour découvrir le langage. De nouvelles refacto ont eu lieu, et le code pour tester les 4 ères régles tiennent sur environ 6 lignes.
Nos animateurs nous montrent un exemple de Tdd as if you meant qu'ils avaient réalisé. Le retardement du choix du placement du code a fait qu'ils ont eu une approche fonctionnelle, où le modèle est sans état.
Et pour finir, ils énumèrent quelques possibilité de challenge possible en code retreat : No loop, No If, ...
Invonlontairement, ces 2 challenges ont été vaincus par David et son code en Ioke.


Debriefing de la journée


Nous finissons la journée sur une rétrospective finale sur ce que nous avons appris et ce qui sera pratiqué au retour au travail. Dans le désordre :
- Découverte du tdd et voir quelle limite dans l'approche du code nécessaire à faire passer le test.
- Le tdd permet de penser plus au fonctionnel.
- Necessité de plus pousser le principe de code minimal afin d'affiner ses tests.
- Réticence à Infinitest vaincu. Pour des tests volumineux, il est paramétrable.
- Un autre langage qui faire penser différement.
- Pair Hero assez plaisant
- Parfois on pense avoir résolu de manière optimale un problème mais après avoir recommencé avec une autre personne, on se rend compte que non.
- Progression dans les tests car parfois quasiment pas de tests dans les projets au boulot.
- Nouvelle vision à chaque fois.
- Du test fait mais pas tdd, ce qui fait un nouvel outil à utiliser.
- Il peut être utile d'avoir une phase de réflexion avant de se lancer dans les tests.
- Des discussions intéressantes.
- Passer plus de temps sur la refacto.




Un autre Code Retreat aura lieu le 2 juillet, avec Oana Juncu de Sfeir comme animatrice.
A l'heure actuelle, il reste quelques places dépéchez si vous être intéressés.

mercredi 22 juin 2011

Bilan Cloud Camp 1 chez Sfeir

C'est le 30 mai dernier qu'a été organisé le 1er Cloud Camp. Plus de 50 personnes étaient présentes au rendez vous.


A l'arrivée, un accueil convivial avec des cacahuètes et boisson attendaient les invités.
La soirée commence avec une présentation de Kohsuke Kawaguchi, sur le build en parallèle avec Jenkins.



Dans la foulée, Steven Noels lui aussi vient aussi nous parler de son bébé : Lily



C'est autour de pizza que nous nous remettons de nos émotions, ce qui est aussi l'occasion de discuter entre différentes personnes présentes.

C'est après, s'être bien rempli l'estomac que la soirée, s'est poursuivies etlLes sessions camp organisées furent :
  • Forplay : le framework de Google pour réaliser des jeux pour des cibles Gwt/Android/Flex/Swing
  • Retour d'expérience sur Appengine
  • Mvp4g
  • Démo de Lilly
  • CloudBees
Le Bilan que je fais de cloud camp est très positif et a plus au participant. Nous avons vu défiler les tweets lors des présentation de nos guest start. Et quelques sujets de blog de participants d'Exilys sur Lily et ForPlay.

D'autres sessions, seront probablement organisée. Nous espérons vous y voir.

jeudi 16 juin 2011

La marmite des Duchess

La 1ère édition de la Marmite des Duchess a eu le 7 juin dernier. Nom de code "Crumble".
Ce nouvel évènement, proposait 2 sessions en parallèle, le choix se faisait à l'inscription :
- Atelier Mockito, animé par Mathilde Lemée et David Gageot. (limité à 20 places)
- Open Space Technologique. (limité à 40 places)
Doit on y voir l'anologie du crumble dans ce découpage ? Je ne saurais répondre à cette question.

Au total, une trentaine de personnes (dont 6 Sfeirien(ne)s) étaient présentes pour une durée d'un peu plus de 2 heures.

Atelier Mockito





C'est la partie à laquelle j'ai assisté.
Cet atelier était basé sur le code de tudu-list. Le but était de, en binome, compléter des tests et de les faire passer au vert. Pour palier au différente connaissance et niveau des participants, ils étaient réparti en 3 niveau de difficulté.
Pour ma part, connaissant un peu Mockito, j'ai fait la partie niveau 2. Nos animateurs étaient bien sûr présent pour nos différentes questions sur la façon de faire/organiser nos test aussi bien sur Mockito mais aussi sur FestAssert.
Ces exercices permettent d'avoir quelques bases sur Mockito en découvrant sa syntaxe et ses particularité et aussi si nous sommes rigoureux avec le formalisme BDD qui est conseillé dans l'écriture des tests mais aussi de

Si vous souhaitez tenter le défi, le code à compléter est ici et la solution .

Open Space Technologie




N'ayant pas de don d'ubiquité, je n'était pas présent à cette partie. Mais heureusement, mon collègue Clément Griffoin avait pris des notes.

Différents sujets ont étés abordés dont :
- Women in java
- ForPlay où Pierre-Yves Ricau fera une démonstration de sa réalisation
- Déploiement continu
- Stubs vs Mock
- TDD/DDD/BDD


Vous pourrez retrouver plus d'information ce qui s'est dit dans cette soirée sur le blog des Duchess.

Et pour finir, c'est un autour d'un repas que les derniers motivés se sont retrouvés.


Félicitations pour ce premier édition ! Et vivement la suite à la rentrée.

Des photos de la soirée sont disponibles

Du protobuf dans mon Jersey

J'avais déjà parlé, dans de précédents articles, de la génération de xml et de json avec Jersey. Et si maintenant, on s'amusait à générer du protobuf ?

On parle de protobuf pour Protocol Buffers, une techno Google pour encoder des structures de données. Ce format de données compact est utilisé en interne chez Google des échanges de données.
Etant basé sur la déclaration d'une structure de données dans un idl, protobuf possède plusieurs implémentation et est ainsi utilisable dans plusieurs langage.
En java, la génération du code cible se fait avec ant. Mais bien sur reste utilisable avec maven par le plugin ant.

Nous allons reprendre notre Hello qui avait d'exemple. Voici sa structure protobuf :

package nfrancois.poc;

option java_package = "nfrancois.poc.protobuf.model";
option java_outer_classname = "HelloProto";

message Hello {
  required string name = 1;
  required string message = 2;
}

La structure se comprend assez facilement. Attention par contre, au trompeur package de 1ère ligne, qui n'est pas lié à la notion de package que nous avons en java. Il sert comme espace de nommage et éviter des collisions de nom si plusieurs objets protobuf portent le même nom. Puisque depuis cette idl, je pourrai aussi bien générer en C++ ou un autre langage, le vrai nom de package java est indiqué par l'option "java_package", de la même façon pour le nom de classe qui va tout encapsuler qui sera "java_outer_classname"

Pour plus d'information sur protobuf, je vous invite à consulter sa page google code.

Le générateur protobuf générera un fichier HelloProto.java, qui permettra de manipuler les Hello : création via pattern builder, encodage/désencodage, ...
Le "vrai" Hello sera encapuslé au sein de ce dernier.
Comme je disais, je génère le java par le ant plugin de maven :


 org.apache.maven.plugins
 maven-antrun-plugin
 1.6
 
  
   generate-sources
   generate-sources
   
    
     
             
             
             
    
   
   
    run
   
       
 

et bien sûr des dépendances protobuf


    com.google.protobuf
    protobuf-java
    2.4.0a


Le contrat de test sera assez proche de se que nous avions dans les tests précédents :

@Test
public void shoulReplyHello(){
 // Given
 String message = "Hello";
 String name ="Nicolas";
 Hello hello = HelloProto.Hello.newBuilder().setName(name).setMessage(message).build();
 when(helloServiceMock.saysHelloToSomeone("Nicolas")).thenReturn(hello);
 // When
 ClientResponse response = resource().path("hello").path(name).get(ClientResponse.class);
 // Then
 verify(helloServiceMock).saysHelloToSomeone(name);
 assertThat(response.getClientResponseStatus()).isEqualTo(Status.OK);
 assertThat(response.getType().toString()).isEqualTo("application/x-protobuf");
 Hello entity = response.getEntity(Hello.class);
 assertThat(entity).isNotNull().isEqualTo(hello);
}

La resource REST, elle aussi va peut évoluer :

@Path("hello")
@Singleton
@Produces("application/x-protobuf")
public class HelloResource {
 
 @Inject
 private HelloService helloService;
 
 @GET
 @Path("/{name}")
 public Hello reply(@PathParam("name") String name){
  return helloService.saysHelloToSomeone(name);
 }
 
 public void setHelloService(HelloService helloService) {
  this.helloService = helloService;
 }
 
}


La difficulté à laquelle il faut se confronter, c'est que Jersey ne permet pas de gérer de base le protobuf… Pas grave, on va s'occuper de faire le lien entre l'encodage/désencodage de protobuf et Jersey.


Commençons par le reader qui s'occupe de désencoder le protobuff. Pour celà, nous devons implémenter l'interface MessageBodyReader où nous aurons du code technique protobuf.

@Provider
@Consumes("application/x-protobuf")
@Singleton
public class ProtobufMessageBodyReader implements MessageBodyReader<Message> {

 public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
  return Message.class.isAssignableFrom(type);
 }

 public Message readFrom(Class<Message> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
  try {
   Method newBuilder = type.getMethod("newBuilder");
   GeneratedMessage.Builder builder = (GeneratedMessage.Builder) newBuilder.invoke(type);
   return builder.mergeFrom(entityStream).build();
  } catch (Exception e) {
   throw new WebApplicationException(e);
  }
 }

}


C'est par le content type "application/x-protobuf" que JAX-RS fera matcher le type le reader/writer à l'entrée/sortie de la resource.
Pour l'encodage, c'est l'interface MessageBodyWriter qu'il faut implémenter.

@Provider
@Produces("application/x-protobuf")
@Singleton
public class ProtobufMessageBodyWriter implements MessageBodyWriter<Message> {
 public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
  return Message.class.isAssignableFrom(type);
 }

 private Map<Object, byte[]> buffer = new WeakHashMap<Object, byte[]>();

 public long getSize(Message m, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  try {
   m.writeTo(baos);
  } catch (IOException e) {
   return -1;
  }
  byte[] bytes = baos.toByteArray();
  buffer.put(m, bytes);
  return bytes.length;
 }

 public void writeTo(Message m, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
  entityStream.write(buffer.remove(m));
 }
}

La configuration de test, quant à elle sera un peu plus complexe, car il faut que la partie cliente puisse désencoder toute seule le protobuf :

protected AppDescriptor configure() {
 ClientConfig clientConfig = new DefaultClientConfig();
 clientConfig.getClasses().add(ProtobufMessageBodyReader.class);
 clientConfig.getClasses().add(ProtobufMessageBodyWriter.class);
 injector = Guice.createInjector(new ServletModule() {
 @Override
 protected void configureServlets() {
  bind(ProtobufMessageBodyReader.class);
  bind(ProtobufMessageBodyWriter.class);
  bind(HelloResource.class);
  serve("/*").with(GuiceContainer.class);
  }
 }); 
 return new WebAppDescriptor.Builder()
          .contextListenerClass(GuiceTestConfig.class)
          .filterClass(GuiceFilter.class)
          .clientConfig(clientConfig)
          .servletPath("/")
          .build();
}
Le code complet est ici.