Skip to content

Blogs de Développeurs: Aggrégateur de Blogs d'Informatique sur .NET, Java, PHP, Ruby, Agile, Gestion de Projet

Forum Logiciel

Forum Logiciel : diffusion de connaissance et d’informations sur toutes les activitĂ©s liĂ©es au dĂ©veloppement d’applications informatiques en entreprise.

Agrégateur de flux

Big Data et banque privée, quels usages ?

Article paru dans le magazine ICT Journal du mois de Mars 2014.

Les technologies Big Data sont de plus en plus utilisées au sein des banques de détail pour le profilage des clients ou les activités marketing. Au sein des banques privées, cependant, les applications sont moins évidentes et les initiatives peu nombreuses. Les opportunités existent pourtant bel et bien, et elles sont surprenantes.

Les technologies Big Data, initiĂ©es par les GĂ©ants du Web comme Google ou Amazon, permettent d’analyser efficacement des donnĂ©es trĂšs volumineuses (de l’ordre du Terabyte voire du Petabyte). La brique logicielle la plus plĂ©biscitĂ©e actuellement est Hadoop, un produit open-source qui s’installe sur un cluster de machines communes et peu onĂ©reuses, et bĂ©nĂ©ficie d’un TCO (Total Cost of Ownership) modeste.

Les principales applications au sein des banques de dĂ©tails consistent Ă  acquĂ©rir des connaissances sur leur base clients, leurs profiles et leur tendances en utilisant des techniques d’apprentissage machine de pointe sur ces donnĂ©es.

Au contraire des banques de dĂ©tail qui exploitent ces technologies depuis quelques annĂ©es, les banques privĂ©es, avec leur faible volume d’opĂ©rations et la taille limitĂ©e de leurs bases client, les considĂšrent avec beaucoup de scepticisme, voir de condescendance.

Pourtant, et contrairement aux idĂ©es prĂ©conçues, des cas d’usages existent et prĂ©sentent des opportunitĂ©s surprenantes autour de trois axes:

  • le dĂ©veloppement de la proximitĂ© avec le client,

  • l’amĂ©lioration des conseils en investissement et

  • la rĂ©duction des coĂ»ts de calcul.

Développer la proximité

Les banques privĂ©es sont parfois mises en concurrence avec les nouveaux modĂšles de tiers gĂ©rants comme les multi-family offices. Ces derniers fournissent Ă  leurs clients un niveau de service trĂšs personnalisĂ© et un haut degrĂ© de proximitĂ©, jusqu’Ă  une certaine forme d’intimitĂ©, Ă  mĂȘme de sĂ©duire les UHNWI (Ultra High Net Worth Individuals).

La dĂ©normalisation progressive des donnĂ©es clientes, des transactions et toutes les autres donnĂ©es liĂ©es mĂȘme indirectement au client dans un cluster Hadoop, puis leurs exploitation massive avec les techniques de pointe d’apprentissage machine permettent aux institutions traditionnelles d’aiguiser leurs connaissances sur leurs clients. il s’agit d’importer sous Hadoop les diffĂ©rentes donnĂ©es de façon incrĂ©mentale, en dĂ©terminant Ă  chaque Ă©tape quelles sont les nouvelles analyses possibles. La banque peut ensuite encore progresser en s’intĂ©ressant aux donnĂ©es tierces, extĂ©rieures Ă  son systĂšme d’information.

Ces nouvelles connaissances leur permettent d’atteindre un niveau de personnalisation du conseil et un degrĂ© de proximitĂ© comparables aux family offices. Elles conservent ainsi plus facilement leurs top clientĂšle sĂ©duite par ces modĂšles de gestion.

Améliorer les conseils

Le profilage des clients pour dĂ©terminer les tendances en terme d’investissement par groupe de pairs prĂ©sente un intĂ©rĂȘt certain. Les profiles peuvent ĂȘtre envisagĂ©s sous tous les angles possibles en combinant les caractĂ©ristiques des clients comme leur Ăąge, leur origine, leur secteur d’activitĂ©, leur niveau de fortune ou encore leur situation familiale.

La banque va typiquement rĂ©utiliser le mĂȘme cluster Hadoop mis en place pour le cas ci-dessus qui comporte dĂ©jĂ  toutes les donnĂ©es nĂ©cessaires Ă  ces nouvelles analyses.

Les objectifs sont multiples. Il s’agit par exemple de pouvoir adapter les conseils en investissement en comparant la situation d’un client avec celles de son groupe de pairs ou simplement avec les tendances gĂ©nĂ©rales du marchĂ©, ou encore d’optimiser les investigations sur les investissements ou clients atypiques, essentiellement pour la dĂ©tection des fraudes.

Réduire les coûts

Des technologies modernes comme Cassandra qui permet d’optimiser le stockage des sĂ©ries temporelles, Infinispan qui permet de structurer un nombre considĂ©rable d’informations en mĂ©moire pour des calculs complexes ou encore Storm, trĂšs efficace dans le traitement en temps-rĂ©el des Ă©vĂ©nements de marchĂ©, offrent une opportunitĂ© sans prĂ©cĂ©dent pour la recherche quantitative sur les trĂšs volumineuses donnĂ©es de marchĂ©.

Il s’agit d’une petite rĂ©volution au sein des banques privĂ©es qui disposent enfin de solutions peu onĂ©reuses pour le calcul massif et en temps rĂ©el des mĂ©triques clĂ©s de risque et performance. Encore plus fort, ces mĂȘmes plateformes peuvent ĂȘtre utilisĂ©es pour l’optimisation, le rebalancing ou encore la simulation de portefeuilles Ă  trĂšs large Ă©chelle. Elles se posent ainsi en alternatives aux approches plus traditionnelles comme les plateformes analytiques de Bloomberg ou les dĂ©veloppements maison avec Terradata.

Le dĂ©ploiement de technologies aussi ambitieuses au sein d’une banque privĂ©e n’est cependant pas anodin. Adopter une approche itĂ©rative consistant Ă  construire les briques logicielles, importer les donnĂ©es et implĂ©menter les analyses ou calculs pas Ă  pas est le facteur clĂ© du succĂšs.

archi

Suggestion d'articles :

  1. Petit-dĂ©jeuner Big Data Ă  GenĂšve : usages et opportunitĂ©s dans nos SI et retour d’expĂ©rience sur la solution Hadoop
  2. Petit-déjeuner : inventer la banque de demain le 19 mars
  3. Data Grid or nosql? same, same but different


Catégories: Blog Société

Revue de Presse Xebia

Revue de Presse Xebia
La revue de presse hebdomadaire des écosystÚmes Java/JEE proposée par Xebia.

Agilité Divide responsibility for defining stories http://www.gravatar.com/f23d9dee080a22a6bb65caad9997acedhttp://blog.xebia.fr/author/lperothttp://twitter.com/ludovicPEROTPar Ludovic Perot

Gojko Adzic est rĂ©putĂ© pour ses travaux sur la dĂ©finition de produit et le travail du (trĂšs bon) Product Owner. Dans Divide responsibility for defining stories, il part d’une conviction : une erreur classique vis-Ă -vis des User Stories et d’attendre du mĂ©tier qu’il dĂ©finisse clairement et entiĂšrement le pĂ©rimĂštre du produit. D’aprĂšs lui, la cause de ce problĂšme est une incomprĂ©hension du rĂŽle du Product Owner ou du client XP : il doit dĂ©cider sur quoi l’équipe va travailler, il n’est pas le responsable de sa dĂ©finition, de sa conception.

Il propose l’expĂ©rience suivante :

  • Les parties-prenantes mĂ©tier spĂ©cifie le ‘As a …’ et le ‘In order to’ ;
  • L’Ă©quipe propose diffĂ©rentes options pour le ‘I want…’ ;
  • Tout le monde Ă©value les options et le PO ou le client XP dĂ©cide laquelle sera implĂ©mentĂ©e.

Un billet qui pousse à la réflexion !

Les barbares attaquent les DSI http://www.gravatar.com/94d0042d24a2eaf116efd4c69ac90541http://blog.xebia.fr/author/ygrenzingerhttp://twitter.com/ygrenzingerhttp://github.com/mbretonPar Yannick Grenzinger

The Family, rapidement devenu un acteur incontournable de l’Ă©cosystĂšme des startups parisiennes, organise des soirĂ©es nommĂ©es « les barbares attaquent » qui revient sur les bouleversements que provoquent le monde des startups Ă  des marchĂ©s tel que le luxe, le retail, Hollywood …

Une de ces soirées, dont la vidéo peut se visionner ici, revenait sur les changements que poussent les startups au sein des DSI.

Voila le résumé :

La disruption numĂ©rique transforme radicalement le rĂŽle des technologies et la mission des DSI dans l’entreprise. Les gĂ©ants de l’internet habituent les employĂ©s, les clients et les dirigeants Ă  des solutions innovantes, simples et ergonomiques. Ces derniers ont des attentes sans cesse plus Ă©levĂ©es Ă  l’égard des DSI. Ce dĂ©calage entre la demande et l’offre des DSI profite aux startups de la Silicon Valley qui s’attaquent pan par pan Ă  l’ensemble des infrastructures et des solutions logicielles. Si ces Barbares attaquent pour le moment les SI des petites et moyennes entreprises, c’est pour mieux s’emparer des grands groupes.

MobilitĂ© L’API wear de Google en developer preview http://www.gravatar.com/742c61e904b91c905521a640c2dc0427http://blog.xebia.fr/author/tguerinhttp://twitter.com/Tom404_http://github.com/tguerinPar Thomas Guerin

C’est officiel Google se lance sur le marchĂ© des montres connectĂ©es dont les premiers constructeurs seront Motorola et LG. D’ailleurs Motorola a dĂ©jĂ  annoncĂ© la sortie de sa moto 360 pour le courant de l’Ă©tĂ© 2014. Par la suite Google souhaite Ă©tendre cette technologie Ă  d’autres objets connectĂ©s. Dans la foulĂ©e de cette annonce, une developer preview de l’API wear a Ă©tĂ© mise Ă  disposition de la communautĂ© des dĂ©veloppeurs.

Craftsmanship Java 8 est sorti http://www.gravatar.com/96a088c582085cec1f71cdf010777f5ahttp://blog.xebia.fr/author/ibeauvaishttp://twitter.com/ibeauvaisPar Ivan Beauvais
  • Si tu n’en peux plus d’écrire des fonctions avec des classes anonymes,
  • Si tu cherches toujours le “reduce” du FluentIterable de Guava,
  • Si tu rĂȘves la nuit de pouvoir faire des Map Reduce sur tes collections en parallĂšle,
  • Si tu dĂ©testes Calendar, java.util.Date et que tu n’as jamais compris la gestion des Time Zone en Java,
  • Si ton espoir secret est d’exĂ©cuter du JavaScript sur la machine virtuelle Java et que se soit rapide,
  • Si tu penses qu’une interface devrait avoir un comportement par dĂ©faut et accepter les mĂ©thodes statiques,
  • Si tu adores les annotations au point de vouloir en ajouter la mĂȘme plusieurs fois sur un mĂȘme Ă©lĂ©ment,
  • Si tu as fait la formation Scala sur Coursera mais que dans la vraie vie tu fais du Java,
  • Si Ă  la pause cafĂ© tu veux toi aussi dire que tu utilises une monade.

… alors Java 8 est fait pour toi, et viens de sortir en version finale, c’est le moment de se lancer !

Front Angular 2.0 http://www.gravatar.com/94d0042d24a2eaf116efd4c69ac90541http://blog.xebia.fr/author/ygreningerhttp://twitter.com/ygrenzingerPar Yannick Grenzinger

La version 2.0 d’Angular, reprĂ©sentant une Ă©volution majeure du framework, commence Ă  ĂȘtre implĂ©mentĂ©e et l’Ă©quipe Google sort un long article sur le sujet. Cette version a pour objectif de proposer un framework web taillĂ© pour le mobile et conçu pour le futur (ce qui fait qu’il sera aussi uniquement compatible avec les derniĂšres versions des navigateurs). Elle a aussi la particularitĂ© d’ĂȘtre codĂ©e en ECMAScript 6+ qui est ensuite compilĂ© en ES5 (la version de JS supportĂ©e par les navigateurs actuels).

Au menu du futur d’Angular :

  • l’utilisation de Object.observe() pour accĂ©lĂ©rer la dĂ©tection des changements et donc l’ensemble du « 2-way databinding »
  • une meilleure instrumentation d’une application
  • un framework plus modulaire pour s’adapter au monde mobile
  • une simplification de l’injection de dĂ©pendance et des directives
  • de nouvelles fonctionnalitĂ©s comme des animations liĂ©s au touch, un meilleur router (surement inspirĂ© de UI-Router) et de la persistence pour faciliter la crĂ©ation d’un mode dĂ©connectĂ©.
Flexbox et Firefox 28 http://www.gravatar.com/d2d7263cc510ef945bf738083be3c4f8http://blog.xebia.fr/author/pantoinehttp://twitter.com/PhilippeAntoinePar Philippe Antoine

Avec la sortie de Firefox 28, il est dĂ©sormais possible d’utiliser flexboxgrid dans tous les navigateurs rĂ©cents sans vendor prefix.

Un exemple de code pour un layout utilisant flexboxgrid:

<div class="row">
 <div class="column-12--hand column-3--lap column-2--desk column-1--wall">
  <div class="box--row"></div>
 </div>
 <div class="column-6--hand column-6--lap column-8--desk column-10--wall">
  <div class="box--row"></div>
 </div>
 <div class="column-6--hand column-3--lap column-2--desk column-1--wall">
  <div class="box--row"></div>
 </div>
</div>

<div class="row">
 <div class="column-12--hand column-3--lap column-2--desk column-1--wall">
  <div class="box--row"></div>
 </div>
 <div class="column-12--hand column-9--lap column-10--desk column-11--wall">
  <div class="box--row"></div>
 </div>
</div>
<div class="row">
 <div class="column-10--hand column-6--lap column-8--desk column-10--wall">
  <div class="box--row"></div>
 </div>
 <div class="column-2--hand column-6--lap column-4--desk column-2--wall">
  <div class="box--row"></div>
 </div>
</div>
Data Hadoop 2.3 : un systÚme de cache centralisé http://www.gravatar.com/2970f03eda4f65fe0a94c9bb32f0415ahttp://blog.xebia.fr/author/bdechouxhttp://twitter.com/BertrandDechouxhttp://github.com/BertrandDechouxPar Bertrand Dechoux

Hadoop est un systĂšme de stockage et de traitement de donnĂ©es optimisĂ© pour les gros volumes. Mais en rĂ©alitĂ©, les profils des traitements de donnĂ©es et des sources de donnĂ©es seront toujours hĂ©tĂ©rogĂšnes. MĂȘme si on travaille avec de gros volumes, on utilise Ă©galement des petites tables de rĂ©fĂ©rence, par exemple. A partir de la version 2.3, Hadoop est dĂ©sormais dotĂ© d’un systĂšme de cache centralisĂ© pour optimiser l’utilisation de ce second type de donnĂ©e.

L’utilisateur peut dĂ©sormais, grĂące une directive, cibler un fichier ou un rĂ©pertoire Ă  charger en mĂ©moire. Cette directive spĂ©cifie un nombre de replication, un time-to-live (TTL) et un pool, qui permet d’ajouter des contraintes supplĂ©mentaires (sĂ©curitĂ©, quota et TTL maximum).

Un point intĂ©ressant est qu’il s’agit d’un vĂ©ritable cache distribuĂ©. Le NameNode (master du systĂšme de fichier) possĂšde une vue complĂšte des caches disponibles. Hadoop optimise l’accĂšs Ă  la donnĂ©e en dĂ©plaçant le traitement Ă  la donnĂ©e et non l’inverse. Avec ce systĂšme de cache, le fonctionnement sera identique. Si un noeud possĂšde la donnĂ©e qui vous intĂ©resse en cache, alors il sera prioritaire pour exĂ©cuter votre traitement.

Dans le future, on peut s’attendre Ă  un systĂšme de cache plus fin : au niveau du block ou mĂȘme en dessous. De mĂȘme, il pourrait ĂȘtre envisageable d’avoir un systĂšme dĂ©tectant de lui-mĂȘme quelles donnĂ©es doivent ĂȘtre mise en cache en prioritĂ©.

