Prise de décision dans les projets agiles

Dans tout projet il est question de faire des choix et des arbitrages. Par rapport à cela, les projets agiles ont certaines spécificités.

Les variables QCD revisitées

Classiquement, les choix dans un projet sont perçus au bout du compte comme un arbitrage entre les trois composante du tryptique QCD :

  • Qualité : La qualité ou le contenu du livrable (exemple nombre ou complexité des fonctions livrées).
  • Cout : Qui revient souvent à la quantité de ressource qu’il va falloir mobiliser sur un projet (nombre de développeurs, moyens financiers …).
  • Délais : Qui est la date de de livraison prévue.

Ainsi, améliorer la Qualité (Q) nécessite soit de mettre plus de ressource (donc un Cout supplémentaire) ou livrer plus tard (donc un Délais supplémentaire). Inversement, réduire le Cout (donc les ressources mobilisées) nécessiterait soit de réduire les fonctionnalités livrées (donc la Qualité) soit augmenter le Délais de livraison vu le manque de ressources. Ainsi de suite …

En projet classique toutes les variables sont considérées pour l’arbitrage, et souvent, on impactera d’abord le Délais, ensuite éventuellement le Cout et vraiment en dernier recours la qualité.

Les priorités QCD en projet Agile : la Qualité, variable de choix

En agile, les durées d’itérations sont fixées, la composante Délais n’est donc pas une variable d’ajustement sauf très rare exception. Cela a pour avantage de maintenir un synchronisme naturel à la fin de l’itération entre les équipes de développement et le reste de l’entreprise (équipes de test, déploiement, métier, communication …).

La composante Cout de son côté est souvent difficilement ajustable. En effet, en projet agile :

  1. La priorité est donnée au livrable par rapport à la documentation.
  2. L’interaction directe des membres prévaut par rapport aux processus et outils.

De fait la culture de l’équipe est relativement orale et met donc du temps à se transmettre aux nouveaux arrivants.

De plus, les équipes étant souvent auto-organisée, cela nécessite du temps pour se réorganiser en fonction des capacités de nouveaux arrivants.

La variable d’ajustement principale est donc souvent la Qualité autrement dit, la question revient souvent à une variante de : Que vas-t-on livrer ?

Les critères de décision en agile : la valeur et la capacité à livrer

Une fois la question posée, les réponses possibles sont analysées selon deux critères principaux :

  1. Quelle valeur ajoutée apporte tel ou tel choix à l’utilisateur (Valeur métier)
  2. A quel point les informations nécessaires pour livrer cette valeur sont disponibles.

Parmi les options suffisamment précise et réalisables on choisira donc celle qui apporte le plus de Valeur au métier.

Le droit à l’erreur

En projet agile, le changement est la règle et non pas une exception, de fait on se donne le droit de se tromper et de changer de cap, de fait la décision peut se prendre avec un certain niveau d’incertitude. Cependant, il convient dans ce cas là de se donner les moyens de détecter son erreur le plus tôt et la convertir en apprentissage dans le cadre de l’amélioration continue.

En conclusion

Les choix de projet agile reviennent souvent à redefinir le périmètre ou les détails du livrable (variable Qualité), ce choix doit se faire essentiellement en regardant la valeur métier et la capacité à réellement livrer cette valeur. Enfin, il n’est pas une exception de devoir éventuellement changer d’avis plus tard, l’important est de transformer les erreurs en apprentissage.

Quel est le bon outil de gestion de projets informatiques ?

Quel est le meilleur outil pour gèrer les projets de développement informatique? Faut-il fédérer l ‘équipe autour de diagramme de Gantt? Ou est-ce mieux d ‘utiliser un plan d ‘action excel? Ou peut être un tracker?

Je me suis entretenu à ce sujet avec plusieurs developpeurs, chefs de projet et architectes de divers horizons et la question semble loin d ‘avoir une réponse évidente unanimement accptée.

Plusieurs types d ‘outils

Pour être très synthetique, j ‘ai retrouvé essentiellement 3 types d ‘outils :

  • les listes de taches que ce soit une simple feuille excel ou un outils plus avancé de type tracker (redmine…)
  • les gantt de type msproject gantt project ou libreproj.
  • les tableaux de sticker (post it board) il s ‘agit de tableaux blancs ou tableaux de paperboard découpés en sections sur lesquels des post-its représentant les taches sont collés et déplacés.