Pour en savoir plus, la documentation de rĂ©fĂ©rence est celle du projet Apache Hadoop concernant le « centralized cache management ».

Big Learning : recommendation par recherche (Mahout + Solr) http://www.gravatar.com/2970f03eda4f65fe0a94c9bb32f0415ahttp://blog.xebia.fr/author/bdechouxhttp://twitter.com/BertrandDechouxhttp://github.com/BertrandDechouxPar Bertrand Dechoux

En fin fĂ©vrier, nous vous avions prĂ©sentĂ© la sortie de Mahout 0.9. Un des Ă©lĂ©ments Ă  retenir Ă©tait le lancement d’une nouvelle approche pour construire un systĂšme de recommendation en utilisant un moteur de recherche (Solr en pratique).

Si vous avez assisté à une présentation de Ted Dunning récemment vous savez tout. Pour ceux qui veulent se rattraper, des ressources sont en lignes. Vous pouvez bien sur consulter les slides et le jira MAHOUT-1288 mais désormais un ebook gratuit est disponible décrivant cette approche : Practical Machine Learning : Innovations in Recommendation.

Le principe est relativement simple. Hadoop avec Mahout fait le travail lourd : trouver les relations importantes Ă  retenir dans vos donnĂ©es. Ces dĂ©couvertes sont ensuite chargĂ©es dans le moteur de recherche. Et une requĂȘte de recherche fournit alors la recommendation par le biais de ses rĂ©sultats. Les donnĂ©es, la formulation de la requĂȘte et le post-traitement des rĂ©sultats vont bien sur influencer grandement la qualitĂ© de la recommendation. Certains de ces aspects sont discutĂ©s dans ce livre. L’ajout de bruit (dithering) permet de briser le cercle vicieux du systĂšme recommandant ce qu’il a dĂ©jĂ  recommandĂ© car c’est que l’utilisateur Ă  choisit. Un mĂ©canisme d’anti-flood permet de diversifier les recommendations.

Le livre bien entendu mentionne plusieurs fois que tout cela est plus facile Ă  mettre en place sur MapR (l’employeur de Ted Dunning) que sur une autre distribution incluant Hadoop. Que cela soit vrai ou pas, le livre reste tout de mĂȘme un bon rĂ©sumĂ© de l’approche.

Sortie de la version GA de kibana 3 http://www.gravatar.com/b8cac58f832026793ff351fdd96a40ebhttp://blog.xebia.fr/author/ebriandPar Eric Briand

Elasticsearch vient d’annoncer sur son blog la sortie de la version 3.0.0 GA. Pour rappel, kibana est une interface html5 pour visualiser vos donnĂ©es prĂ©sentes dans elasticsearch. Au programme de version release, pas de nouvelles key feature ce qui n’est guĂšre excitant… Mais beaucoup de bugfixes ! Vous trouverez sur le post du blog des vidĂ©os pour vous y mettre.

Catégories: Blog Société

Xebia, n°5 au palmarÚs Great Place to Work

Les Xebians le disent : c’est trĂšs agrĂ©able de travailler chez Xebia ! Et bien maintenant, c’est officiel ! 

Pour la premiĂšre fois, Xebia a tentĂ© l’aventure « Great Place to Work« , en participant au palmarĂšs qui rĂ©compense les entreprises oĂč il fait bon de travailler. Mais qu’est-ce que cela signifie ? « Une entreprise oĂč il fait bon travailler est un lieu oĂč vous faites confiance Ă  vos dirigeants, vous ĂȘtes fier de votre travail et vous apprĂ©ciez vos collĂšgues. » selon Robert Levering, cofondateur de Great Place to WorkÂź.

Chez Xebia, toutes les conditions étaient réunies pour que nous décrochions la 5Úme place du palmarÚs des best Workplaces en France, dans la catégorie des moins de 500 salariés, en 2014 !

100% des Xebians sont fiers de travailler chez Xebia et 99% apprĂ©cient aussi cet esprit de famille qui rĂšgne au sein de l’entreprise. La preuve en image !

5Ăšme du palmarĂšs Great Place to Work 2014

Catégories: Blog Société

Rendez-vous au ScrumDay 2014 !

Le ScrumDay est une confĂ©rence agile de rĂ©fĂ©rence chaque annĂ©e. Il se dĂ©roulera les 10 et 11 avril et aura lieu pour la premiĂšre fois au centre de congrĂšs de Disneyland Paris. Cette annĂ©e, le thĂšme est la ‘culture produit’. Et nous y serons, avec trois prĂ©sentations…

L’alliance Xebia sera prĂ©sente Ă  cet Ă©vĂšnement.

Nous y animerons trois sessions :

  • Nos ‘cousins’ de Thiga, Alexandre Irrmann-TĂ©zĂ© et Hugo Geissmann, vous parleront du Design Thinking dans la crĂ©ation de produits numĂ©riques :
  • À l’heure actuelle, l’objectif d’un atelier d’imagination d’un service numĂ©rique est de passer d’une idĂ©e Ă  une liste de features. Aucune place n’est laissĂ©e Ă  la divergence intellectuelle, Ă  l’inspiration et au prototypage. Ces pratiques empruntĂ©es au design industriel et regroupĂ©es sous le nom "design thinking" sont parfois perçues comme une perte de temps. Et pourtant, en les appliquant avec discernement elle donnent toutes les clĂ©s pour se lancer dans le dĂ©veloppement d’un produit Ă  la fois dĂ©sirable, faisable et viable !

    Au cours de cette session de 50 minutes, nous vous proposons de découvrir les grandes étapes du design thinking illustrées par des exemples trÚs concrets empruntés à notre quotidien comme à de grands projets internationaux.

  • Yannick Grenzinger et ClĂ©ment Rochas vous proposeront un retour d’expĂ©rience sur la spĂ©cification par l’exemple :
  • Vous avez Ă©crit des centaines de pages de spĂ©cification mais personne ne les a lu et elles sont dĂ©jĂ  dĂ©suĂštes ? Pourtant "ce qui est clairement Ă©noncĂ© ce conçoit bien" ! La solution se trouve dans la spĂ©cification par l’exemple qui permet de mettre en pratique l’ATDD, le BDD et surtout la co-crĂ©ation en crĂ©ant le dialogue et un langage commun avec le mĂ©tier.

    Cette session est un retour d’expĂ©rience sur la mise en place de la spĂ©cification par l’exemple chez SFR. Dans le cadre de la gestion de l’offre fixe, nous avons travaillĂ© en collaboration directe, rĂ©guliĂšrement autour du mĂȘme Ă©cran, avec notre PO afin de dĂ©crire les comportements du service interne aussi bien ceux dĂ©jĂ  dĂ©veloppĂ©s que les Ă©volutions. Ceci nous a permis de reprendre en main l’implĂ©mentation des rĂšgles mĂ©tiers, grandement amĂ©liorer la couverture de tests et mĂȘme permettre le refactoring du code. Nous avons appliquĂ© la mĂȘme mĂ©thode sur la partie post-panier de la boutique en ligne SFR mais cette fois avec des tests fonctionnels de l’interface. La session s’adresse aux dĂ©veloppeurs comme aux fonctionnels.
    Nous ferons une dĂ©monstration de l’outil Thucydides (JBehave + Selenium) et vous donnerons les arguments pour vous lancer !

  • Enfin, Renaud Chevalier vous posera 10 questions auxquelles il faut apporter une rĂ©ponse pour savoir si oui ou non, vous ĂȘtes prĂȘts pour le modĂšle Spotify :
  • Depuis la publication de Kniberg en 2012, le modĂšle Spotify est devenu "LE" modĂšle organisationnel en feature teams Ă  la mode. Toutes les compĂ©tences rĂ©unies dans une mĂȘme Ă©quipe pour rĂ©aliser un besoin fonctionnel de bout en bout. Ça fait rĂȘver ! Mais concrĂštement, comment l’implĂ©menter ? Suite Ă  plusieurs transformations d’envergures, nous avons identifiĂ© les 10 questions indispensables Ă  se poser avant de se lancer : stratĂ©gie, gestion de produit, organisation, test, devops et communication.
    Vous voulez savoir si vous ĂȘtes prĂȘts pour le modĂšle Spotify ? Venez vous Ă©valuer dans ma session !

    Cette prĂ©sentation est un retour d’expĂ©rience sur les questions Ă  se poser avant de se lancer dans une telle transformation. Nos clients nous sollicitent de plus en plus sur ce type d’accompagnement. Parfois, la dĂ©cision d’appliquer le modĂšle Spotify est mĂȘme dĂ©jĂ  prise avant notre intervention. L’objectif est d’obtenir une prise de conscience de toutes personnes envisageant de mettre en place le modĂšle Spotify sur les points suivants :
    - C’est un modĂšle organisationnel compliquĂ© Ă  implĂ©menter
    - Les impacts humains et techniques sont largement sous-estimés
    - C’est un chantier risquĂ© avec un coĂ»t d’entrĂ©e Ă©levĂ©
    - Il existe une multitude de solutions d’implĂ©mentation
    - Ce n’est pas la rĂ©ponse Ă  tous les problĂšmes
    - C’est un modĂšle qui n’est pas applicable dans certains contextes / cultures
    Les 10 questions sont illustrées avec des problématiques concrÚtes. Des solutions potentielles sont présentées dans certains cas (stratégie de découpe et devops en particulier).

Nous y tiendrons, comme chaque annĂ©e, un stand oĂč vous pourrez nous rencontrer. Nous vous y rĂ©servons quelques surprises.

Nous espérons donc vous rencontrer à cette occasion !

Catégories: Blog Société

Java 8 – Gestion du temps

Blog d’Ippon Technologies - mer, 03/19/2014 - 09:00
Pour l’Ă©vĂšnement de la sortie de Java 8, Ippon vous propose plusieurs posts sur les nouveautĂ©s du langage. A lire Ă©galement :

Avec Java 8 vient une nouvelle API de gestion du temps nommée java.time qui est spécifiée par la JSR 310 et implémentée via le projet threeten.

Il y a ainsi 3 API différentes pour gérer le temps dans le JDK8.

Situation avant Java 8

Le but de cette nouvelle API est de pallier aux défauts des 2 premiÚres :

  • Les annĂ©es sont stockĂ©es sur 2 chiffres Ă  partir de 1900 ce qui conduit Ă  des manipulations de type +1900/-1900 pour utiliser ces valeurs
  • Mois commençant Ă  0 ce qui oblige Ă  faire des +1 pour les convertir en date humainement lisible, et Ă  des -1 pour l’opĂ©ration inverse
  • Objets Date et Calendar muables ce qui oblige Ă  en faire une copie dĂ©fensive (en faisant un clone()) pour Ă©viter que le code appelant ne les modifie
  • ProblĂšme de nommage : Date n’est pas une date mais une date et une heure (datetime)
  • Nombreux constructeurs et mĂ©thodes dĂ©prĂ©ciĂ©s car buggĂ©s
  • API peu facile Ă  utiliser
  • Pas thread-safe : source de bugs de concurrence
  • Palette de concepts incomplĂšte : pas de durĂ©e, pĂ©riode, intervalle, Heure(heures-minutes-secondes), Date(annĂ©e-mois-jour)…

java.time est inspirée de la librairie Joda-Time et est en grande partie réalisée par son auteur, Stephen Colebourne. Il a été choisi de réécrire une librairie de gestion du temps from scratch au sein de Java 8 afin de pouvoir corriger les défauts constatés de Joda-Time.

  1. Mauvaise reprĂ©sentation interne des dates en tant qu’instant. Alors qu’une date&heure peut correspondre Ă  plusieurs instants lors des changements “heure d’Ă©tĂ©/heure d’hiver” ou ne pas exister (passage de 3h Ă  2h ou de 2h Ă  3h du matin) ce qui amĂšne également des calculs plus compliquĂ©s
  2. Trop flexible (chaque classe peut accepter un systĂšme calendaire diffĂ©rent du calendrier grĂ©gorien) -> utilisation d’un systĂšme calendaire global ISO (calendrier grĂ©gorien) par dĂ©faut dans java.time
  3. Accepte les null sans erreur pour la plupart de ses méthodes ce qui entraßne des bugs

java.time vise donc Ă  apporter un design plus simple et plus robuste que celui de Joda-Time. Cette API sera Ă©galement disponible via un backport pour Java 7 dispo sur le central maven. L’API fluide permet de manipuler des objets immuables et thread-safe afin d’éviter les problĂšmes. Les Classes de gestion du temps sont sĂ©parĂ©s selon les 2 visions du temps : temps machine et temps humain. Afin d’assurer une transition en douceur, on peut facilement transformer un objet java.util.Date ou java.util.GregorianCalendar depuis et vers cette API.

Temps Machine Instant

Un point précis dans le temps.
La classe Instant reprĂ©sente le nombre de nanosecondes depuis l’Epoch (1er Janvier 1970). c’est ce qui se rapproche le plus de java.util.Date.

Instant.ofEpochSecond(1395100800);
Instant.parse("2014-03-18T00:00:00.000Z");
Duration

Durée entre 2 Instants ou durée en jours/heures/minutes/secondes/millisecondes/nanosecondes.

Duration.ofDays(5);
Duration.of(5, ChronoUnit.DAYS);
Duration.between(Instant.parse("2011-07-28T00:00:00.000Z"),
Instant.parse("2014-03-18T00:00:00.000Z")).getSeconds();
Temps Humain Fuseau horaire

On peut l’utiliser pour crĂ©er des ZonedDateTime et des OffsetDateTime Ă  partir d’un instant via les classes ZoneId et ZoneOffset.
ZonedDateTime et des OffsetDateTime sont Ă©quivalent Ă  la classe GregorianCalendar.

ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("Europe/Paris"));
OffsetDateTime.ofInstant(Instant.now(), ZoneId.of("GMT+1"));
OffsetDateTime.ofInstant(Instant.now(), ZoneOffset.of("+01:00"));
LocalDateTime

Date et Heure (sans notion de fuseau horaire).

LocalDateTime date = LocalDateTime.of(LocalDate.of(2014, Month.MARCH, 18), LocalTime.MIDNIGHT);
// formatage
date.format(DateTimeFormatter.ISO_DATE);
date.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
//parsing
LocalDateTime.parse("18/03/2014 00:00", DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
// manipulation
date.withHour(16).plusWeeks(3); // on positionne Ă  16h et on ajoute 3 semaines
date.with(TemporalAdjusters.firstDayOfNextMonth()); // le premier jour du mois prochain
date.with(Temporals.nextWorkingDay()); // TemporalAdjuster de threeten-extra (non inclus dans le jdk)
Dates et heures partielles

Un LocalDateTime incomplet : 18/03 (18 Mars), 12:00 (midi).

LocalDate.of(2014, Month.MARCH, 18);
LocalTime.of(12, 0); // Ă©gal Ă  LocalTime.NOON
DayOfWeek.of(2);// DayOfWeek.TUESDAY
Month.of(3); // Ă©gal Ă  Month.MARCH
MonthDay.of(Month.MARCH, 18);
YearMonth.of(2014, Month.MARCH);
Year.of(2014);
PĂ©riode

ReprĂ©sentation “humaine” d’une durĂ©e, par exemple 1 mois (qu’il ait 28 ou 31 jours)

Period.ofMonths(3);
//période entre la sortie de java 7 et la sortie de java 8
Period.between(LocalDate.of(2011, Month.JULY, 28), LocalDate.of(2014, Month.MARCH, 18)); // 2 ans, 7 mois, 18 jours
Interoperabilité java.time, Date, GregorianCalendar.

Possibilité de transformer facilement un objet depuis et vers cette nouvelle API.

Date date = new Date();
date.toInstant();
Date.from(Instant.now());
//
GregorianCalendar gregorianCalendar = new GregorianCalendar(TimeZone.getTimeZone("Europe/Paris"));
gregorianCalendar.toZonedDateTime();
gregorianCalendar.toInstant();
GregorianCalendar.from(ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("Europe/Paris")));
Conclusion