Plusieurs facteurs de réussite

Lors des différents échangés les outils peuvent être appréciés ou rejetés pour des raisons que je synthétise par :

  • L ‘adoption : les développeurs et les chefs de projet vont-ils réellement savoir utiliser l ‘outil?
  • L ‘utilité : l ‘outil vas-t-il réellement rendre service à son utilisateur ou est-ce un fardeau à porter par obligation?
  • La souplesse : l ‘outil vas-il s ‘adapter au fonctionnement de l ‘équipe ou vas-t-il introduire des contraintes a ce fonctionnement?

Au delà de l ‘outil, les revues régulières, l ‘écoute et la pédagogie du team leader sont un must pour favoriser la bonne utilisation des outils et le bon déroulement du projet.

Symptôme du mauvais outil : le multi-suivi

Quand l ‘outil adopté par le projet ne satisfait pas l ‘équipe, un phénomène se produit quasi systématiquement : Le développement de suivis parallèles à l ‘outil principal : des plans d ‘action sur Excel, des échanges de mail, des pages Wiki des Trackers … Reprennent et s’ajoutent aux taches principales du projet.

Cela vas sans dire : Cela est très nuisible à la synergie de l’équipe et à l’efficacité de la collaboration.

Les développeurs amateurs de plus en plus nombreux selon l’IDC, ils représenteraient actuellement presque 40 % des développeurs

C ‘est plutôt une bonne nouvelle, le concept d’école comme l’Ecole Simplon fait donc sens, Reste quel pourcentage de passionnés et quel pourcentage d ‘opportunistes ….

http://www.developpez.com/actu/66593/Les-developpeurs-amateurs-de-plus-en-plus-nombreux-selon-l-IDC-ils-representeraient-actuellement-presque-40-des-developpeurs/

INVEST – Les 6 piliers d’une bonne User Story scrum

La façon dont les besoins du Metier sont exprimés en terme de story agile est déterminante pour maximiser le gain d’efficacité promise par les projets agiles.

Qu’est ce qu ‘une story

C ‘est une paragraphe court qui decrit sommairement une fonction du produit et sa valeur métier, par exemple :

En tant que client je peut chercher les produits de la e-boutiques en tapant des mots clés cela me permet de trouver rapidement l'ensemble des produits qui repondent à mes besoins.

Une user story est censée être un sujet de discussions et non pas une description détaillée d’une fonction. Il n ‘y a pas de mal à ce que une story soit au départ trops générique voir mal cernée par le product owner lui même tant qu ‘elle reste dans le backlog. Cependant, elle ne peut être admise dans une itération que quand le product owner a la maturité nécessaire pour pouvoir donner des informations detaillées : sur la fonction principale, les chemins alternatifs, les cas d ‘erreur… (Voir cet article sur les critères de réalisation d’une story)

Les 6 critères de qualité INVEST