Comme on vient de le voir, cette API de gestion des données temporelles permet de corriger les défauts des précédentes APIs tout en étant trÚs facile et agréable à utiliser, notamment grùce à sa syntaxe fluide et ses concepts clairs.
Un certain nombre de possibilitĂ©s existant avec Joda-Time n’ont pas pu voir le jour au sein de java.time et ont rejoint le projet threeten-extra (dispo sur maven central) que l’on pourra donc inclure en complĂ©ment dans ses projets.
Il faut Ă©galement espĂ©rer que l’inclusion de cette nouvelle API au sein de Java 8 permette une intĂ©gration rapide au sein des nombreux frameworks que nous utilisons tous les jours.

Catégories: Blog Société

Petit-dĂ©jeuner : Vers l’entreprise agile – le mardi 1 avril

Entr_AgileBLOG

Une fois passĂ©es les premiĂšres expĂ©rimentations sur les mĂ©thodes agiles, une question s’impose de façon rĂ©currente : comment changer d’Ă©chelle et devenir une entreprise Agile ?

Bien sĂ»r, il ne s’agit pas de savoir lancer un Ă©niĂšme projet en Scrum mais plutĂŽt de rĂ©pondre aux questions suivantes :

  • Qu’est ce qu’une entreprise Agile ?
  • L’entreprise Agile chez moi, est-ce que cela fait sens ? Jusqu’oĂč dois-je ou puis-je aller ?
  • Comment assurer un pilotage de mon portefeuille projets et de mes budgets ?
  • Comment engager cette transformation? Quels sont les Ă©cueils Ă  Ă©viter ?

En répondant à ces questions, OCTO vous propose un chemin.

Nous ne parlerons pas directement de Scrum, Software Craftsmanship, Lean Startup, ou autre Devops, mais bien de la maniĂšre de crĂ©er une alchimie rĂ©unissant ces ingrĂ©dients au travers de la gouvernance, de l’organisation, des pratiques de management et de la culture d’entreprise.

Au delĂ  du partage des bonnes pratiques et des Frameworks d’entreprise, ce petit dĂ©jeuner sera l’occasion confronter les retours d’expĂ©rience chez nos clients dans diffĂ©rents domaines (banque, eCommerce, tĂ©lĂ©coms, pure players du web).

La deuxiĂšme partie de ce petit dĂ©jeuner rĂ©unira  des acteurs de la transformation agile chez SociĂ©tĂ© GĂ©nĂ©rale et Viadeo autour d’une table ronde.

 

Avec ce petit dĂ©jeuner, nous avons l’ambition de vous fournir une base de rĂ©flexion et d’action pour transformer votre organisation en entreprise apprenante.

Ce sĂ©minaire s’adresse Ă  tous ceux qui ont envie d’aller plus loin sur l’agilitĂ© : marketing, chefs de produits, architectes, geeks, managers ou responsables DSI.

Cliquez ici pour vous inscrire à ce petit-déjeuner

Suggestion d'articles :

  1. Petit-dĂ©jeuner AgilitĂ© Ă  GenĂšve : un voyage vers l’entreprise Agile!
  2. Petit-dĂ©jeuner : Tout pour rĂ©ussir votre premier projet Hadoop et passer Ă  l’Ă©chelle industrielle le 22 Avril
  3. OCTO organise un petit dĂ©jeuner sur le thĂšme des MaĂźtrises d’Ouvrage Agile

Catégories: Blog Société

Premier aperçu d'AngularJS 2.0

Zenika - mar, 03/18/2014 - 14:45

Au dĂ©tour de plusieurs confĂ©rences, notamment la trĂšs rĂ©ussie ngConf 2014, l’équipe de dĂ©veloppement d’AngularJS a Ă©voquĂ© le sujet d’AngularJS 2.0. Pas plus tard que cette nuit alors que j'allais publier cet article, un article de blog est apparu sur le blog officiel introduisant Angular 2.

Outre ce nouvel article, beaucoup d'Ă©lĂ©ments de la conception d'Angular 2 sont publics. Tous les drafts de design des diffĂ©rents composants ainsi que les comptes rendus de rĂ©unions hebdomadaires de l’équipe de dĂ©veloppement. Il est donc possible, en creusant un peu, d’avoir un bon aperçu de ce qui se prĂ©pare. Les bases AngularJS 2.0 sera une... Read Premier aperçu d'AngularJS 2.0

Catégories: Blog Société

Java sera Ă  l’honneur chez Microsoft le 20 mars et vous y ĂȘtes conviĂ©s !

Logo InfoQ
La tendance actuelle est au rapprochement ! Vous n’ĂȘtes pas sans savoir que Microsoft et Oracle ont signĂ© un accord pour associer leur force et proposer une offre plus complĂšte sur le Cloud. Cette nouvelle stratĂ©gie orientĂ©e utilisateurs vise Ă ...
Catégories: Blog Société

Java 8 – Interfaces fonctionnelles

Blog d’Ippon Technologies - mar, 03/18/2014 - 09:30

Pour l’Ă©vĂšnement de la sortie de Java 8, Ippon vous propose plusieurs posts sur les nouveautĂ©s du langage. A lire Ă©galement :

Java 8 introduit le concept d’”interface fonctionnelle” qui permet de dĂ©finir une interface disposant d’une unique mĂ©thode abstraite, c’est-Ă -dire une seule mĂ©thode ne possĂ©dant pas d’implĂ©mentation par dĂ©faut.

Le but d’une interface fonctionnelle est de dĂ©finir la signature d’une mĂ©thode qui pourra ĂȘtre utilisĂ©e pour passer en paramĂštre :

  • une rĂ©fĂ©rence vers une mĂ©thode statique
  • une rĂ©fĂ©rence vers une mĂ©thode d’instance
  • une rĂ©fĂ©rence vers un constructeur
  • une expression lamba.

MĂȘme si ce n’est pas obligatoire, le JDK permet de vĂ©rifier le contrat “une seule mĂ©thode abstraite” en appliquant l’annotation @FunctionalInterface :

@FunctionalInterface
public interface ExampleInterface {
    void doSomething();
    default int methodWithDefaultImpl() { return 0; }
}

Si vous définissez plusieurs méthodes abstraites, le compilateur génÚrera une erreur du type :

Unexpected @FunctionalInterface annotation
ExampleInterface is not a functional interface
multiple non-overriding abstract methods found in interface ExampleInterface

Retour en arriĂšre

En Java < 8, lorsqu’il fallait passer une fonction en paramĂštre d’un appel de fonction, le recours Ă  une classe anonyme Ă©tait courant.

Prenons un exemple. Nous devons parser des chaĂźnes de caractĂšres de type “<prĂ©nom> <nom>” en les dĂ©coupant sur le caractĂšre espace.

Nous allons créer des objets de type Name :

public class Name {

   private String firstName;
   private String lastName;

   public Name(String firstName, String lastName) {
       this.firstName = firstName;
       this.lastName = lastName;
   }

   public String getFirstName() { return firstName; }
   public String getLastName() { return lastName; }

}

Pour le parsing, nous crĂ©ons une classe NameParser dont la responsabilitĂ© sera limitĂ©e au seul rĂŽle de parsing. La classe NameParser ne doit donc pas construire l’objet rĂ©sultant. Nous dĂ©lĂšguons cette responsabilitĂ© Ă  une interface Creator qui dĂ©clare une mĂ©thode “create” prenant deux arguments (le prĂ©nom et le nom extraits lors du parsing) :

public class NameParser {
    public  T parse(String name, Creator creator) {
        String[] tokens = name.split(" ");
        String firstName = tokens[0];
        String lastName = tokens[1];
        return creator.create(firstName, lastName);
    }
}

public interface Creator {
    T create(String firstName, String lastName);
}

Pour utiliser notre NameParser, nous devons l’appeler en lui passant une instance d’une classe implĂ©mentant l’interface Creator. Nous avons donc recours Ă  une classe anonyme :

NameParser parser = new NameParser();

Name res = parser.parse("Eric Clapton", new Creator<name>() {
    @Override
    public Name create(String firstName, String lastName) {
        return new Name(firstName, lastName);
    }
});

Les responsabilités sont clairement dissociées mais la syntaxe résultante est trÚs verbeuse et la lisibilité du code est rendue difficile


En Java 8…

Java 8 apporte une rĂ©ponse Ă  ce problĂšme grĂące aux “interfaces fonctionnelles”.

Bien que l’annotation @FunctionalInterface ne soit pas obligatoire, nous l’ajoutons sur notre interface Creator :

@FunctionalInterface
public interface Creator<T> {
    T create(String firstName, String lastName);
}

Sans aucune modification sur la classe NameParser, nous allons maintenant pouvoir passer toute méthode dont la signature répondra aux contraintes suivantes :

  • deux paramĂštres de type String
  • type de retour gĂ©nĂ©rique

Java se chargera en interne de convertir l’appel de sorte que l’on aura toujours l’impression d’appeler la mĂ©thode “create” de l’interface Creator.

Référence vers un constructeur

Le constructeur de la classe Name répond aux contraintes définies ci-dessus. Nous pouvons donc écrire :

Name res = parser.parse("Eric Clapton", Name::new);

Ici, la syntaxe “<cible>::<mĂ©thode>” permet de dĂ©finir une rĂ©fĂ©rence sur mĂ©thode, le mot-clĂ© “new” faisant rĂ©fĂ©rence au constructeur de la classe Name.

Référence vers une méthode statique

De la mĂȘme maniĂšre, nous pouvons donner une rĂ©fĂ©rence vers une mĂ©thode statique. Prenons une factory :

public class Factory {
    public static Name createName(String firstName, String lastName) {
        return new Name(firstName, lastName);
    }
}

Nous pouvons écrire :

Name res = parser.parse("Eric Clapton", Factory::createName);
RĂ©fĂ©rence vers une mĂ©thode d’instance

Toujours avec la mĂȘme syntaxe, nous pouvons donner une rĂ©fĂ©rence vers une mĂ©thode d’instance, donc une rĂ©fĂ©rence vers un objet existant. Prenons une factory lĂ©gĂšrement modifiĂ©e (plus de mot-clĂ© “static”) :

public class Factory {
    public Name createName(String firstName, String lastName) {
        return new Name(firstName, lastName);
    }
}

Nous pouvons alors écrire :

Factory factory = new Factory();
Name res = parser.parse("Eric Clapton", factory::createName);
Expression lambda

Enfin, nous pouvons passer une expression lambda :

Name res = parser.parse("Eric Clapton", (s1, s2) -> new Name(s1, s2));

Ou alors, avec notre factory :

Name res = parser.parse("Eric Clapton", (s1, s2) -> Factory.createName(s1, s2));
Package java.util.function

Dans notre exemple, nous avons crĂ©Ă© notre propre interface fonctionnelle. Pour les cas les plus simples – et certainement les plus courants – ce n’est pas nĂ©cessaire. En effet, le package java.util.function fait son apparition dans le JDK et reçoit de nombreuses interfaces fonctionnelles de base : http://download.java.net/jdk8/docs/api/java/util/function/package-summary.html

Les interfaces définies avec des types génériques sont :

  • Consumer<T> : opĂ©ration qui accepte un unique argument (type T) et ne retourne pas de rĂ©sultat.
    • void accept(T);
  • Function<T,R> : opĂ©ration qui accepte un argument (type T) et retourne un rĂ©sultat (type R).
    • R apply(T);
  • Supplier<T> : opĂ©ration qui ne prend pas d’argument et qui retourne un rĂ©sultat (type T).
    • T get();

Notons l’interface Predicate qui est une spĂ©cialisation de Function visant Ă  tester une valeur et retourner un boolĂ©en.

  • boolean test(T);

Enfin, de nombreuses autres interfaces fonctionnelles sont définies avec des types de base : IntConsumer, LongToIntFunction, DoubleSupplier, etc.

Exemple avec plusieurs méthodes

Nous avons vu qu’une interface fonctionnelle ne peut contenir qu’une seule mĂ©thode abstraite. Impossible, donc, d’annoter l’interface suivante avec @FunctionalInterface sous peine d’obtenir une erreur de compilation :

private interface Operation<T>
{
    public T function();
    public void onSuccess(T res);
    public void onError(Exception ex);
}

En Java < 8, nous aurions écrit :

public <T> void doSomething(Operation<T> operation) {
    try {
        T res = operation.function();
        operation.onSuccess(res);
    } catch (Exception ex) {
        operation.onError(ex);
    }
}

Avec un appel trÚs verbeux :

doSomething(new Operation<Object>() {
    @Override
    public Object function() {
        return 42;
    }
    @Override
    public void onSuccess(Object res) {
        System.out.println(res);
    }
    @Override
    public void onError(Exception ex) {
        System.err.println("Error: " + ex.getMessage());
    }
});

En Java 8, nous pouvons nous passer complĂštement de l’interface Operation et utiliser une interface fonctionnelle par mĂ©thode. Et, puisque c’est possible, nous allons exploiter le package java.util.function. Notre mĂ©thode devient :

public <T> void doSomething(Supplier<T> function, Consumer<T> onSuccess, Consumer<Exception> onError) {
   try {
       T res = function.get();
       onSuccess.accept(res);
   } catch (Exception ex) {
       onError.accept(ex);
   }
}

Et l’appel est grandement simplifié :

doSomething(
    () -> 42,
    System.out::println,
    ex -> System.err.println("Error: " + ex.getMessage()));
Conclusion

Le principe d’interface fonctionnelle permet de se passer des classes anonymes dans un grand nombre de cas. Du point de vue du code appelĂ©, les choses restent simples : on continue Ă  appeler une mĂ©thode d’une interface. C’est du cĂŽtĂ© du code appelant que la lisibilitĂ© du code est grandement amĂ©liorĂ©e . L’emprunts aux langages fonctionnels est ici une grande rĂ©ussite.

Catégories: Blog Société

Freelance ou agence, qui choisir et pourquoi ?

L'actualité de Synbioz - mar, 03/18/2014 - 00:00

J’ai conscience que ce point peut ĂȘtre sujet Ă  dĂ©bats, et je serai ravis d’avoir des retours d’expĂ©rience en commentaire.

Je l’aborde car j’ai une expĂ©rience des 2 situations.

Lire la suite...

Catégories: Blog Société

POST vs. PUT : la confusion

Aujourd’hui, de plus en plus d’applications web disposent d’une API. La pratique de SOAP Ă©tant jugĂ©e trop glissante (surtout avec les interfaces liquides), c’est le REST qui se rĂ©pand.

Ce style d’architecture reposant sur HTTP, comprendre la norme HTTP est essentiel.

Cependant, les mauvais usages et autres anti-patterns sont Ă  l’affĂ»t, prĂȘts Ă  se jeter sur les concepteurs et dĂ©veloppeurs d’API. Dans cet article, nous nous attacherons Ă  dĂ©mĂȘler une confusion entre PUT et POST.

Comme remarqué par John Calcote, beaucoup ont été tentés de faire un mapping naïf entre CRUD et les verbes HTTP :

  • Create = PUT
  • Retrieve = GET
  • Update = POST
  • Delete = DELETE

Et une variante trÚs répandue :

  • Create = POST
  • Update = PUT

Certains seront peut-ĂȘtre chagrinĂ©s d’apprendre que jusqu’en 2010, il n’y avait que 3 verbes HTTP dĂ©diĂ©s au CRUD, et que POST n’a jamais fait partie et ne fera jamais partie d’entre eux.

Posez vos boucliers, je n’ai pas dit que nous ne pouvions pas crĂ©er ou mettre Ă  jour une entitĂ© avec POST ! Mais comme dans HTTP, et Ă  fortiori dans une API RESTful, la sĂ©mantique est trĂšs importante et a un impact sur le design de l’API, POST peut avoir le rĂŽle de crĂ©ation , mais n’est pas prĂ©sentĂ© comme tel. Nous allons devoir y regarder de plus prĂšs.

Les mauvaises pratiques

Voici la liste non exhaustive des mauvaises pratiques autour de PUT et POST :

PUT pour modifier uniquement, POST pour créer

Erreur commise dans le but de « clarifier » les rĂŽles respectifs de PUT et POST, afin que les « dĂ©butants » comprennent vite leur API. Également commise par ceux qui trouvent POST bien pratique pour crĂ©er, et qui ont cantonnĂ© PUT Ă  un rĂŽle par dĂ©faut (par mĂ©connaissance du verbe PUT ?). Un inconvĂ©nient de cette pratique, si on ne connait pas le rĂ©cent verbe PATCH, est qu’on ne peut pas faire de mise Ă  jour partielle via POST alors que c’est trĂšs pratique et largement tolĂ©rĂ©. Nous verrons plus bas que si PUT n’est pas utilisĂ© pour crĂ©er, cela ne doit rĂ©sulter que d’une contrainte.

POST utilisant l’URI de l’entitĂ© Ă  crĂ©er

Probablement le plus grave. Ceci constitue Ă  la fois une violation de la dĂ©finition de POST et une ignorance totale du rĂŽle de PUT. Dans le cas oĂč POST crĂ©e une ressource, le corps de la requĂȘte contient soit l’entitĂ©, soit des informations permettant de la crĂ©er, mais l’URI est toujours une URI tierce capable de traiter la demande.

Exemple de comportement non conforme :
POST /clients/123
> ...
> ...
< 201 Created
> GET /clients/123
< 200
< ...
< ...

Exemple de comportement conforme :
> POST /clients/create
> ...
> ...
< 201 Created
< Location: /clients/123
> GET /clients/123
< 200 OK
< ...
< ...

POST qui crĂ©e une entitĂ© sans renvoyer le header « Location »

Le code retour 201 Ă©tant facultatif mais conseillé ; hĂ© oui, oĂč est l’entitĂ© crĂ©Ă©e ou modifiĂ©e ? En renvoyant le header Location, en rĂ©ponse Ă  un POST supposĂ© crĂ©er une ressource, je permets au client de connaĂźtre son identifiant.

PUT qui renvoie un header Location

C’est superflu, vu qu’une requĂȘte PUT se fait sur l’URI de l’entitĂ© Ă  crĂ©er. Si par exemple je devais complĂ©ter cet Ă©change :
> GET /clients/123
< 404
> PUT ???
> ...
< 201
> GET /clients/123
< 200
< ...
Les points d’interrogation ne peuvent ĂȘtre remplacĂ©s que par « /clients/123″, du coup pas besoin de header Location.

PUT partiel

On doit fournir une entitĂ© complĂšte dans le corps d’une requĂȘte PUT

POST omnipotent, PUT inutilisé voire inutilisable

Cela revient Ă  supprimer la sĂ©mantique de PUT et POST, et Ă  la faire porter entiĂšrement Ă  l’URI et Ă  ses paramĂštres. Un peu comme SOAP, un peu comme les dĂ©buts erratiques du web oĂč toutes pages d’un site Ă©taient servies par /servlet/Toto?page=truc&action=toutgerer&jenpasse&desmeilleures

POST pour crĂ©er alors qu’on connait l’identifiant de l’entitĂ© Ă  crĂ©er

Si l’identifiant de l’entitĂ© Ă  crĂ©er est prĂ©visible, PUT est plus appropriĂ© car nous avons alors les deux conditions nĂ©cessaires pour faire un PUT :

  • avoir une entitĂ© complĂšte (crĂ©ation)
  • avoir l’URI de l’entitĂ© (grĂące Ă  l’identifiant)
Mais alors comment PUT et POST sont-ils conçus pour fonctionner ? PUT

Regardons la norme HTTP. D’aprĂšs la RFC 2616 (HTTP methods), PUT sert Ă 

Créer une entité :
  • L’URI doit ĂȘtre celle de l’entitĂ© Ă  crĂ©er
  • Si l’entitĂ© dans la requĂȘte est acceptĂ©e et crĂ©Ă©e cĂŽtĂ© serveur, le serveur doit renvoyer un code 201 (created).
  • Si l’entitĂ© peut avoir plusieurs URIs (exemple : /script/v1.2 ou /script/current), le serveur peut donc dĂ©finir ces URIs alternatives comme pointant sur la nouvelle entitĂ©
Modifier une entité :
  • Si une entitĂ© avec la mĂȘme URI que celle de la requĂȘte existe dĂ©jĂ , l’entitĂ© de la requĂȘte devrait la remplacer.
  • Ce n’est pas une crĂ©ation, le code retournĂ© par le serveur en cas de succĂšs doit ĂȘtre 200 (OK) ou 204 (No content). En effet, en pratique un PUT va trĂšs rarement gĂ©nĂ©rer une rĂ©ponse avec un contenu.
Dans les deux cas :
  • Une incomprĂ©hension des header Content-* de la part du serveur doit gĂ©nĂ©rer une erreur 501 (not implemented) car il n’a pas le droit de les ignorer. Les autres cas d’erreur devraient Ă©galement donner un code cohĂ©rent, voire un message d’erreur cohĂ©rent.
  • L’URI du PUT est celle de l’entitĂ© Ă  crĂ©er/mettre Ă  jour.
  • Le corps de la requĂȘte PUT doit contenir l’entitĂ© complĂšte.
  • La redirection est possible, mais doit ĂȘtre permanente (code 301). Libre au client de suivre la redirection, mais s’il s’arrĂȘte lĂ  le PUT n’est Ă©videmment pas effectif. Ce cĂŽtĂ© dĂ©finitif de la redirection est nĂ©cessaire du fait que l’URI doit dĂ©signer l’entitĂ©, et non pas un processus ou action qui prendrait en charge la requĂȘte. On ne redirige donc que si on veut indiquer un changement d’URI. Il faut donc s’attendre Ă  ce qu’une future requĂȘte accĂšde directement Ă  l’URI indiquĂ©e dans le prĂ©cĂ©dent 301.

DĂ©tail qui a son importance, la rĂ©ponse Ă  un PUT n’est pas cachable car dĂ©pendant intrinsĂšquement du contenu de la requĂȘte ! Vu que la rĂ©ponse est vide dans 99% des cas, ceci n’est qu’un dĂ©tail logique.

Enfin, deux requĂȘtes PUT identiques (mĂȘme contenu, mĂȘme URI) laissent le systĂšme dans le mĂȘme Ă©tat que si une seule avait Ă©tĂ© lancĂ©e (idempotence). Un dĂ©tail ne devra pas nous Ă©chapper : on doit rĂ©pondre 200 ou 204 Ă  la seconde si on a rĂ©pondu 201 Ă  la premiĂšre ; si James Bond ne meurt que deux fois, une entitĂ© n’est elle, crĂ©Ă©e qu’une fois.
> GET /clients/123
< 404
> PUT /clients/123
> toto
< 201
> GET /clients/123
< 200
< toto
> PUT /clients/123
> toto
< 204
> GET /clients/123
< 200
< toto
> PUT /clients/123
> poum
< 204
> GET /clients/123
< 200
< poum
Ci-dessus, nous voyons que le 201 n’est renvoyĂ© que la premiĂšre fois, Ă  la crĂ©ation. 200 aurait Ă©tĂ© acceptable Ă  la place de 204, mais 204 signale explicitement que la rĂ©ponse n’a pas de corps, alors qu’avec un 200 le client le dĂ©couvre.

Conclusion : PUT est bien un double verbe CRUD, capable de crĂ©er ou de modifier en intĂ©gralitĂ© l’entitĂ© dĂ©signĂ©e par l’URI. En pratique, PUT peut ĂȘtre Ă©cartĂ© comme verbe pour la crĂ©ation car notre application ne permettra pas (politique de sĂ©curitĂ©, contrainte technique ou contrainte fonctionnelle) Ă  un client de connaĂźtre Ă  l’avance son URI.

POST

Toujours d’aprĂšs la RFC 2616, POST sert à :

  • annoter des ressources existantes
  • poster un message au sens « forum » du terme
  • envoyer des donnĂ©es Ă  un processus qui saura les prendre en charge
  • ajouter des donnĂ©es dans une base de donnĂ©e

Vous trouvez ça flou ? La RFC confirme votre impression : c’est le serveur qui dĂ©termine ce que nous devons faire d’un POST. Donc, pas de sĂ©mantique forte associĂ©e Ă  ce verbe.

Comme pour le PUT, le POST doit renvoyer le statut 200 si la réponse contient une entité, 204 si elle est vide.

Maintenant, vous aurez peut-ĂȘtre une question : la crĂ©ation en POST, nous n’en avons pas parlé ! Ai-je ratĂ© quelque chose ?

Pas de panique : il y a bien une petite phrase pour dire que si une entitĂ© est crĂ©Ă©e suite Ă  une POST, la rĂ©ponse a le statut 201 et devrait Ă©galement indiquer dans le header Location l’uri de la nouvelle entitĂ©.

On voit donc que la crĂ©ation d’entitĂ© n’est qu’un rĂŽle annexe de POST, il n’y a donc aucune raison de l’introniser « verbe CRUD pour la crĂ©ation » !

Le problĂšme pratique

Avec de telles dĂ©finitions, les concepteurs d’API se sont vite trouvĂ©s embarrassĂ©s : d’un cĂŽtĂ©, un PUT qui permet create/update mais avec une entitĂ© complĂšte ; de l’autre, un POST dont la sĂ©mantique floue permet de tout faire. InĂ©vitablement, POST s’est retrouvĂ© utilisĂ© pour les crĂ©ations et mises Ă  jour avec des informations partielles. Comme on ne peut pas toujours connaĂźtre Ă  l’avance l’URI de l’entitĂ© Ă  crĂ©er, POST a donc pris frĂ©quemment le rĂŽle de create/update : on demande une crĂ©ation avec les informations postĂ©es, et la nouvelle URI est dans la rĂ©ponse.

Ce dernier point marque une carence du protocole : il n’y a pas de moyen, en HTTP, de mettre Ă  jour une entitĂ© connue, en la dĂ©signant directement par son URI (comme avec PUT), avec juste le diffĂ©rentiel d’informations. Avec POST, il faut passer par une URI tierce, qu’on appellera un handler, une action, un processus, etc. qui lui prendra la demande en charge et inventera un sens contextualisĂ© pour POST. Et ce mĂȘme si nous connaissons l’URI de l’entitĂ© Ă  modifier ! Il n’y a pas moyen… enfin c’Ă©tait le cas jusqu’en 2010.

Heureusement, Ă  partir de cette annĂ©e lĂ , la RFC5789 a introduit un nouveau verbe : PATCH. Le gros avantage, c’est qu’on peut dĂ©sormais « patcher » une entitĂ©, c’est Ă  dire la modifier partiellement quand on connait son URI. L’inconvĂ©nient, d’aprĂšs moi, c’est que POST perd un rĂŽle qui Ă©tait clair et se retrouve Ă  prendre « le reste », ce que les autres verbes ne prendront pas par soucis de respect de leur sens.

Alors si tout cela est une histoire de sĂ©mantique, pourquoi n’imposerions-nous pas les rĂŽles des diffĂ©rents verbes HTTP pour que nos APIs soient plus claires ?

Le rÎle central de la sémantique

Dans le protocole HTTP, la sémantique a un rÎle déterminant sur la maniÚre dont les différents éléments (matériels ou logiciels) doivent agir.

La respecter implique de :

  • s’assurer que les autres Ă©lĂ©ments soient cohĂ©rents dans leur maniĂšre d’agir et que nous n’obtiendrons pas des rĂ©sultats aberrants.
  • permettre que n’importe quel Ă©lĂ©ment insĂ©rĂ© qui touchera Ă  des requĂȘtes ou rĂ©ponses HTTP puisse agir de maniĂšre performante et optimisĂ©e. La RFC fourmille de suggestions sur ce que devraient faire ou ne pas faire les proxies, par exemple.

La discoverability est un aspect intéressant des APIs REST, qui se base sur le formalisme des éléments du protocole.

La discoverability est la qualitĂ© d’une API Ă  pouvoir ĂȘtre dĂ©couverte par un client Ă  partir d’indices sĂ©mantiques. Si vous avez entendu parler de « web sĂ©mantique », vous avez une bonne idĂ©e de comment permettre la discoverability dans une API. L’idĂ©e est de dĂ©couvrir les URIs de l’API Ă  partir d’une ressource rĂ©fĂ©rence et de leur donner des rĂŽles

Comment ? Je vous conseille de lire REST : Richardson Maturity Model qui lui-mĂȘme fait rĂ©fĂ©rence Ă  Richardson Maturity Model (par Martin Fowler). Vous y trouvez, au niveau 3 du Richardson Maturity Model, des exemples concrets qui montrent comment dans REST, une ressource permet d’en dĂ©couvrir d’autres.

La sĂ©mantique complĂšte n’est donc pas portĂ©e par les seuls verbes : les headers la modulent, la sĂ©mantique des liens (leur rĂŽle) la prĂ©cisent.

Les verbes HTTP donnent donc un sens trĂšs formel, qui devrait ĂȘtre prĂ©cisĂ©. Mais comment crĂ©er une sĂ©mantique applicative cohĂ©rente si le sens premier des verbes n’est pas respectĂ© ?

Si vos APIs ne sont pas RESTful (ce qui est le cas de 98% des APIs qui se disent RESTful), il reste nĂ©cessaire de respecter le minimum de sens portĂ© par les verbes HTTP pour tirer parti au maximum de l’architecture induite.

Le sens minimaliste intrinsĂšque des verbes HTTP (indĂ©pendamment de la sĂ©mantique donnĂ©e par les ressources) est actuellement un standard respectĂ© largement : le simple fait de naviguer sur le web, c’est utiliser une « API » RESTful.

Si le respect du standard semble dĂ©jĂ  une bonne raison, nous pourrions Ă©galement ajouter les conventions qui rendent le dĂ©veloppement, la maintenance et la communication autour d’une application possible : vous viendrait-il Ă  l’esprit de crĂ©er une classe Java avec des getters dont le prĂ©fixe est « set » ou des setters dont le prĂ©fixe est « get » ? Pourtant me direz-vous, il suffit de le prĂ©ciser dans la javadoc… Avec les verbes HTTP, c’est pareil. Il est possible de faire n’importe quoi et de le documenter, mais mieux vaut garder les conventions Ă©tablies par les RFCs et dĂ©jĂ  respectĂ©es par ailleurs.

Impact sur les APIs HTTP

Maintenant que nous sommes convaincus que la diffĂ©rence PUT/POST n’est pas une simple vue de l’esprit, que faire ?

Nous distinguerons les simples APIs HTTP, qui ont l’inconvĂ©nient d’avoir le client liĂ© Ă  l’organisation des ressources sur le serveur, et les APIs RESTful, qui bĂ©nĂ©ficient du dĂ©couplage permis par les hypermedias.

APIs HTTP

Si vous avez des API exposĂ©es Ă  l’extĂ©rieur qui ne respecteraient pas la norme, voyez si vous pouvez assurer une migration en profitant d’un refactoring ou d’une rĂ©organisation des applicatifs clients. Si aucune occasion se prĂ©sente, il est peu probable que votre client accepte de changer la maniĂšre de consommer votre API juste parce que vous avez ignorĂ© la RFC.

Par contre, n’hĂ©sitez pas Ă  introduire le nouveau formalisme pour toute nouvelle ressource exposĂ©e, mĂȘme dans des API existantes. Vous Ă©duquerez les dĂ©veloppeurs au plus tĂŽt sur la nouvelle maniĂšre de faire sans perturber les consommateurs des ressources existantes.

APIs RESTful

Si vous avez optĂ© pour du RESTful, vous devriez rencontrer moins de problĂšmes. MĂȘme si le dĂ©couplage permis par l’architecture REST vous permet de changer pas mal de chose cĂŽtĂ© serveur sans perturber le client, voyez au cas par cas si

  • le client consomme bien votre API de maniĂšre RESTful
  • la ressource permet de changer facilement le verbe (exemple : la mĂ©thode pour accĂ©der Ă  une ressource liĂ©e est prĂ©cisĂ©e dans la ressource parente)

J’ai conscience que peu de gens imaginent la flexibilitĂ© rĂ©elle d’une API RESTful, et qualifient Ă  tort une simple API HTTP de RESTful, je vous conseille donc la visualisation de Building Hypermedia APIs with HTML (Jon Moore). Cette vidĂ©o qui sort largement du cadre de la confusion PUT/POST nous montre une mise en Ɠuvre d’une API RESTful. Une autre vidĂ©o de l’auteur montrant la mise en Ɠuvre d’une API RESTful avec des documents XHTML a Ă©tĂ© supprimĂ©e de VimĂ©o, mais le court article Thoughts on hypermedia apis donne l’esprit original. Quel que soit la vidĂ©o, on y voit comment REST permet de dĂ©-corrĂ©ler le client et la structure des ressources cotĂ© serveur.