Afin de s ‘assurer qu ‘une user story a les qualités nécessaires pour être effectivement incluse dans une itération, 6 critères ont été definis sous l’acronyme INVEST.

  • Independant : chaque story doit constituer un avantage métier par elle même : On ne peux pas avoir deux story qui dépendent l ‘une de l ‘autre pour produire de la valeurs. Exemple:
    Story 1: en tant que client mes transactions doivent être stockée en base lors d 'un achat. 
    Story 2: en tant que client je doit recevoir une fois par mois une liste détaillée de transactions pour pouvoir mettre à jour ma comptabilité.
    

    La story 1 ne produit pas de valeur en soit, imaginons qu ‘elle soit réalisée lors d ‘une iteration, il n’y aura de vrai ROI (retour sur investissement) qu’appartir du moment ou la Story 2 est mise en place. Entre temps, du temps de développement a été investi sans réelle rentabilité. Par ailleurs, dans un environnement changeant, la story 2 pourra devenir à un certain moment inutile ou pas prioritaire, on aura alors investit du temps inutilement.

  • Negociable : Toute story peut être remise en question, discutée négociée à tout moment. Par ailleurs, elle doit être exprimée dans un language compris à la fois par l’équipe de développement et le métier pour permettre une réelle négociation et connaissance des enjeux partagée.

  • Valuable : Chaque story doit apporter de la valeur, c’est la base du bon sens. Si on est incapable de décrire le bénéfice utilisateur d’une story, c’est qu’elle est probablement supérflue ou plus proche d’une tache technique que d’une story. Les besoins non fonctionnels sont des fois assez astucieux à exprimer en terme de valeur métier. Ainsi, mettre en place des logs techniques peut s’expriemer :

    En tant qu'opérateur de maintenance je doit avoir accès à des traces d'erreur afin de rapidement résoudre les incidents qui bloquent les utilisateurs.
    
  • Estimable : Litérallement, cela veut dire que l’équipe de développement peut donner une estimation de l’effort pour réaliser la story. Plus concrètement, il s’agit de s’assurer que l’équipe a une discussion autour de la story et voit globalement la solution technique pour la réaliser.

  • Sized appropriately : Doit avoir une taille la plus petite possible. Afin de réduire la taille d’une story une des techniques est de découper en variante ainsi :

    En tant qu'utilisateur, je peux payer mes achats en ligne afin de recevoir ma commande plus rapidement.
    

    On pourrait découper cette story en 3 :

    En tant qu'utilisateur, je peux payer mes achats en ligne par carte banquaire afin de recevoir ma commande plus rapidement.
    En tant qu'utilisateur, je peux payer mes achats en ligne avec mon compte paypal afin de recevoir ma commande plus rapidement.
    En tant qu'utilisateur, je peux payer mes achats en ligne avec mon compte mobile afin de recevoir ma commande plus rapidement.
    
  • Testable : Chaque story développée doit pouvoir être validée par le métier en effectuant des tests. Il faut donc qu’elle soit définie de façon concrète avec des critères d’acceptation précis.

En conclusion

Le découpage en story n’est pas juste une façon différente de produire un cahier des charges mais a un impact réel sur la conception du produit lui même et le déroulé du projet. C’est ce bon découpage qui donne tout son intérêt à un projet agile:
– La motivation des équipe augmente en voyant l’aboutissement concret de ce qu’elles réalisent sans être bloquées par le métier.
– La satisfaction des managers augmente en voyant à chaque itération des fonctions utiles livrées et améliorées et donc un ROI progressif.

Et enfin, le métier garde la marge de manoeure pour ajuster ou re-prioriser les fonctions du produit et gérer les risques et incertitudes de l’évolution du contexte.

PayPal abandonne Java pour JavaScript coté serveur

Node.js a permis un gain important en performance et en temps à l’entreprise, un retex intéressant même si le javascript pour des plates formes d’entreprise ne doit pas être mis entre toutes les mains : la souplesse du langage exige des developpeurs expérimentés pour le manier correctement.

http://www.developpez.com/actu/65013/PayPal-abandonne-Java-pour-JavaScript-Node-js-a-permis-un-gain-important-en-performance-et-en-temps-a-l-entreprise/

Le bon nommage dans la programmation, un vecteur d’agilité

Un bon nommage dans un code permet une meilleur lisibilité du code facilitant son test, sa modification et son évolution sans recourir à une documentation exhaustive. Les équipes peuvent alors concentrer leurs efforts sur la production de fonctionnalités plutôt que de documentation: Working software over comprehensive documentation.

Intérêts du bon nommage

Si vous codez en Java il vous est certainement déjà arrivé de commencer à taper « au hasard » un nom de classe ou de méthode dont vous n’êtes pas certain de l’existence, l’assistance à la saisie de votre IDE aidant et une excellente convention de nommage qu’est celle de l’API java permet souvent de trouver la classe ou la méthode dont vous avez besoin sans ouvrir la documentation.

Outre l’utilisablité quand vous développez une librairie, un bon nommage rends le code facilement lisible et donc facile à valider et corriger.

Entre ce code:

int debit(int m) throws Exception {
    int a=solde-m;
    if(a < 0) update(-m);
    else throw new SoldeException();
    return a;
}

et celui ci:

int debiterCompte(int montantADebiter) {
    int soldeRestant=soldeCourrant - montantADebiter;
    if(soldeRestant < 0) mettreAJourSolde(-montantADebiter);
    else throw new ExceptionSoldeInsuffisant();
    return soldeRestant;
}

Il est plus facile de valider et déboguer le code dans le second exemple que dans le premier. Et l’erreur de comparaison du solde dans le deuxième cas se déclare par elle même à la relecture du code.