Conclusion

Nous avons donc vu que le mapping CRUD ⟷ verbes HTTP n’existait pas, et que PUT et POST avaient chacun leurs rĂŽles bien dĂ©finis. Bien qu’en pratique il sera plus facile de crĂ©er une ressource avec POST, il faudra bien veiller Ă  ce que le POST crĂ©e une ressource liĂ©e dont il retournera l’uri (Header Location) et Ă  ne pas oublier qu’implĂ©menter la crĂ©ation avec PUT reste possible. Si crĂ©er avec PUT est possible, faites-le car c’est plus naturel (URI ressource ressource crĂ©Ă©e = URI de la requĂȘte PUT).

Nous avons vu que le respect de la distinction PUT/POST avait une influence sur la gestion des flux rĂ©seau, et sur le design des APIs. Également, le rĂŽle de POST est beaucoup plus flou et « free style » depuis l’apparition de PATCH. L’idĂ©al serait donc d’utiliser PATCH pour les mises Ă  jour partielles, PUT pour les crĂ©ations et mises Ă  jour complĂštes, et POST pour les crĂ©ations complĂštes lorsque PUT n’est pas possible ainsi que tout ce qui n’est pas faisable avec les autres verbes. Le mapping CRUD ↔ verbes HTTP semble inutile, car en suivant les RFCs on aboutit toujours Ă  quelque chose de juste. Il suffit juste de s’interroger, avant chaque usage de POST, si un autre verbe ne collerait pas mieux. Et si ce n’est pas le cas, et bien… utilisons POST !

Enfin nous avons entraperçu un sujet parallĂšle, Ă  savoir que quasiment personne prĂ©tendant faire du REST n’en fait vraiment, alors que les avantages sont Ă©vidents (dĂ©couplage libĂ©rant le serveur de contraintes empĂȘchant l’Ă©volution et permettant au client de ne pas ĂȘtre impactĂ© par chaque ajustement cĂŽtĂ© serveur).

Catégories: Blog Société

API Stream – Une nouvelle façon de gĂ©rer les Collections en Java 8

Blog d’Ippon Technologies - lun, 03/17/2014 - 09:30
Pour l’Ă©vĂšnement de la sortie de Java 8, Ippon vous propose plusieurs posts sur les nouveautĂ©s du langage. A lire Ă©galement :

Jusqu’à prĂ©sent, effectuer des traitements sur des Collections ou des tableaux (de type MapReduce) en Java passait essentiellement par l’utilisation du pattern Iterator. Java 8 nous propose l’API Stream pour simplifier ces traitements en introduisant un nouvel objet, Stream.

Un stream se construit Ă  partir d’une source de donnĂ©es (une collection, un tableau ou des sources I/O par exemple), et possĂšde un certain nombre de propriĂ©tĂ©s spĂ©cifiques :

  • Un stream ne stocke pas de donnĂ©es, contrairement Ă  une collection. Il se contente de les transfĂ©rer d’une source vers une suite d’opĂ©rations.

  • Un stream ne modifie pas les donnĂ©es de la source sur laquelle il est construit. S’il doit modifier des donnĂ©es pour les rĂ©utiliser, il va construire un nouveau stream Ă  partir du stream initial. Ce point est trĂšs important pour garder une cohĂ©rence lors de la parallĂ©lisation du traitement.

  • Le chargement des donnĂ©es pour des opĂ©rations sur un stream s’effectue de façon lazy. Cela permet d’optimiser les performances de nos applications. Par exemple, si l’on recherche dans un stream de chaĂźnes de caractĂšres une chaĂźne correspondant Ă  un certain pattern, cela nous permettra de ne charger que les Ă©lĂ©ments nĂ©cessaires pour trouver une chaĂźne qui conviendrait, et le reste des donnĂ©es n’aura alors pas Ă  ĂȘtre chargĂ©.

  • Un stream peut ne pas ĂȘtre bornĂ©, contrairement aux collections. Il faudra cependant veiller Ă  ce que nos opĂ©rations se terminent en un temps fini – par exemple avec des mĂ©thodes comme limit(n) ou findFirst( ).

  • Enfin, un stream n’est pas rĂ©utilisable. Une fois qu’il a Ă©tĂ© parcouru, si l’on veut rĂ©utiliser les donnĂ©es de la source sur laquelle il avait Ă©tĂ© construit, nous serons obligĂ©s de reconstruire un nouveau stream sur cette mĂȘme source.

Il existe deux types d’opĂ©rations que l’on peut effectuer sur un stream : les opĂ©rations intermĂ©diaires et les opĂ©rations terminales.

Les opĂ©rations intermĂ©diaires (Stream.map ou Stream.filter par exemple) sont effectuĂ©es de façon lazy et renvoient un nouveau stream, ce qui crĂ©e une succession de streams que l’on appelle stream pipelines. Tant qu’aucune opĂ©ration terminale n’aura Ă©tĂ© appelĂ©e sur un stream pipelines, les opĂ©rations intermĂ©diaires ne seront pas rĂ©ellement effectuĂ©es.

Quand une opĂ©ration terminale sera appelĂ©e (Stream.reduce ou Stream.collect par exemple), on va alors traverser tous les streams crĂ©Ă©s par les opĂ©rations intermĂ©diaires, appliquer les diffĂ©rentes opĂ©rations aux donnĂ©es puis ajouter l’opĂ©ration terminale. DĂšs lors, tous les streams seront dit consommĂ©s, ils seront dĂ©truits et ne pourront plus ĂȘtre utilisĂ©s.

       List<String> strings = Arrays.asList("girafe", "chameau", "chat", "poisson", "cachalot");

       strings.stream()
               // filtrage

               .filter(x -> x.contains("cha"))
               // mapping : reformatage des chaĂźnes de caractĂšres

               .map(x -> x.substring(0, 1).toUpperCase() + x.substring(1))
               // tri par ordre alphabétique

               .sorted()
               // Outputs:

               // Cachalot

               // Chameau

               // Chat

               .forEach( System.out::println );

Exemple simple de traitement de Collection avec un Stream CrĂ©ation d’un stream

On peut créer un stream de plusieurs façons. La plus simple consiste à appeler la méthode stream() ou parallelStream() sur une collection, mais un certain nombre de méthodes ont été ajoutées aux classes déjà existantes.

Notons ainsi la mĂ©thode chars() de la classe String, qui renvoie un IntStream construit sur les diffĂ©rents caractĂšres de la chaĂźne de caractĂšres, ou encore la mĂ©thode lines() de la classe BufferedReader qui crĂ©e un stream de chaĂźnes de caractĂšres Ă  partir des lignes du fichier ouvert. À la classe Random s’ajoute aussi une mĂ©thode intĂ©ressante, ints(), qui renvoie un stream d’entiers pseudo alĂ©atoires.

L’API propose Ă©galement des mĂ©thodes statiques au sein de la classe Stream. Par exemple, le code suivant : “Stream.iterate(1, x -> x*2)” renverra un stream infini d’entiers contenant la suite des puissances de 2. Le premier argument contient la valeur initiale du stream, et le deuxiĂšme la fonction permettant de passer de l’élĂ©ment n Ă  l’élĂ©ment n+1 dans le stream.

Parallélisation

L’un des points forts de cette nouvelle API est de nous permettre de parallĂ©liser nos traitements de façon particuliĂšrement aisĂ©e. En effet, n’importe quel stream peut ĂȘtre parallĂ©lisĂ© en appelant sa mĂ©thode parallel() hĂ©ritĂ©e de l’interface BaseStream – de la mĂȘme façon, un stream peut ĂȘtre rendu sĂ©quentiel en invoquant la mĂ©thode sequential(). On peut Ă©galement construire un stream parallĂšle sur une collection directement en appelant la mĂ©thode parallelStream() sur cette collection.

Ces mĂ©thodes nous permettent de masquer la rĂ©partition du travail, mais ne doivent pas ĂȘtre prises Ă  la lĂ©gĂšre : en essayant de gagner en performance en parallĂ©lisant n’importe quel traitement, on prend le risque de produire l’effet inverse (nous y reviendrons plus tard).

Opérations intermédiaires

Les opĂ©rations intermĂ©diaires peuvent ĂȘtre stateful ou stateless. Les opĂ©rations stateless effectuent un traitement sur les Ă©lĂ©ments du stream un Ă  un sans avoir Ă  prendre en compte les autres Ă©lĂ©ments du stream.

List<Commande> mesCommandes = 
 ;

List<Client> mesClients = mesCommandes.stream()
     .map( c -> c.getClient() )
     .collect( Collectors.toList() );

collect permet ici simplement de stocker le résultat dans une liste

Les opĂ©rations stateful quant Ă  elles, ont gĂ©nĂ©ralement besoin de connaĂźtre l’ensemble du stream pour donner un rĂ©sultat (par exemple Stream.distinct ou Stream.sorted). Par consĂ©quent, parallĂ©liser un tel traitement risque bien souvent de baisser nos performances au lieu de les amĂ©liorer.

List<Commande> mesCommandes = 
 ;

List<Client> mesClients = mesCommandes.stream()
     .map( c -> c.getClient() )
     .distinct()
     .collect( Collectors.toList() );

On renvoie la liste de nos clients, sans doublons, grùce à l'opération intermédiaire stateful distinct() Opérations terminales

Nous disposons de deux types de rĂ©ductions dans l’API Stream. Les opĂ©ration de rĂ©ductions simples et les rĂ©ductions mutables.

Les rĂ©ductions simples sont celles auxquelles on pourrait penser en premier lieu : La somme d’élĂ©ments (Stream.sum), le maximum (Stream.max), ou le nombre d’élĂ©ments (Stream.count) sont des rĂ©ductions simples. Dans sa forme gĂ©nĂ©rale, elle se dĂ©fini de la façon suivante :

<U> U reduce(U identity,

     BiFunction<U, ? super T, U> accumulator,

     BinaryOperator<U> combiner);

L’élĂ©ment identitĂ© est l’élĂ©ment initial pour la rĂ©duction (et l’élĂ©ment renvoyĂ© si le stream est vide). L’accumulator crĂ©e un nouveau rĂ©sultat partiel Ă  partir d’un rĂ©sultat partiel et d’un nouvel Ă©lĂ©ment, et le combiner crĂ©e un nouveau rĂ©sultat partiel Ă  partir de deux rĂ©sultats partiels.

Deux points sont à noter dans cette méthode :

  • Tout d’abord, l’identitĂ© doit ĂȘtre une identitĂ© au sens mathĂ©matique du terme pour la fonction combiner : combiner.apply(u, identity) doit ĂȘtre Ă©gal Ă  u quel que soit u.

  • La fonction combiner doit ĂȘtre associative. Cela est une nĂ©cessitĂ© pour ne pas obtenir de rĂ©sultat alĂ©atoire lors d’une parallĂ©lisation du travail.

La mĂ©thode sum peut donc ĂȘtre rĂ©Ă©crite en utilisant la mĂ©thode reduce :

List<Commande> mesCommandes = 
;

int chiffreAffaire = mesCommandes.stream()
     .reduce( 0, 
          (result, commande) -> result + commande.getPrice(),
          (resultA, resultB) -> resultA + resultB );

On peut réécrire la méthode sum() en utilisant la méthode reduce

Les rĂ©ductions mutables gĂ©nĂ©ralisent ce concept en accumulant les Ă©lĂ©ments d’un stream dans un container. Ce dernier peut ĂȘtre une Collection, un StringBuilder, ou mĂȘme un simple entier (auquel cas nous aurions affaire Ă  une rĂ©duction simple).

<R> R collect(Supplier<R> supplier,

     BiConsumer<R, ? super T> accumulator,

     BiConsumer<R, R> combiner);

Nous retrouvons une syntaxe relativement similaire à la syntaxe de la méthode reduce. Cette fois-ci nous devons cependant initialiser un container (supplier), puis définir la méthode accumulator qui ajoutera un élément à un container, et enfin la méthode combiner qui créera un nouveau container à partir de deux container temporaires.

Afin de simplifier notre code, l’API Stream nous propose Ă©galement une autre classe, Collectors, qui encapsule les trois arguments nĂ©cessaire Ă  une rĂ©duction pour certaines opĂ©rations classiques (rĂ©cupĂ©ration des donnĂ©es dans une liste, une map ou un set, concatĂ©ner des chaĂźnes de caractĂšres
). On pourrait par exemple modifier notre code prĂ©cĂ©dent pour obtenir le mĂȘme rĂ©sultat :

List<Commande> mesCommandes = 
;

int chiffreAffaire = mesCommandes.stream()
     .collect( Collectors.summingInt( Commande::getPrice ) );
Conclusion

Cette nouvelle API fournie par le JDK 8 va donc modifier fondamentalement notre façon de traiter les Collections en nous proposant une alternative au pattern Iterator relativement lourd à mettre en place. Celle-ci tire profit de la nouvelle syntaxe des lambdas expressions pour réduire notre code un maximum tout en améliorant nos performances. De plus, la classe Collectors présentée succinctement ici nous offre de nombreux patterns qui remplaceront dans de nombreux cas le pattern Iterator.

Catégories: Blog Société

JVM Hardcore – Part 19 – Bytecode – Comparaisons et contrîle – 3/3

JVM Hardcore - Part 19 – Bytecode – Comparaisons et contrîle - 3/3
Au cours des parties 1/3 et 2/3, nous avons Ă©tudiĂ© en dĂ©tail le fonctionnement de 25 instructions de comparaisons et de contrĂŽle. Aujourd’hui, nous allons nous intĂ©resser Ă  leur implĂ©mentation dans PJBA tout aussi bien au niveau des builders, des...
Catégories: Blog Société

MapReduce et les grilles de données ou Hadoop sans Hadoop

Blog d’Ippon Technologies - ven, 03/14/2014 - 14:00

Dans cet article nous allons Ă©tudier la possibilitĂ© d’exĂ©cuter des tĂąches MapReduce en dehors d’Hadoop.

En particulier nous allons étudier les possibilités offertes par les grilles de données open source Java.

Introduction

L’impression actuelle est que tous les Ă©diteurs veulent prendre le train Hadoop en route et se positionnent sur ce marchĂ© quitte Ă  brouiller l’image de leur produit et la nĂŽtre par la mĂȘme occasion :

  • ETL, bases de donnĂ©es, caches, BI, la liste est longue.

Parmi ces initiatives il y a donc les grilles de données mémoire qui proposent des API MapReduce.

Les solutions étudiées :

  • Hazelcast qui propose une API MapReduce depuis la version 3.2
  • Infinispan qui propose une API MapReduce depuis la version 5.2

D’autres solutions de type NoSQL ou grilles de donnĂ©es mĂ©moire font un rapprochement avec Hadoop mais elles sont hors contexte car elles ne visent pas Ă  remplacer complĂštement Hadoop mais Ă  le complĂ©ter :

C’est le cas des produits suivants :

  • Cassandra, Coherence, Terracotta…

Par exemple avec Cassandra il est possible d’exĂ©cuter des jobs MapReduce avec en entrĂ©e des donnĂ©es Cassandra et de stocker les rĂ©sultats dans Cassandra (ou dans un File System).

Cette solution exige toutefois la mise en place d’un cluster Hadoop (dans ce cas Cassandra remplace HBase comme solution NoSQL).

A l’opposĂ© avec Terracotta les donnĂ©es sont extraites d’Hadoop (HDFS) pour traitement et le rĂ©sultat final est stockĂ© dans Hadoop (mais peut ĂȘtre consultĂ© dans Terracotta).

De plus d’autres solutions comme MongoDB proposent aussi une API MapReduce mais ce ne sont pas des solutions Java (MongoDB est Ă©crit en C++ et on code les fonctions MapReduce en JavaScript).

Enfin il existe depuis peu Apache Spark qui est une grille de calcul mémoire qui peut fonctionner avec ou sans Hadoop.

Mais Spark est encore un peu jeune et mĂ©riterait un article Ă  lui tout seul : c’est pourquoi il n’est pas Ă©tudiĂ© ici.

Présentation Hazelcast et Infinispan

Hazelcast et Infinispan sont des grilles de données mémoire (In Memory Data Grid) open source (Licence Apache) qui permettent le stockage et le traitement de données réparties dans un cluster.

Fonctionnalités communes :

  • Écrit en Java,
  • Caches locaux et distribuĂ©s,
  • Clients natifs pour les langages Java, C#, …
  • API Rest, memcache,
  • DĂ©couverte automatique des membres,
  • Failover automatique (un crash d’un nƓud ne met pas en pĂ©ril les donnĂ©es),
  • Support des transactions et des locks,

Liste des cas d’utilisations :

  • Cache de service,
  • Cache L2,
  • Cache de sessions HTTP,

Licence : Open source, LGPL.

Les derniÚres versions :

  • Infinispan 6.0 (novembre 2013)
  • Hazelcast 3.2 RC1 (fĂ©vrier 2014)

Infinispan est plus ancien et bĂ©nĂ©ficie du support de RedHat mais Hazelcast compte dans ses rangs des noms prestigieux dans l’Ă©cosystĂšme Java :

  • Rod Johnson, crĂ©ateur de Spring, au comitĂ© exĂ©cutif.
  • Greg Luck crĂ©ateur d’Ehcache en tant que CTO.

Les grilles de donnĂ©es mĂ©moire proposent dĂ©jĂ  des traitements distribuĂ©s sous des dĂ©nominations parfois diffĂ©rentes : EntryProcessor, ExecutorService, Distributed task, 


Mais offrant toutes la mĂȘme fonctionnalité : faire exĂ©cuter les traitements Ă  l’endroit mĂȘme oĂč sont stockĂ©es les donnĂ©es plutĂŽt que de rapatrier les donnĂ©es pour les traiter.

Un traitement est en charge de la bonne exĂ©cution et de l’agrĂ©gation des rĂ©sultats.

Nous allons donc Ă©tudier l’intĂ©rĂȘt de l’implĂ©mentation MapReduce des grilles de donnĂ©es vis Ă  vis d’Hadoop mais aussi par rapport aux traitements distribuĂ©s dĂ©jĂ  offerts par ces solutions.

ImplĂ©mentations MapReduce Rappel de l’implĂ©mentation Map Reduce d’Hadoop

MapReduce

Cinq phases distinctes constituent l’algorithme MapReduce (pour rappel les donnĂ©es sont stockĂ©es dans le systĂšme de fichiers HDFS sous la forme clĂ©/valeur).

  1. Phase de prĂ©paration : Les nƓuds contenant les donnĂ©es concernĂ©es sont identifiĂ©es (stockage HDFS).
  2. Phase Map (calcul) : Pour chaque ensemble le traitement Map est appliqué.
  3. Phase Shuffle : Les donnĂ©es sont triĂ©es et les donnĂ©es liĂ©es sont regroupĂ©es pour ĂȘtre traitĂ©es par un mĂȘme nƓud.
  4. Phase Reduce (agrégation) : Les données sont éventuellement agrégées.
  5. Phase finale : Les rĂ©sultats de chacun des nƓuds sont regroupĂ©s et triĂ©s pour stockage et/ou restitution.

NB : La phase « combiner » qui est sommairement une phase de Reduce en mémoire a été volontairement omise pour simplifier la compréhension.

Ces cinq phases ne sont pas obligatoirement strictement sĂ©quentielles dans la mesure ou une phase peut dĂ©marrer avant la fin complĂšte de la phase prĂ©cĂ©dente (sous rĂ©serve de la disponibilitĂ© des donnĂ©es et de l’absence d’impact sur le rĂ©sultat final).

HDFS_MapReduce

Ensuite un jobTracker est en charge de la supervision de l’ensemble des traitements confiĂ©s aux diffĂ©rents nƓuds (taskTracker).

JobTraker

Il serait toutefois injuste de ne pas aborder la derniĂšre Ă©volution, Ă  savoir YARN.

YARN est une refonte complÚte de MapReduce afin de répondre aux limitations majeures de la premiÚre version :

  • AmĂ©liorer la scalabilitĂ© et la disponibilitĂ©.
  • Étendre MapReduce (et faciliter l’introduction de traitements temps rĂ©el).

Scalabilité : Une partie de la gestion des tĂąches est maintenant gĂ©rĂ©e par les nƓuds de data (nƓuds secondaires).

De plus il n’y a plus d’affectation de rĂŽle aux slots de calculs (un nƓud devait ĂȘtre configurĂ© pour utiliser n slots dĂ©diĂ©s aux taches Map et m slots dĂ©diĂ©s aux tĂąches Reduce).

Disponibilité : Suppression des SPOF (Single Point Of Failure) que pouvaient ĂȘtre le NameNode et le jobTracker (ce dernier est sĂ©parĂ© en deux).

Temps rĂ©el : La rĂ©ponse au besoin temps rĂ©el n’est pas directement adressĂ©e par YARN.

Mais ce dernier offre la possibilitĂ© d’aller au delĂ  du framework MapReduce et donc d’intĂ©grer des paradigmes moins axĂ©s batch.

Par exemple :

  • Traitement de flux de donnĂ©es massif comme Storm ou Apache S4 (streaming),
  • Traitement in-memory comme Apache Spark (qui peut aussi faire du streaming).

YARN permet l’intĂ©gration entre Hadoop et ces solutions qui bĂ©nĂ©ficieront des avantages de la plateforme comme la scalabilitĂ©.

Infinispan

Pour son implĂ©mentation MapReduce, Infinispan s’est basĂ© sur la publication originale de Google.

Quatre composants permettent de définir une tache MapReduce :

  • Mapper,
  • Reducer,
  • Collator,
  • MapReduceTask.

Mapper : Comme son nom l’indique il s’agit de l’Ă©quivalent de la phase Map d’Hadoop
Reducer : Comme son nom l’indique il s’agit de l’Ă©quivalent de la phase Reduce d’Hadoop
Collator : C’est une Ă©tape supplĂ©mentaire par rapport Ă  Hadoop dans la mesure oĂč elle permet Ă  l’utilisateur de dĂ©finir une fonction qui va traiter les rĂ©sultats des tĂąches MapReduce
MapReduceTask : il s’agit du composant en charge de l’ordonnancement des traitements.

Un dĂ©veloppeur Hadoop reconnaĂźtra un systĂšme trĂšs familier dans l’implĂ©mentation d’Infinispan. MĂȘme si il y a une phase supplĂ©mentaire dans l’implĂ©mentation Infinispan (en tout cas une Ă©tape sur laquelle l’utilisateur peut intervenir contrairement Ă  Hadoop).

Particularités propres à Infinispan :

  • Timeout sur la durĂ©e des taches.
  • Le locking est automatiquement gĂ©rĂ©.
  • Les donnĂ©es en entrĂ©es et en sorties sont des caches.
  • Tout comme Infinispan, MapReduce est compatible avec CDI.
  • Avec Infinispan il est possible d’indiquer que l’on souhaiterait distribuer les tĂąches de type Reduce au sein du cluster (attribut distributeReducePhase lors de la crĂ©ation d’une tĂąche MapReduce).
  • Il est aussi possible d’indiquer Ă  Infinispan d’utiliser un cache pour le stockage des rĂ©sultats intermĂ©diaires (useIntermediateSharedCache), cette option est plus lente mais utile pour le dĂ©bogage (le cache utilisĂ© s’appelle alors __tmpMapReduce).

A noter qu’une Ă©volution importante est annoncĂ©e avec la version 7 d’Infinispan, les Ă©tapes Map et Reduce ne sont plus mono-thread mais basĂ©es sur un pool de threads consommant les tĂąches Ă  accomplir. De grandes amĂ©liorations sont attendues au niveau de la performance.

Hazelcast

La premiÚre implémentation MapReduce dans Hazelcast était basée sur CastMapR, elle a été récemment entiÚrement revue et intégrée de maniÚre officielle.

La nouvelle implĂ©mentation s’inspire de celle d’Infinispan et comme cette derniĂšre toutes les taches sont parallĂšles et s’inspire donc plutĂŽt de YARN que de MapReduce.

Quatre composants permettent de définir une tùche MapReduce :

  • Mapper,
  • Reducer,
  • Collator,
  • JobTracker.

Mapper : Comme son nom l’indique il s’agit de l’Ă©quivalent de la phase Map d’Hadoop
Reducer : Comme son nom l’indique il s’agit de l’Ă©quivalent de la phase Reduce d’Hadoop
Collator : C’est une Ă©tape d’agrĂ©gation des rĂ©sultats avec Ă©ventuellement un traitement global du rĂ©sultat produit par MapReduce
JobTracker : il s’agit du composant en charge de l’ordonnancement des traitements.

Particularités propres à Hazelcast :

  1. La clĂ© et la valeur des entrĂ©es du cache peuvent ĂȘtre de n’importe quel type.
  2. Le locking est automatiquement géré.
  3. Les données en entrée et en sortie sont des caches.
  4. L’interface JobProcessInformation permet d’obtenir des statistiques sur les traitements MapReduce (Ă©tat des partitions, nombre d’enregistrements traitĂ©s, 
).
  5. PossibilitĂ© de dĂ©finir une stratĂ©gie en cas de changement de la topologie (perte de nƓuds pouvant entraĂźner la perte de donnĂ©es).

A noter qu’une Ă©volution importante est annoncĂ©e : Continuous MapReduce.

Il s’agit en fait de l’intĂ©gration des « continuous Query » avec MapReduce.

Les Continuous Query sont des fonctionnalitĂ©s classiques des grilles de donnĂ©es mĂ©moire, elles permettent Ă  un client d’effectuer une requĂȘte sur la grille de donnĂ©es et de recevoir automatiquement les nouvelles donnĂ©es qui pourraient avoir Ă©tĂ© insĂ©rĂ©es.

Cette fonctionnalité est un pas de plus vers le streaming MapReduce.

Schéma de synthÚse

IMDG_MR Avantages de l’implĂ©mentation MapReduce des Grilles de donnĂ©es

Le principal avantage est Ă©videmment la mĂ©moire. Toutes les donnĂ©es sont traitĂ©es en mĂ©moire ce qui garantit des performances accrues par rapport Ă  HDFS (on annonce des performances jusqu’Ă  100 fois plus rapides).

L’autre avantage est que les tĂąches Map et Reduce peuvent ĂȘtre exĂ©cutĂ©es en parallĂšle ce qui est rarement le cas avec Hadoop. C’est pourquoi une Ă©tape supplĂ©mentaire existe dans les implĂ©mentations des IMDG.

Enfin un des apports des grilles de donnĂ©es est la scalabilitĂ© (dĂ©couverte automatique des nƓuds) : mĂȘme si Hadoop est par dĂ©finition scalable, il est loin d’atteindre le cotĂ© “plug and play” de ces solutions.

On pourra ajouter ou supprimer un nƓud qui sera automatiquement pris en compte (sans la phase de dĂ©claration d’Hadoop) pour les traitements.

Il est mĂȘme possible de modifier la topologie du cluster pendant un traitement.

Les grilles de données sont plus simple à mettre en oeuvre du fait de leur architecture réduite.

En effet, a minima, une plateforme Hadoop va intégrer :

  • MapReduce : Framework de traitement des donnĂ©es
  • HBase : Ajoute du NoSQL et des transaction Ă  Hadoop
  • Zookeeper : Gestion centralisĂ©e de la configuration  et coordination des services
  • HDFS : SystĂšme de stockage des donnĂ©es (SystĂšme de fichiers distribuĂ©s)

+ Un outil d’interrogation :

  1. Hive (Interrogation de type SQL)
  2. Pig  (Langage de haut niveau)

+ Un outil de monitoring :

  • Cloudera manager.
  • Apache Ambari.

Une autre différence importante entre Hadoop et les grilles de données est le cycle de vie des données.

Avec les grilles, les donnĂ©es sont stockĂ©es en mĂ©moire et peuvent changer, avec Hadoop (HDFS) les donnĂ©es sont figĂ©es (les blocks de donnĂ©es peuvent ĂȘtre amendĂ©s mais pas mis Ă  jour).

De plus les grilles supportent le versioning des données (les données ont alors un historique) alors que MapReduce, Storm, Spark ne gÚrent pas le modÚle de données.

Toutefois signalons que le streaming est une vraie valeur ajoutĂ©e des grilles de donnĂ©es mĂ©moire mais il n’est pas encore mis en oeuvre.

Enfin les implĂ©mentations sont trĂšs proches d’Hadoop ce qui facilite la montĂ©e en compĂ©tence pour des dĂ©veloppeurs dĂ©jĂ  formĂ©s Ă  Hadoop.

Inversement une pratique des mĂ©canismes MapReduce des grilles de donnĂ©es peut ĂȘtre vue comme une premiĂšre Ă©tape vers une future adoption d’Hadoop au sein du SI.

Il est donc possible de capitaliser malgrĂ© les diffĂ©rences d’implĂ©mentation.

CONCLUSION CritÚres de choix traitements distribués vs MapReduce Quels sont les avantages, les différences avec les traitements distribués ?

MapReduce est préférable :

  1. Si plusieurs sources de données sont concernées ou bien la source est des données est différente du cache.
  2. Si justement le traitement ne consiste pas uniquement Ă  effectuer des calculs mais Ă  agrĂ©ger/trier les rĂ©sultats (le fameux Word Count en est l’exemple typique).

Traitements distribués préférables :

  1. Traitements simples et unitaires fortement liés à la donnée.

L’algorithme MapReduce offre une nouvelle possibilitĂ© de traitement distribuĂ© aux grilles de calculs mĂ©moire.

CritĂšres de choix traitements MapReduce (Grilles de donnĂ©es vs Hadoop) Quelles sont les avantages, les diffĂ©rences avec l’implĂ©mentation Hadoop ?

Cas d’utilisation MapReduce (Hadoop) :

  1. Volumétrie (péta-octets).
  2. Persistance des données.
  3. Besoin d’analyse des donnĂ©es poussĂ©e (Mahout, …).

Cas d’utilisation MapReduce (grilles de donnĂ©es) :

  1. VolumĂ©trie (relativement) faible : jusqu’Ă  1 To.
  2. Expériences grilles de données et envie de capitaliser sur cette technologie.
  3. Besoin de performances (calcul) et de latence faible (disponibilité des résultats).

L’implĂ©mentation MapReduce des grilles de donnĂ©es apporte une possibilitĂ© supplĂ©mentaire, ce n’est Ă©videmment pas un remplacement d’Hadoop.

Il est Ă©vident que la capacitĂ© d’une grille de donnĂ©es mĂ©moire ne peut rivaliser avec celle d’un cluster Hadoop, car la capacitĂ© mĂ©moire d’une machine ne peut concurrencer les capacitĂ©s disques.

Une capacitĂ© d’un tĂ©ra-octet est dĂ©jĂ  une limite haute pour une grille de donnĂ©es mĂ©moire (soit un cluster de 15 serveurs).

Un cluster Hadoop est tout à fait capable de traiter des péta-octet.

Mais dans certains cas il apporte une plus value car la montée en compétence et la conduite du changement est moins forte que pour Hadoop (déploiement et administration simplifiée).

Exemple complet (Infinispan) :

Voici un exemple avec le fameux “word count” :

Dans cet exemple nous allons comptabiliser le nombre d’occurrences de chacun des mots dans un texte et afficher le mot apparaissant le plus souvent.

Ici seul un nƓud Infinispan est dĂ©marrĂ©, vous pouvez Ă©videmment en lancer d’autres pour un exemple plus rĂ©aliste.

La librairie “LoremIpsum” est utilisĂ©e pour la gĂ©nĂ©ration du texte.

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.distexec.mapreduce.Collator;
import org.infinispan.distexec.mapreduce.Collector;
import org.infinispan.distexec.mapreduce.MapReduceTask;
import org.infinispan.distexec.mapreduce.Mapper;
import org.infinispan.distexec.mapreduce.Reducer;
import org.infinispan.eviction.EvictionStrategy;
import org.infinispan.manager.DefaultCacheManager;

import de.svenjacobs.loremipsum.LoremIpsum;

public class WordCountExample {

    private static int MAX_ENTRIES = 1000;

    private static String CACHE_NAME = "WordsList";

    private static final Log log = LogFactory.getLog(WordCountExample.class);