En effet, un bon nommage permet de lire le code comme si on lisait un texte est donc utiliser les capacités logiques de la vie courante pour valider le code.

Un vecteur d’agilité

Le deuxième principe de l’Agile Manifesto édicte

Working software over comprehensive documentation

Or la capacité de réduire la documentation sans faire courir de risque au projet dépend fortement de la lisibilité du code. Un bon nommage favorise cette lisibilité.

Cela est en lien avec une pratique du lean qu’st le Management Visuel

Le Management visuel est l’une des techniques lean conçue de telle sorte que toute personne entrant dans un atelier, même ceux qui
sont pas familiers avec le détail des processus, peuvent voir très rapidement ce qui se passe, comprendre et voir ce qui
est sous contrôle et ce qui ne l’est pas. (source)

Dans ce sens, un code lisible en soit favorise l’efficacité et améliore la quailité. En effet, un nouveau développeur arrivant sur un code lisible n’a pas besoin de documentation exhaustive pour le prendre en main et peut directement concentrer ses effort sur la valeur ajoutée à apporter au Product Owner.

Une documentation dit ce que fait le code, un code lisible dit ce qu’il fait mais aussi comment il le fait, cela encourrage alors le développeur, au besoin à améliorer améliorer le code quand l’opportunité se présente.

Syndrôme de la page blanche

Comme un écrivains on a face à l’écran un syndrome de la feuille blanche, syndrome qui pousse souvent à adopter des règles de nommage techniques ou sans aucun sens. Ainsi, j’ai eu dans mon équipe un développeur qui nommait les variables avec des combinaisons de ses initiales. Cela faisait en exagérant un peu quelque chose comme :

int jpl = 3;
int plj = 10;
if((plj-jpl)>23) doSomeThing(jpl);
....

Pour stimuler la créativité, dans la suite de l’artice je vais donner quelques tuyaux pour bien nommer les variables.

Quelques tuyaux pour trouver des idées pertinentes des noms de variables.

Chapter 1. Nommer une variable selon ce qu’on doit en faire

Comme par exemple {{{itemsToRemove}}} ici :

ArrayList itemsToRemove = new ArrayList();
for(MyType elem : myCollection) {
    if(elem.needsRemoval()) 
        itemsToRemove.add(elem);
}
myCollection.removeAll(itemsToRemove);

Cette approche est souvent plus pertinente pour les variables plutôt locales et éphémères qui ne sont utilisées que pour une tache précise dans l’algorithme.

Chapter 2. Nommer selon la nature de ce qu’elle contient

Comme unsold items dans :

ArrayList unsoldItems = getUnsoldItems();
for(Item item : unsoldItems) {
    item.setAsAvailableForSale();
}
...
warehouse.markAsAvailable(unsoldItems);
...
for(Item item : unsoldItems)
    paymentProvider.refund(item.getCustomerId(), item.getPrice());

Cette approche est souvent très pertinente et donne une lisibilité exceptionnelle au code.
Elle nécessite cependant de trouver une façon judicieuse pour décrire le contenu de la variable en peu de mots:

//Unsold items including new items returned by the user after delivery but not used ones.
ArrayList unsoldItems = ...

et non pas

ArrayList unsoldAndReturnedItemsButNotReturnedOnes = ...

En effet, une caractérisitique du bon nom est qu’il puisse être retenu par le lecteur, il se doit donc d’être succinct. Et de ce fait, 2 ou 3 mots sont un max.

Chapter 3. Nommage des booleans

La meilleure approche est de les nommer par en une affirmation logique qui est vraie quand la valeur du boolean est true. Ainsi, à comparer ces deux codes :

if(availibity && price) return false;

on comprends moins le sens que dans

if(itemIsAvailable && priceIsValid) return false;

cette approche permet de faire en sorte que les assertions logiques, même longues soient « vérifiables »

if(basketIsNotEmpty && (userHasPaymentInfo || basketIsAGift || !productIsPrivate)) allowDelivery();