    private static Cache<Integer, String> wordsListCache = null;
	public static void main(String[] args) throws IOException {

		/** Configure ISPN */
		GlobalConfiguration globalConfig = new GlobalConfigurationBuilder()
			.transport().clusterName("ISPN-MR").transport()
			.defaultTransport()
			.addProperty("configurationFile", "jgroups-tcp.xml").build();

		DefaultCacheManager manager = new DefaultCacheManager(globalConfig);

		/** Define custom cache */
		manager.defineConfiguration(
			CACHE_NAME,
			new ConfigurationBuilder().eviction()
				.strategy(EvictionStrategy.LIRS)
				.maxEntries(MAX_ENTRIES).clustering()
				.cacheMode(CacheMode.DIST_SYNC).build());
		manager.start();
		wordsListCache = manager.getCache(CACHE_NAME);

		wordsListCache.start();

		/** Put words to count into the cache */
		feedCache(MAX_ENTRIES / 10);

		/** Create Map Reduce Task masterCacheNode, distributeReducePhase, useIntermediateSharedCache */
		MapReduceTask<Integer, String, String, Integer> t = new MapReduceTask<Integer, String, String, Integer>(
			wordsListCache, true, true);

		/** Define Mapper and Reducer */
		t.mappedWith(new WordCountMapper()).reducedWith(new WordCountReducer());

		/** Define Collator */
		String[] mostFrequentWord = t
			.execute(new Collator<String, Integer, String[]>() {

			    @Override
			    public String[] collate(Map<String, Integer> reducedResults) {
					String mostFrequent = "";
					Integer maxCount = 0;
						for (Entry<String, Integer> e : reducedResults
							.entrySet()) {
						    Integer count = e.getValue();
						    if (count > maxCount) {
							maxCount = count;
							mostFrequent = e.getKey();
						    }
					}
					return new String[] { mostFrequent, maxCount.toString() };
			    }

		});

		log.info("The most frequent word is '" + mostFrequentWord[0]
			+ "' which appears " + mostFrequentWord[1] + " times.");
		manager.stop();
	}

	    static class WordCountMapper implements
		    Mapper<Integer, String, String, Integer> {
			private static final long serialVersionUID = -5943370243108735560L;

			@Override
			public void map(Integer key, String value, Collector<String, Integer> c) {
			    StringTokenizer tokens = new StringTokenizer(value);
			    log.debug("Key : " + key + ", Value : " + value);
			    while (tokens.hasMoreElements()) {
					String s = (String) tokens.nextElement();
					c.emit(s, 1);
			    }
			}
	    }

	    static class WordCountReducer implements Reducer<String, Integer> {
		private static final long serialVersionUID = 1901016598354633256L;

			@Override
			public Integer reduce(String key, Iterator<Integer> iter) {
			    int sum = 0;
			    while (iter.hasNext()) {
					Integer i = (Integer) iter.next();
					log.debug("Key : " + key + ", Value : " + i);
					sum += i;
			    }
			    return sum;
			}
	    }

	    public static String[] generateIpsum(int wordsToGenerate) {
			LoremIpsum loremIpsum = new LoremIpsum();
			String phrase = loremIpsum.getWords(wordsToGenerate);
			log.debug("Phrase : " + phrase);
			phrase = phrase.replaceAll(", ", " ");
			return phrase.split(" ");
	    }

	    public static void feedCache(int length) {
			String[] wordsArray = generateIpsum(length);

			for (Integer i = 1; i < wordsArray.length; i++) {
			    wordsListCache.put(i, wordsArray[i]);
			}
    	}    
}
Catégories: Blog Société

NightClazz Build Tools & Continuous Delivery - DĂ©couverte, le 3 avril au zlocalhost

Zenika - ven, 03/14/2014 - 14:00

AprĂšs la NigthClazz AngularJS AvancĂ© (vous trouverez les diffĂ©rents supports ici). Zenika vous propose d’assister Ă  la NightClazz Build Tools & Continuous Delivery - DĂ©couverte, le 3 avril prochain Ă  partir de 19h.

Au sein d’une dĂ©marche DevOps, le build et le dĂ©ploiement continue sont les premiers piliers Ă  mettre en place. Cette session dĂ©couverte de notre NighClazz “Build Tools & Continuous Delivery” a pour objectif de prĂ©senter les enjeux de l’automatisation, d’introduire les principaux outils de builds Java, de comprendre le mĂ©canisme de livraison... Read NightClazz Build Tools & Continuous Delivery - DĂ©couverte, le 3 avril au zlocalhost

Catégories: Blog Société

A la conquĂȘte des Tests A/B

Clever Age - Blog - jeu, 03/13/2014 - 14:42

Matthieu n'est pas du genre à prendre une décision à la légÚre, surtout lorsqu'elle risque d'avoir un impact sur le chiffre d'affaire de son entreprise. Il aime essayer avant d'adopter. C'est pourquoi il a décidé de se lancer dans les Tests A/B.

Une histoire de tests A/B

Matthieu n'est pas tatillon, loin de là, mais ses responsabilités et sa conscience professionnelle l'obligent à mesurer chaque évolution du site Internet de son entreprise, de maniÚre à assurer l'amélioration de l'ensemble des indicateurs clés à chaque livraison.

JPEG - 82.7 ko
"Questioned Proposal" par Ethan Lofton - CC BY 2.0

Mais parfois, il faut l'avouer, Matthieu ne sait pas. Il hésite. Il se pose des questions : cette fonctionnalité va-t-elle améliorer les choses ? Cette nouvelle façon de communiquer incitera-t-elle les clients à venir visiter le site ? Et ce nouveau tunnel de paiement, est-il vraiment plus performant que l'ancien ?

Les Tests A/B, c'est simple et objectif

Pour améliorer son processus de décision, il se renseigne et découvre une technique éprouvée sur les géants du Web : l'A/B Testing. Il lit consciencieusement la définition de Wikipedia et comprend immédiatement le principe, qui repose sur trois étapes :

  1. D'une part, il devra livrer les deux versions de sa fonctionnalité, diriger certains utilisateurs sur l'une, appelée version A et les autres sur l'autre, appelée version B ;
  2. d'autre part, il devra ĂȘtre capable de collecter des donnĂ©es sur l'expĂ©rience des utilisateurs sur les diffĂ©rentes versions. Pour Matthieu, cela implique d'adapter son plan de marquage analytique pour ĂȘtre capable de diffĂ©rencier les mesures issues des deux versions ;
  3. enfin, ce sera l'analyse de ces chiffres qui permettra à Matthieu de faire ressortir une vérité statistique concernant ces versions, déterminant ainsi la plus performante au regard des critÚres qu'il aura défini.

Confiant, Matthieu s'enquiert de quelques exemples pour convaincre sa Direction. Il découvre par exemple l'histoire incroyable mais vraie de Marissa Mayer (alors salariée de Google) qui demanda à ses équipes de déployer sur un site 41 variations de bleu pour déterminer la plus performante auprÚs des utilisateurs.

Si Google le fait, Matthieu devrait pouvoir le faire aussi. Et ça a mĂȘme l'air facile.

Les Tests A/B, c'est compliqué et subjectif

Matthieu réfléchit à l'implémentation concrÚte. Sa premiÚre contrainte est sa capacité à mettre en place les deux versions en simultané. C'est une contrainte forte pour Matthieu, qui réalise alors que de nombreux tests A/B lui seront impossibles : l'infrastructure de son entreprise est limitée, et il ne peut pas demander de nouveaux serveurs et passerelles pour étendre le schéma d'architecture à volonté.

Qu'à cela ne tienne, il décide de franchir le pas malgré tout et demande à son équipe de développement de le suivre sur un premier essai. Il choisit spécifiquement une modification qui ne nécessite pas de changement d'infrastructure : un variante visuelle au sein d'une page.

Il hĂ©site, puis dĂ©cide finalement de tester l'affichage de l'image produit sur le gabarit “Fiche Produit” du site e-commerce. La version courante, avec l'image produit Ă  gauche de sa description, sera considĂ©rĂ©e comme la version de contrĂŽle, la version A. Sur la version B, c'est une vidĂ©o du produit qui sera affichĂ©e. Depuis le temps que le dĂ©partement Marketing dit qu'il faut mettre davantage de vidĂ©o, il est temps de le vĂ©rifier !

PNG - 22.6 ko
Maquette de la fiche produit : la zone jaune incluera soit un visuel du produit (version A), soit une vidéo (version B)

Se pose alors un problÚme analytique : comment mesurer l'efficacité d'une version par rapport à l'autre ? Il existe de nombreux indicateurs, servant à représenter la réalité de l'expérience utilisateur : achats, abandons, mesures de temps, mesures du nombre de rebonds... AprÚs mûre réflexion, l'équipe fait un choix : celui d'utiliser l'action d'ajout-panier comme critÚre de succÚs. Plus un produit sera ajouté au panier, meilleure sera jugée la version.

Se pose ensuite un problĂšme technique car par souci de cohĂ©rence, Matthieu souhaite qu'un utilisateur ayant basculĂ© vers une version reste sur cette version pendant toute la durĂ©e du test : hors de question d'avoir tantĂŽt un visuel, tantĂŽt une vidĂ©o, au hasard ! L'Ă©quipe met donc en place un cookie qui stocke la version choisie pour un visiteur au moment oĂč elle est choisie. Le systĂšme teste ainsi pour chaque visiteur l'existence du cookie et s'il existe, lit Ă  l'intĂ©rieur la valeur Ă  lui afficher.

Reste Ă  choisir la version qui sera affichĂ©e Ă  la premiĂšre visite d'un client. De nouveau, une dĂ©cision doit ĂȘtre prise pour savoir comment seront traitĂ©s les utilisateurs : quelle quantitĂ© de visiteurs verra la version B, sur quels critĂšres seront-ils choisis et sur quel pĂ©rimĂštre du site le test aura-t-il lieu : toutes les fiches produit ou seulement certaines ? Pour ne pas influencer les rĂ©sultats, la technique du test A/B impose de trouver un critĂšre parfaitement indĂ©pendant, mais ce n'est pas Ă©vident !

Matthieu et son équipe décident de s'en remettre à un tirage au sort, qui délivrera la version de contrÎle à 99% des utilisateurs et la version B à 1% seulement, sur tout le site. Ainsi, si la version B ne réalise pas ses promesses, cela ne sera que peu préjudiciable à l'activité.

Matthieu se rend compte que sous couvert d'objectivité, l'équipe a déjà fait de nombreux choix trÚs subjectifs :

  • la nature du test lui-mĂȘme ;
  • la façon de mesurer la rĂ©ussite d'une version par rapport Ă  une autre ;
  • la façon dont les populations de visiteurs sont triĂ©es et la rĂ©partition relative de ces populations

Pas si simple, les Tests A/B, finalement. Mais bon, maintenant, c'est fait !

Les Tests A/B, ça commence quand ça finit

Matthieu décide de mener un test sur plusieurs jours et voici les chiffres qu'il récolte :

Version Nombre de visiteurs Nombre d'ajouts au panier Ratio Ajouts Panier / Visiteurs Version de contrÎle (A) 34 217 6234 18,21 % Version avec vidéo (B) 327 68 20,79 %

Au premier coup d'oeil au ratio entre nombre d'ajouts au panier et nombre de visiteurs, il semble clair que la version B est plus efficace que la version A. Malheureusement, le trafic n'a pas été à la hauteur de ce qui était attendu et l'échantillon est trÚs faible. Difficile de dire alors si l'échantillon de mesures est suffisant pour permettre une généralisation des résultats...

De plus, un des membres de l'Ă©quipe de Matthieu lui apporte une information nouvelle : suite Ă  une erreur dans la gestion du tirage au sort, les visiteurs dĂ©marrant leur navigation dans le rayon "High Tech" ont eu davantage de tirages B que les autres. Or, le rayon "High Tech" est un des rayons dont la transformation est la meilleure. La diffĂ©rence de presque 3 points observĂ©e n'a peut-ĂȘtre donc rien Ă  voir avec la modification apportĂ©e sur le visuel produit. Matthieu et son Ă©quipe sont dubitatifs.

Enfin, durant les quelques jours pendant lesquels le test a été effectué, le taux de conversion global du site a chuté. N'ayant pas fait suivre l'information A/B dans ses indicateurs jusqu'au paiement (seul l'ajout-panier stockait la différence), Matthieu a du mal à savoir si la version B y est pour quelque chose... Et si les gens ajoutaient davantage au panier, pour finalement partir sans avoir acheté ? C'est un risque que l'équipe ne peut pas prendre à la légÚre.

Tout cela enseigne beaucoup Ă  Matthieu
 sur la façon de faire des tests A/B. Mais sur le visuel produit, aucune conclusion n'est possible : il va falloir rĂ©itĂ©rer l'expĂ©rience en la contrĂŽlant mieux.

Les Tests A/B, quand les autres s'en mĂȘlent

Finalement, Matthieu et son Ă©quipe reproduisent le test avec de meilleures mesures et un volume significatif, ce qui leur permet de bien isoler les rĂ©sultats. Contrairement Ă  ce qu'ils avaient pensĂ©, la version B est moins performante, aussi le site est-il Ă  nouveau basculĂ© Ă  100% sur sur la version avec visuel produit. MĂȘme si Matthieu est frustrĂ© de ne pas comprendre les raisons du rĂ©sultat, lui qui pensait que la vidĂ©o ne pourrait ĂȘtre que plus attrayante, il est tout de mĂȘme satisfait de l'avoir obtenu et sa Direction l'en fĂ©licite.

Fiers de ce succÚs, l'équipe de Matthieu se voit confier de plus en plus de demandes de tests, en provenance notamment des équipes Marketing qui y trouvent un moyen formidable de mesurer l'activité des visiteurs. Mais de nombreux problÚmes techniques se posent, car certains tests, simples sur le papier, obligent notamment à maintenir plusieurs architectures logicielles incompatibles entre elles. Matthieu et son équipe sont obligés de mettre ces tests en attente, le temps de ré-écrire une partie du code pour pouvoir y injecter des dépendances. Et d'autres demandes, elles aussi mises en attente pour un délai indéterminé, nécessitent de modifier l'infrastructure technique. Beaucoup de dépenses qui n'étaient pas au budget...

Heureusement, certains tests continuent Ă  ĂȘtre possibles. L'Ă©quipe Marketing demande notamment un Split testing sur la Home sur site Corporate. Cela signifie que seront testĂ©es des versions complĂštement diffĂ©rentes de la page. Pourquoi pas, se dit Matthieu...

JPEG - 128.4 ko
"Rue d'Enfer" par Frédéric Bisson - CC BY 2.0

Malheureusement, cette demande s'ajoute aux autres, plus nombreuses, et certaines concernent des pages similaires. Les utilisateurs pourraient ainsi subir sans le savoir plusieurs tests A/B au sein d'une mĂȘme page. Sur la fiche produit, par exemple :

  • un test A/B jouerait sur la police d'Ă©criture du nom du produit ;
  • un test A/B jouerait sur le texte du call-to-action d'ajout-panier ;
  • un dernier test conditionnerait l'affichage d'informations en temps rĂ©el sur le produit consultĂ©

Techniquement possibles (en étendant les concepts déjà mis en place pour un seul test), cette analyse multivariée pose néanmoins le problÚme de la complexification de l'analyse statistique, déjà délicate. Car avec tout ça, le nombre de versions du site augmente excessivement vite.

Matthieu se retrouve à gérer :

  • un Split Test A/B/C sur la page d'accueil,
  • trois tests A/B sur la fiche produit ;
  • un test A/B impliquant une variation de la structure de navigation...