Quelques pièges et solutions

  1. Les noms trop longs : Quand il est absolument nécessaire de manipuler des notions dont le nom est trops long, une technique est d’utiliser un acronyme ou les initiales avec une définition dans un commentaire, mais c’est une technique à éviter et il est préférable de chercher des noms courts.
    //PSP : Payment Service Provider
    Operator selectedPSP = getSelection().geProvider();
    
  2. Remettre le nom de la classe dans le nom de ses attributs. C’est une pratique à rejeter complètement, sauf dans d’extrêmement rares cas, cette approche ne fait que rallonger le texte sans apporter d’information du genre {{{ Product.price }}} n’a rien qui manque par rapport à {{{ Product.productPrice }}}. D’autant plus que dans le nommage des instances, la pratique de mettre le nom de la classe (ou de préférence une de ses spécialisation) est bonne :
    Product selectedProduct; //Bonne pratique
    

En conclusion

La rédaction d’un code lisible avec un bon nommage est un art. On peut souvent négliger le fait qu’il faut « coder pour être lu » non seulement par la machine, mais par soit même ou un autre qui dans plusieurs mois ou années aura affaire au code pour le corriger ou le faire évoluer. Quoi qu’on en dise, barder un code de commentaire ou l’accompagner de documentation est une technique beaucoup moins efficace et introduit de la rigidité et de la non-valeur dans le projet.

La mobilité, le cloud, le big data : la révolution du SI est pour tout de suite.

Les ruptures technologiques peuvent impacter de façon importante le système d ‘d’information et son rôle stratégique dans l’entreprise. De la même façon que la démocratisation du PC qui a sorti l’informatique des centres de calcul a permis au SI de devenir un élément stratégique de la performance des métiers, divers experts prévoient une nouvelle révolution du SI à l’horizon 5 à 10 ans.

Une révolution complexe

Cette fois-ci il ne s ‘agit pas d ‘une technologie mais de la convergence de plusieurs tendances. Identifiées par IDC sous le nom de la 3ème plateforme et par Gartner sous le nom du Nexus of Forces, cette convergence concerne :

  • Le cloud en tant que possibilité nouvelle offerte directement aux directions métier de se fournir en services au delà des catalogues de la DSI. Plus en phase avec le rythme effréné des nouvelles technologies et facilement pris en main par la nouvelle génération de salariés, les services cloud mettent à mal la DSI qui doit sortir du rôle de mise à disposition d’application métier internes vers la mise en oeuvre maîtrisée d’un SI forcément ouvert vers le cloud.
  • La mobilité comme une fenêtre vers le cloud dans la poche des clients, des fournisseurs ou des salariés. Un véritable vecteur de performance des métiers et de relation client, la mobilité est aussi un challenge en terme de sécurité et d ‘interopérabilité.
  • Les médias sociaux comme une nouvelle façon pour les salariés de collaborer et une nouvelle façon pour l’entreprise d ‘interagir avec ses clients et partenaires, les médias sociaux permettent aussi de comprendre, mesurer et rester en phase avec les évolutions rapides de la société.
  • L’internet des objets et le BigData comme promesse, non seulement de disposer de données plus abondantes et plus précises sur l ‘entreprise et son environnement, mais aussi de pouvoir les analyser et les visualiser pour en extraire une information pertinente.

A l’entreprise de se préparer

Autant les éditeurs que les entreprises utilisatrices doivent intégrer dans leur feuille de route la préparation à cette révolution. Si bien que l’IDC rajoute à cette recommandation pour les éditeur « quit à cannibaliser leurs marché actuel », car de leur point de vue c’est une réelle redéfinition du paysage ou toutes les places sont remises en jeu, même celles des leaders.
De son côté l’Open Group a lancé le Forum Plateform 3.0 dont le but est de définir des standards et pratiques permettant aux entreprises de bien négocier ce virage. Ainsi, pour l’Open Group l’entreprise de demain doit se doter de Capacités nouvelles, dont :

  • Traiter des données dans le cloud en maîtrisant tous les aspects (réglementaire, sécurité …).
  • Intégrer des données de diverses sources y compris celles issues d’objets communicants ou des médias sociaux.
  • Gérer, partager et distribuer un gros volume de données.
  • Extraire et exploiter l’information utile depuis ces données.

Cela nécessite bien entendu de la préparation en amont et une réelle mutation de la façon de concevoir le rôle de la DSI et l’Architecture du SI, d’autant plus que le travail d’identification des fonctions nécessaires pour supporter ces capacités sont à définir et les briques techniques à même de fournir ces fonctions sont encore en maturation.

Factorisation d’écriture dans les arrays pour optimiser la taille d’un Cardlet JavaCard

Il m’a été donné l’occasion de travailler sur une optimisation d’un Cardlet Sim Toolkit pour un opérateur télécom. Le problème principale était la taille de mémoire nécessaire pour installer l’Applet sur la carte. Il était donc question d’optimiser la taille du code.

Cette applet offrait un certain nombre de services par SMS, au bout du menu, de façon très classique, un SMS était construit et envoyé à un numéro précis pour fournir le service. Ci dessous un exemple du code utilisé pour constuire le SMS:

int index=0;
buffer[index++]=(byte)'A';
buffer[index++]=(byte)'B';
buffer[index++]=(byte)'C';
...

J’appellerai cela une écriture inline dans le buffer
Il se trouve que un des axes majeurs d’optimisation de cette applet était de transformer ce genre de pattern en :

index = addBytes(buffer,index,'A','B','C');
index = addBytes(buffer,index,...);
...

J’ai en effet créé une fonction statique addBytes surchargée en version à 3, 4 et 5 bytes que j’appelle en lieu et place de la définition manuelle des bytes.
Elle ajoute les parametres au buffer et retourne la nouvelle position d’index. J’appelerai ça une écriture factorisée dans le buffer.

Pourquoi est-ce une optimisation de la taille du code ?

Cela tien à la structure du code compilé java du .class (dit bytecode) que la JVM exécute. Comme la bonne vieille HP 48 GX le bytecode utilise une pile pour décrire à la JVM les paramètres des instructions à exécuter. Ainsi pour faire une addition de 1 + 1 le byte code sera :

  1. Pousser 1 dans la pile.
  2. Pousser 2 dans la pile.
  3. Additionner les deux au sommet de la pile.

Soit en byte code (en suppostant travailler avec des int) :

  1. iconst_1 (push constant value 1 into the stack)
  2. iconst_2 (push constant value 2 into the stack)
  3. iadd (add the two last values and store result into the stack)

La version avec les insersion dans l’array factorisés dans une methode statique est beaucoups moins gourmande en byte code.

Comparaison des deux approches : inline vs factorisée

Chaque ligne du type :
buffer[index++]=’A’
Reviens à faire les opérations suviante:

  1. Charge la référence de buffer dans la pile : Instruction aload
  2. Charge la valeur de index dans la pile : Instruction iload
  3. Charge la constant ‘A’ dans la pile : Instruction iconst
  4. Stock dans le buffer : Instruction bastore
  5. Incremente index : Instruction iinc

Faire cela 3 fois créer donc environ 15 insructions de bytecode.

Comparons cela avec la version factorisée :

index = addBytes(buffer,index,'A','B','C') + index;

Les instructions sont les suviantes :

  1. Charge la référence de buffer dans la pile : Instruction aload
  2. Charge la valeur de index dans la pile : Instruction iload
  3. Charge la constant ‘A’ dans la pile : Instruction iconst
  4. Charge la constant ‘B’ dans la pile : Instruction iconst
  5. Charge la constant ‘C’ dans la pile : Instruction iconst
  6. Appeler addBytes : Instruction invokestatic
  7. Ecriture de la valeur de retour dans index : Instruction istore

En bout de compte la version factorisée consomme 7 instructions de bytecode.

Comparaison des deux approches :

L’approche inline consomme 5 instructions par byte écris dans l’array (soit 15 instructions pour 3 bytes). L’approche factorisée en écrivant 3 bytes d’un coups consomme 7 instructions pour les trois bytes, donc en fonction du nombre d’écritures faites dans le code le gain est de l’ordre de 50% :

Nombre de bytes écris Nombre d’instructions inline Nombre d’instructions fatorisé Gain
3 15 7 53%
6 30 14 53%
60 300 140 53%

Avec une versions d’addBytes qui écris 5 bytes en un seul appel le gain devient de l’ordre de 60%.

Conclusion

Ainsi une connaissance plus fine du fonctionnement du bytecode permet d’optimiser la taille d’un code JavaCard, ceci dit, comme toujours lors de l’optimisation cela reste un tradeoff entre la performance et la taille : la version factorisée nécessite un invokestatic qui est plus gourmand en performance que une simple instruction astore.

Quelques références utiles :

  1. Specifications de la JVM
  2. Liste des instructions du bytecode java
  3. Intro au bytecode sur wikipediat