... soit 18 combinaisons possibles pour chaque visiteur et une augmentation considĂ©rable des coĂ»ts de maintenance (car dĂ©sormais, pour reproduire un bug, il faut se mettre dans la mĂȘme configuration que le navigateur client sur lequel il s'est produit). CoĂ»ts auxquels s'ajoute la problĂ©matique du suivi, car le dernier test a pour consĂ©quence directe de fausser les mesures analytiques existantes, qui jusqu'Ă  prĂ©sent se basaient sur les URLs.

Les Tests A/B, s'outiller

En se renseignant, Matthieu dĂ©couvre diffĂ©rente entreprises proposant des produits permettant de rationaliser les tests A/B. La plupart internalisent notamment deux des principaux problĂšmes : l'analyse statistique et la gestion des campagnes. Parfois, les campagnes sont mĂȘme automatisĂ©es pour s'arrĂȘter Ă  l'obtention d'un rĂ©sultat significatif.

Malheureusement, il est trĂšs difficile de dĂ©terminer l'intĂ©rĂȘt d'une solution plutĂŽt qu'une autre, car chacune semble adaptĂ©e Ă  un type de besoin :

  • Pour les Ă©quipes commerciales, certaines solutions se superposent au Front-End pour modifier Ă  la volĂ©e la page visualisĂ©e par le client. Si le concept est sĂ©duisant, il peut parfois aboutir Ă  des lenteurs ressenties par l'utilisateur, des "flashs" de la page et mĂȘme des situations de SPOF [1] dans les cas les plus extrĂȘmes ;
  • d'autres solutions plus orientĂ©es "injection" permettent de rĂ©aliser simplement des bascules entre plusieurs architectures logicielles ;
  • enfin, d'autres solutions permettent de basculer rapidement vers une architecture plutĂŽt qu'une autre, mais introduisent des passerelles supplĂ©mentaires dans le systĂšme, entraĂźnant Ă  la fois des risque et des baisses de performance

Matthieu sait donc qu'il devra passer par une phase de veille et de sélection de la meilleure offre au regard de ses propres problématiques. Mais plus que ça, il commence également à ressentir que...

Les Tests A/B ont beaucoup de limites

La premiÚre d'entre elles concerne la fonction d'adaptation. En effet, tout chantier d'optimisation consiste à approcher la meilleure des solutions en comparant plusieurs variations. Ceci étant, cela ne veut pas dire qu'il s'agit de la meilleure variation dans l'absolu. Ce n'est pas parce qu'on aboutit à un optimum local (autour de la situation d'origine) qu'il n'existe pas une variante trÚs éloignée produisant de meilleurs résultats.

Imaginons, par exemple, que nous procĂ©dions Ă  une analyse multivariĂ©e composĂ©e de deux tests ayant chacun une quinzaine de variations (le cas est extrĂȘme, mais il sert la dĂ©monstration). Jouer sur les variations des deux tests consiste alors Ă  se dĂ©placer sur le plan jaune du graphe ci-joint, Ă  la recherche d'un maximum de performance. Rien ne nous permettrait, une fois arrivĂ©s en haut du sommet jaune, de savoir qu'il en existe un plus grand sommet ailleurs et que nous l'aurions trouvĂ© en poursuivant nos tests sur un plus grand nombre de variations.

Ensuite, le Test A/B ne dira jamais que ce qu'on lui demande de dire. Dans l'exemple de Matthieu sur le visuel ou la vidéo produit, le test a répondu que le visuel était la meilleure solution, mais il est incapable d'expliquer qu'il s'agit probablement de la conséquence de deux facteurs : d'une part l'habitude des utilisateurs à visualiser des vidéos en paysage plutÎt qu'en portrait et d'autre part, leur incapacité à ne pas se disperser face à un média interactif. Promouvoir les tests A/B est donc une bonne chose... à condition de faire appel à des professionnels pour savoir en comprendre les résultats !

Ajoutons Ă  cela plusieurs autres limites Ă©videntes :

  • l'A/B Testing ne connait pas vos visiteurs. Il ne sait pas s'ils sont vieux, jeunes, technophiles, fidĂšles... or, ces populations peuvent avoir des comportements et des processus de dĂ©cision complĂštement diffĂ©rents et vous n'en aurez qu'une vision globale. A vous de complĂ©ter votre A/B Testing par un outil analytique de qualitĂ©, ou un tracker, qui vous permettra de bien segmenter les retours de ces typologies de visiteurs ;
  • l'abus d'analyses multivariĂ©es entraĂźne un besoin croissant en nombre de visites : il n'est donc pas possible de "tout tester" en espĂ©rant trouver la bonne recette, d'autant que le taux de conversion est probablement une Ă©quation plus complexe que la simple addition de l'ensemble des cas de figure ;
  • l'A/B Testing est un outil court-termiste qui ne prend pas en compte la courbe d'apprentissage de vos visiteurs. Sa pertinence n'est donc pas la mĂȘme pour un vendeur de masse et une entreprise dont les produits sont Ă©laborĂ©s et le processus de vente trĂšs rĂ©flĂ©chi
JPEG - 69.8 ko
"Thinking" par Moyan Brenn - CC BY 2.0
Les Tests A/B, au final

Interrogé par sa Direction, Matthieu présente l'intégralité de son expérience sur les tests A/B. Envisagé comme un outil magique d'aide à la décision, l'A/B Testing est en réalité plus complexe et coûteux qu'imaginé.

En rĂ©alitĂ©, comme tous les outils, l'A/B Testing nĂ©cessite d'ĂȘtre manipulĂ© par des experts ayant la meilleure connaissance possible du contexte. Enfin, jusqu'Ă  ce qu'un test A/B prouve le contraire !

[1] Single Point of Failure (SPOF) : situation dans laquelle le site repose fortement sur une ou plusieurs ressources externes. Si ces ressources ne sont pas disponibles ou qu'un problÚme technique rend impossible leur acheminent jusqu'au client (problÚme réseau, passerelles capricieuses) alors la page n'est plus consultable.

Catégories: Blog Société

La chasse aux faux semblants dans Scrum

Forum Logiciel - jeu, 03/13/2014 - 10:17
Nous avons essayĂ© d’appliquer le manuel Scrum Ă  la lettre : daily, dĂ©mo/rĂ©tro, itĂ©rations courtes, post-its, product owner … Mais tout n’a pas fonctionnĂ© comme sur des roulettes. Est-ce Ă  cause du manque de maĂźtrise / Ă©quipe dĂ©butante ou d’un problĂšme de Product Owner? Nous allons faire un retour d’expĂ©riences sur nos pratiques « agiles » des […]
Catégories: Blog Individuel

Revue de Presse Xebia

Revue de Presse Xebia
La revue de presse hebdomadaire des écosystÚmes Java/JEE proposée par Xebia.

Agilité La révolution du Service Design http://www.gravatar.com/94d0042d24a2eaf116efd4c69ac90541http://blog.xebia.fr/author/ygrenzingerhttp://twitter.com/ygrenzingerPar Yannick Grenzinger

Si vous demandez Ă  un designer quel est leur plus grand dĂ©fi, beaucoup vous rĂ©pondrons que c’est lorsque leur client leur demande de justifier le business ou de dĂ©finir le retour sur investissement financier d’un design, avant que quoique ce soit ait Ă©tĂ© conçus.

Cependant grĂące au design de service, une rĂ©volution est peut ĂȘtre en cours. Les Ă©tudes de cas donnent un aperçu intĂ©ressant de ce qui fait qu’un client vas s’engager – promesses d’efficacitĂ©, d’efficience, de clients heureux et de rentabilitĂ©.

Cet article explique les raisons de cette révolution et fait suite à une conférence mondiale sur le service design dont vous pouvez voir les vidéos ici.

L’innovation par les mĂ©thodes de management : le cas Favi http://www.gravatar.com/f23d9dee080a22a6bb65caad9997acedhttp://blog.xebia.fr/author/lperothttp://twitter.com/ludovicPEROTPar Ludovic Perot

Ayeba nous partage la confĂ©rence qu’a tenue Jean-François Zobrist, patron de Favi. Favi est une sociĂ©tĂ© leader de son marchĂ©, mais son activitĂ© est industrielle. Pour autant, sa rĂ©putation dĂ©passe son secteur d’activitĂ© par son approche du management : pas de planning, pas de contrĂŽle qualitĂ©, pas de tableaux excel d’analyse.
Zobrist s’est appuyĂ© sur des outils d’amĂ©lioration continue dont certains pourraient vous rappeler des choses : 5S, Kaizen, 5 pourquoi, etc.
Si vous ne connaissez pas ce cas d’école, cet article (http://ayeba.fr/2014/01/linnovation-par-les-methodes-de-management-le-cas-favi/) vous donnera peut-ĂȘtre envie de creuser !

Mobilité Twitch annonce un SDK mobile http://www.gravatar.com/63d261113651caa0dc887445c61ea48ahttp://blog.xebia.fr/author/blacroixhttp://twitter.com/benjlacroixhttp://github.com/mbretonPar Benjamin Lacroix

Twitch annonce son SDK pour enregistrer et/ou diffuser le contenu d’une application mobile (Android & iOS).

Au menu :

  • Diffusion et capture de l’audio et de la vidĂ©o
  • Capture vidĂ©o depuis la camĂ©ra frontale
  • Capture audio depuis le micro interne ou un micro externe
  • Les vidĂ©os peuvent ĂȘtre archivĂ©es pour ĂȘtre immĂ©diatement vues sur Twitch ou tĂ©lĂ©chargĂ©es pour ĂȘtre partagĂ©es
  • QualitĂ© de diffusion paramĂ©trable (haut, moyen, faible)
  • Option de chat intĂ©grĂ©e
  • Recherche avancĂ©e de vidĂ©os similaires Ă  celles diffusĂ©es

Malheureusement, pas encore de date de sortie ni d’informations sur les terminaux compatibles.

News correspondante sur le blog de Twitch : http://goo.gl/UUwY8L

Xebia aux CocoaHeads ce jeudi 13 mars pour parler de l’aprĂšs Testflight http://www.gravatar.com/39c333db7f8ce30aba2b66dbcaea5716http://blog.xebia.fr/author/tcavinhttp://twitter.com/ThibaudCAVINhttp://github.com/mbretonPar Thibaud Cavin

Xebia sera prĂ©sente aux CocoaHeads ce jeudi 13 mars. Simone Civetta abordera les solutions alternatives Ă  Testflight suite Ă  son rachat par Apple. Ce sera l’occasion d’aborder les sujets suivants :

  • Fonctionnement d’un MAM (Mobile Application Management)
  • Quel avenir pour Testflight suite au rachat d’Apple ?
  • HockeyApp : Une alternative Ă  Testflight ?
  • Et Ă©galement les solutions hĂ©bergĂ©es comme HockeyKit, Knappsack, Shenzhen

Plus de détails sur le programme par ici 

Front Sortie de SASS 3.3 http://www.gravatar.com/d2d7263cc510ef945bf738083be3c4f8http://blog.xebia.fr/author/pantoinehttp://twitter.com/PhilippeAntoinehttp://github.com/philippeantoinePar Philippe Antoine

Au delà des simples listes, il est désormais possible de créer de nouvelles structures de données : les Maps. Vous pouvez maintenant aller un cran plus loin dans vos factorisations:

$social: (twitter, $Twitter),
        (facebook, $FB),
        (googleplus, $GPlus),
        (linkedin, $LinkedIn);

@each $socialnetwork, $color in $social {
  .social-link--#{$socialnetwork} {
    background-color: $color;
    &:focus,
    &:hover {
      background-color: darken($color,5%);
    }
    &:before {
      background-image: url('/images/#{$socialnetwork}.png');
    }
  }
}

Exemple tiré de always twisted. Pour aller plus loin: un exemple sassmeister éditable en ligne avec des rÚgles imbriquées

Le support tant attendu des sourcemaps est dĂ©sormais officiel. Pour l’instant uniquement disponible dans Google Chrome, vous pouvez donc visualiser et Ă©diter vos fichiers SASS directement dans votre console :

Activez la fonctionnalitĂ© dans vos flags chrome://flags puis enable Developer Tools Experiments. Dans vos devTools, dans l’onglet General cochez Enable source maps, pareil pour Experiments/Support for Sass. Enfin, compilez votre sass avec sass watch --sourcemap. Si vous utilisez grunt, rajoutez dans votre tache sass options: { sourcemap: true }

Enfin, on peut citer le support amélioré de la syntaxe BEM.

Pour plus de dĂ©tails, l’annonce de la sortie de SASS 3.3 sur le blog the sassy way

Back Akka 2.3.0 http://www.gravatar.com/37a6259cc0c1dae299a7866489dff0bdhttp://blog.xebia.fr/author/nullhttp://twitter.com/nullhttp://github.com/mbretonPar Nicolas Jozwiak

Typesafe vient de sortir la version 2.3.0 de Akka. Basé sur les acteurs, Akka apporte de la simplicité et de la souplesse dans la mise en place de systÚme performants. Cette cuvée apporte sont lot de nouveautés avec :

  • Un module de persistence (Akka Persistence)
  • Le support de Java 8 avec les lambdas
  • AmĂ©liorations de la gestion des clusters

Cerise sur le gĂąteau, de nouveaux templates Activator sont mis Ă  dispositions pour voir ces nouveautĂ©s Ă  l’oeuvre. Si l’envie vous prend de les essayer cela se passe ici.

10 Habits of a Happy Node Hacker http://www.gravatar.com/b8cac58f832026793ff351fdd96a40ebhttp://blog.xebia.fr/author/ebriandPar Eric Briand

Heroku nous partage sur son blog un billet sur des best practices pour nodejs. Celle-ci ne s’applique pas qu’Ă  un dĂ©ploiement chez Heroku. En rĂ©sumĂ©, le billet nous donne des bonnes pratiques pour bien dĂ©marrer son projet node (privilĂ©gier npm plutĂŽt que node par exemple) et des pistes pour aller encore plus loin comme utiliser harmony avec node, ou utiliser les libs nodes cĂŽtĂ© client avec browserify.

Cloud Google Cloud Platform Developer Roadshow 2014 http://www.gravatar.com/b8cac58f832026793ff351fdd96a40ebhttp://blog.xebia.fr/author/ebriandhttp://twitter.com/nullPar Eric Briand

Google réitÚre cette année son Google Cloud Platform Developer Roadshow et il passe à Paris le 7 avril. Au programme de cette aprÚs midi, 4 conférences autour de Compute Engine et App Engine. Cet événement permettra aussi à Google de revenir sur les annonces faites au cours de la journée Google Cloud Platform Live. Inscription pour la session de Paris ici.

DevOps Puppet Enterprise 3.2 http://www.gravatar.com/d4aab995af10c95e3ca72dab4b271ab1http://blog.xebia.fr/author/mnanternhttp://twitter.com/mnanternhttp://github.com/mnanternPar Matthieu Nantern

PuppetLabs vient de publier la version 3.2 de Puppet Enterprise, un des principaux outils d’automatisation et de gestion de la configuration.

Parmi les nouveautĂ©s, il est Ă  noter principalement le support officiel de certains modules de la forge. Ainsi il est maintenant possible de dĂ©ployer automatiquement des serveurs Apache HTTPD, MySQL, NTP ou PostgreSQL sans avoir besoin d’Ă©crire la moindre ligne de code Puppet.

Cette nouvelle version fournit Ă©galement:

  • Une simplification de l’installation et des mises Ă  jour des agents Puppet
  • Une preview de Razor : un outil de provisionning de serveurs nus (« bare metal »)
  • Des fonctionnalitĂ©s orientĂ©es entreprise : support de Solaris 11 et possibilitĂ© pour les utilisateurs non-root de profiter de Puppet

Si l’envie vous prend de tester cette nouvelle version, Puppet Enterprise est gratuit jusqu’Ă  10 noeuds.

La banque d’investissement de la SociĂ©tĂ© gĂ©nĂ©rale passe ses Ă©quipes Ă  l’agilitĂ© http://blog.xebia.fr/author/xebiahttp://twitter.com/xebiaFrPar XebiaFr

La Société générale vient de passer un nouveau cap. En deux ans et demi, la moitié des applications SGCIB sont passées à un mode de développement agile, aidée par nos consultants agiles !
Ceci fut aussi le premier pas vers l’adoption du Continuous Delivery. La sociĂ©tĂ© GĂ©nĂ©rale utilise dorĂ©navant DeployIt, un produit de XebiaLabs.
Nous vous invitons à découvrir cette transformation à travers cet article publié dans 01 Business.

Catégories: Blog Société

[ #Office365 ] Comment créer un formulaire Excel ?

Le blog de Patrick Guimonet - jeu, 03/13/2014 - 09:21
La possibilitĂ© de crĂ©er une enquĂȘte Excel est accessible depuis la mise Ă  jour d’aoĂ»t 2013 sur Office 365. C’est l’une des 5 solutions (avec InfoPath !) de formulaires disponibles en natif sur SharePoint /Office 365. Vous trouvere...
Catégories: Blog Individuel

Partagez la connaissance

Partagez BlogsdeDeveloppeurs.com sur les réseaux sociaux