Tech Days 2013 – Session plénière du mardi 12 février

Comme d’habitude, la plénière est ouverte en musique, avec un excellent groupe Rock, dont j’ai appris un peu plus tard qu’il s’agissait de Microsoftees. Je pensais qu’ils étaient pro, vu le niveau !

1-Musiciens

Eric Mittelette prévient ensuite rapidement qu’il faut faire gaffe à notre nuque. Je n’ai pas trop compris pourquoi, jusqu’à ce que je vois des ballons de 3 mètres de diamètre qui nous descendaient dessus ! Marrant… surtout que les premiers rangs s’amusaient à faire remonter les balles de façon que les gars qui voulaient les ranger n’arrivaient plus à les attraper. On est vraiment des sales gosses Sourire

2-Balles

Une analogie est faite sur toute la durée de la session entre le développement et la cuisine. Les développeurs étant comparés à des chefs, ce qui ne va pas toujours de soi, mais bon, la comparaison est correcte dans le sens où ce que nous faisons ressemble parfois à une drôle de cuisine… Par contre, il faudra éviter d’inviter des stars féminines de la télévision, parce qu’Eric Vernié avait du coup un peu de mal à se rappeler de quoi il voulait parler Sourire

Premier enseignement : désormais, tout est service. Logiciels, API, partages de documents, réseaux sociaux, etc. sont unifiables sous le concept d’un service dans le sens où il réalise un besoin unitaire d’un utilisateur ou d’un autre service. Le tout en multi-device bien sûr.

Du coup, trois points importants :

  • la synchronisation multi-device, pour suivre le parcours utilisateur
  • le design, pour la continuité d’expérience entre les différents devices
  • la donnée comme cœur de l’application (il sera d’ailleurs beaucoup question de Big Data sur ces Tech Days

Windows Azure Active Directory : solution pour des besoins d’authentification déléguée

http://www.microsoft.fr/spark propose d’aider les startups avec une salle et des personnes dédiées dans Paris, dans le sentier. 300 m² dans lesquels chacun peut venir proposer une idée, trouver du conseil.

Eric Mittelette revient sur le mouvement Fier d’être  développeur, qui démarre pour de bon cette année, avec les tee-shirt qui sont distribués, et du beau monde dans les premiers membres. Pour rappel, cette association est dans la droite lignée des mouvements comme le Software Craftsmanship, et a pour but de valoriser le travail du développeur.

Visual Studio est présenté comme le point de rassemblement unique du multi-écran (au sens écran PC ou portable, écran tablette ou smartphone, écran TV ou console). Le passage de contexte d’un mobile a un PC est montré sur un exemple d’application de choix de cocktail sur un portable, puis commande des ingrédients depuis le PC, et enfin invitation automatique par mail qui détecte l’adresse et affiche la carte sur un smartphone. Pour finir, on envoie la vidéo de la recette sur la Xbox, pilotée par la voix. La démo fait un peu artificielle, on sent que les présentateurs voulait absolument faire voir tous les devices, mais ca reste assez démonstratif de ce qu’on peut atteindre.

Démo du framework Fakes, et on en profite pour filer la métaphore qui a guidé la session, avec le testeur comparé au goûteur dans la cuisine. L’approche est complémentaire des frameworks de génération de mocks : l’idée, dans le cas de Fakes, est d’intercepter n’importe quelle fonction, et de la remplacer à la volée par une implémentation sur mesure dans un contexte de programmation limité par sa portée, un peu comme un using. Pour cela, le framework crée d’abord une librairie qui mime celle “faked”, et qui prend sa place dans les références. Pour ne pas trop surcharger, il est possible de restreindre les classes à simuler, sachant que par défaut, Fakes prend tout.

Team Foundation Service est désormais disponible sur http://www.visualstudio.com : il s’agit ni plus ni moins qu’un TFS accessible en mode service pour les petites équipes. Codeplex était déjà basé sur un TFS disponible à distance, mais là, c’est du vrai SaaS. Vraiment intéressant.

Moins intéressant (enfin, perso), HDInsight est le Hadoop sur Azure. Le projet a visiblement abouti, et est donc désormais disponible en production. Ca reste du Big Data, donc une tentative de remplacer de la cervelle par des énormes ressources matérielles, mais au moins, en mode Cloud, ça aura moins d’impact sur l’environnement car les serveurs seront simplement affectées à d’autres applications, qu’on peut espérer plus utiles.

Commandes Linux disponibles pour piloter Azure et les sites web, puis faire un déploiement depuis GitHub. Même chose évidemment dans Visual Studio en publiant après avoir téléchargé le profil de publication. Ca illustre l’ouverture de Microsoft sur les logiciels externes, et c’est plutôt une bonne nouvelle. L’intégration semble en plus très bien faite : pas de plugin ou de configuration bizarre, le lien GitHub est disponible dans l’interface par défaut. Exactement le genre d’outil qu’il faut pour démocratiser le déploiement continu des services. Encore que les outils ne sont en général pas le problème pour l’adoption de ce genre de pratique.

L’utilisation de SignalR est ensuite montrée pour recréer une application de chat. Très peu de code à réaliser. Je ne rentre pas dans le détail car je n’ai pas assez pris de notes sur ce point. Cet exemple sert de base pour démontrer l’élasticité complète de la montée en charge. La démo se poursuit ensuite sur les machines virtuelles disponibles sur Azure, qui est donc dorénavant aussi un service IaaS. VMDepot met à disposition des images préinstallées avec de nombreux OS vierges ou avec une application phare. Il est par exemple possible de trouver une image de Debian, ou une image Linux+Tomcat. De plus, la maintenance est prise en compte, apparemment, même si ça reste à vérifier dans le temps. Dans une autre session, un développeur Debian interviendra pour expliquer que la communauté Debian à participé aux modifications nécessaires pour que cet OS fonctionne dans Azure. Bref, Azure est gentiment en train de devenir aussi ouvert voire plus que le Cloud d’Amazon.

C’est ensuite un designer qui intervient, et les présentateurs insistent sur le fait que cette fonction est de plus en plus importante. Je ne peux que les approuver, étant moi-même une nullité retentissante en UI/UX. La première comparaison réalisée par le designer (je n’ai malheureusement pas noté son nom, mais nous le verrons désormais dans l’équipe des évangélistes – c’est en soi une information, ou à tout le moins un signe, d’ailleurs) est entre une application orientée colonne sur un écran PC en 16/10, et la même application correctement orientée sur une tablette Modern UI. Evidemment, on gagne de manière phénoménale en espace. A noter que le designer n’exclue pas l’utilisation du multiscroll sur mobile. Jusqu’à maintenant, j’avais toujours entendu dire qu’il fallait se limiter à une seule direction de scroll, mais bon…

Un nouvel acronyme, les applications SOLOMO, pour SOcial + LOcale + MObile. Démo d’après insistant sur la personnalisation de Windows Phone 8, en passant de l’information sur l’écran de verrouillage ou d’accueil, ce qui encourage l’utilisateur à aller plus souvent sur l’application, ou en tout cas lui facilite la vie pour être au courant sans avoir à chercher activement l’information dont il veut avoir connaissance. C’est là qu’on voit que des ergonomes ont bossé sur ModernUI.

WalletTransactionItem est la classe pour piloter le portefeuille dans WP8, et WalletAgent est celle qui permet de mettre à jour en mode push. Pour le NFC, on déclare simplement un protocole de type monappli:// dans le manifeste d’application.

Il y a désormais un objet JsonArray pour lire du JSON depuis .NET, donc plus besoin d’API externe comme JSON.NET, d’après ce que j’ai compris.

Au final, une bonne session bien orientée développeurs, comme toujours pour le premier jour des Tech Days, la seconde étant plutôt dédiée aux IT, et la troisième aux décideurs, ce qu’on constatera encore une fois en cette septième édition des Tech Days.

Un lien sur un VRAI site, pour un compte-rendu de VRAIS journalistes : http://pro.clubic.com/it-business/cloud-computing/actualite-540886-techdays-2013-tfs-microsoft-cloud-services-developpeurs.html

Posted in Retours | Tagged | Leave a comment

Optimisation d’échanges de titres par algorithmes génétiques

Le problème

Comment fait-on quand on ne trouve pas un algorithme élégant qui solutionne mathématiquement un problème, en donnant une solution parfaite ? On transige, en bon développeur pragmatique…

Prenons le cas d’un échange de titres dans le cadre d’un rachat des actions d’une société. Imaginons que nous ayons N vendeurs possédant chacun un nombre entier d’actions, et M acheteurs, souhaitant acheter chacun un nombre entier d’actions, le total des actions vendues étant évidemment égal au total des actions achetées.

image

Si on aligne bêtement les vendeurs et les acheteurs, on voit sur l’exemple ci-dessus qu’il faudrait un échange de trois actions entre le vendeur 1 et l’acheteur 1, puis d’une action entre le vendeur 1 et l’acheteur 2, deux entre le vendeur 2 et l’acheteur 2, etc.

D’instinct, en mettant dans l’ordre des plus gros détenteurs et des plus gros vendeurs respectivement, on se dit qu’on doit pouvoir réduire le nombre de chèques échangés, mais ça n’a rien d’une réelle optimisation, car il suffit d’un décalage d’une seule action pour mettre par terre tout un bel alignement.

Par contre, il y a peut-être un algorithme pour aligner correctement, mais perso, je ne suis pas un crack en maths, et j’ai eu beau retourner ça dans ma tête pendant quelques heures, je n’ai pas trouvé la recette miracle.

Le principe

Du coup, on va passer à un autre mode d’optimisation, pas parfaite, mais avec de bonnes chances de tomber sur un optimum relatif. De toute façon, on n’est pas à un échange prêt, seule la précision sur les nombres d’actions est importante. Ensuite, s’il y a un ou deux échanges de plus que l’optimal absolu, pas grave… Bref, algorithmes génétiques à la rescousse !

L’idée des algorithmes génétiques est de simuler une optimisation séquentielle en codant les solutions dans des chromosomes, et en réalisant l’équivalent d’une évolution naturelle, à savoir que les solutions qui ont le plus de valeur (dans notre cas, qui nécessitent le moins d’échanges de chèques) seront favorisées pour apparaitre dans la prochaine génération (qui correspond à l’itération). Ces solutions favorisées se croiseront pour produire des solutions qui seront encore meilleures, et dans ce cas elles poursuivront l’évolution, ou bien moins bonnes et elles laisseront la place aux autres.

Après quelques itérations, on voit en général une stabilisation des solutions. Si on a bien réglé le calcul, les solutions trouvées sont assez proches de l’optimum. Toute la difficulté dans les algorithmes génétiques est de faire en sorte de ne pas étouffer la diversité génétique : il faut donc un algorithme de sélection qui secoue bien les gènes et créent des chromosomes suffisamment différents pour que certains soient meilleurs que leurs ancêtres. Mais il faut bien sûr équilibrer avec une fonction permettant de trier les meilleurs chromosomes, et c’est le rôle de la fonction d’évaluation (souvent appelée fitness) qui est utilisée pour supprimer les chromosomes les moins adaptés.

L’outillage

Mais passons à la pratique. Nous allons pour cela commencer par créer un projet de test dans Visual Studio :

image

Puis, nous utiliserons le gestionnaire de références pour ajouter la librairie AForge.Genetic ainsi que ses références. C’est beaucoup plus simple avec NuGet qu’auparavant…

image

Choix du chromosome et du codage

La première chose à faire avant de coder est de réfléchir à la façon de faire tenir l’information nécessaire aux algorithmes génétiques sur un chromosome. Dans notre cas, c’est relativement simple : AForge fournit un chromosome de base de type ShortArrayChromosome, qui embarque un tableau d’entiers. Nous allons donc utiliser le début pour stocker l’ordre des vendeurs et la seconde pour stocker l’ordre des acheteurs. Dans notre exemple, nous allons prendre 10 vendeurs et 32 acheteurs, et nous aurons donc besoin d’un chromosome avec 42 entrées :

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using AForge.Genetic;

namespace AlgoGenActions
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            IChromosome IndividuRacine = new ShortArrayChromosome(42);
        }
    }
}

Attention, ce chromosome contient bien l’ordre des vendeurs et acheteurs, et non pas le nombre d’actions que possèdent ou veut acheter chacun. Ce nombre est fixe par personne, et ne servira que lors du calcul de la valeur de la solution portées par le chromosome.

Création de la fonction d’évaluation

Justement, c’est la fonction d’évaluation (ou fitness) qui va gérer ceci. Pour commencer, nous créons une classe pour implémenter AForge.Genetic.IFitnessFunction :

class FitnessRepartitionActions : IFitnessFunction
{
    public double Evaluate(IChromosome chromosome)
    {
        throw new NotImplementedException();
    }
}

Avant même de se poser la question de la méthode de calcul (eh oui… il va quand même falloir qu’on fasse un peu d’algorithmes, sinon ce ne serait pas marrant), il faut qu’on donne le nombre d’actions de chaque vendeur et acheteur :

ushort[] Vendeurs = new ushort[] { 911, 612, 712, 276, 520, 491, 280, 110, 134, 1 };
ushort[] Acheteurs = new ushort[] { 48, 48, 320, 250, 115, 110, 253, 665, 69, 10, 412, 82, 30, 30, 30, 150, 30, 300, 100, 35, 30, 60, 70, 60, 350, 30, 50, 100, 30, 30, 150 };

L’étape d’après consiste, dans la fonction Evaluate, à récupérer l’état du chromosome courant :

ushort[] genes = ((ShortArrayChromosome)chromosome).Value;

Les 12 premiers gènes représentent l’ordre des vendeurs. Nous allons nous en servir pour créer la liste ordonnée des nombres d’actions vendues. L’algorithme est un peu spécial, car le contenu des gènes n’est pas comme on le souhaiterait un numéro de vendeur, garantissant qu’il ne sera pas répété. Chaque gène peut prendre n’importe quelle valeur de ushort, y compris des valeurs similaires, alors qu’un même vendeur ne vend pas deux fois ses actions.

Il nous faut donc un mécanisme un peu spécial qui commence par ramener le ushort à la taille de l’offset maximum pour cibler le prochain vendeur, c’est-à-dire le nombre de vendeurs décrémenté d’une unité, puis utiliser un tableau stockant les positions restant disponibles pour être sûr de ne pas dupliquer l’information. Au final, ça donne ceci :

int NBVENDEURS = Vendeurs.Length;
int[] positionsVendeurs = new int[NBVENDEURS];
List<int> positionsRestantes = Enumerable.Range(0, NBVENDEURS).ToList();
for (int i = 0; i < NBVENDEURS; i++)
{
    ushort gene = genes[i];
    int offset = gene % (NBVENDEURS - i);
    positionsVendeurs[i] = positionsRestantes[offset];
    positionsRestantes.RemoveAt(offset);
}
ushort[] vendeursOrdonnes = new ushort[NBVENDEURS];
for (int i = 0; i < NBVENDEURS; i++)
    vendeursOrdonnes[i] = Vendeurs[positionsVendeurs[i]];

On n’oublie pas bien sûr d’ajouter les deux using qui vont bien :

using System.Collections.Generic;
using System.Linq;

L’étape suivante consiste à répéter exactement le même code pour obtenir la liste ordonnée des actions achetées. Puis, on peut passer au calcul de fitness proprement dit. Là, c’est relativement simple : on compte simplement le nombre de frontières totales, c’est-à-dire les passages d’un vendeur à l’autre ou d’un acheteur au suivant, en ne comptant simplement pas les cas où ça tombe pile. Bref, on compte le nombre de lignes en pointillés sur le premier schéma tout en haut de cet article.

List<int> frontieresActions = new List<int>();
ushort cumulActions = 0;
for (int i = 0; i < NBVENDEURS; i++)
{
    cumulActions += vendeursOrdonnes[i];
    frontieresActions.Add(cumulActions);
}
cumulActions = 0;
for (int i = 0; i < NBACHETEURS; i++)
{
    cumulActions += acheteursOrdonnes[i];
    if (!frontieresActions.Contains(cumulActions))
        frontieresActions.Add(cumulActions);
}

Il ne nous reste plus alors qu’à renvoyer un double entre 0 et 1, sachant que plus le nombre est haut, plus le chromosome évalué porte une solution intéressante. Pour cela, on utilise une simple fonction affine inversant le nombre de frontières. En effet, plus celui-ci est élevé, moins la solution portée par le chromosome est bonne.

En théorie, le nombre minimal de chèques est égal à Max(N, M), tandis que le nombre maximal est certainement autour de deux fois ce nombre minimal (peut-être décrémenté d’une unité…). On peut donc écrire le code ci-dessous :

double Valeur = 2.0 - (1.0 / Math.Max(NBVENDEURS, NBACHETEURS)) * frontieresActions.Count;
return Math.Max(0, Math.Min(1, Valeur));

La classe de fitness est terminée.

Création de la fonction de sélection

Pour compléter les deux faces des algorithmes génétiques, il faut, en plus de la fonction de fitness, une fonction de sélection, c’est-à-dire une méthode qui va créer une nouvelle population à partir d’une ancienne, en brassant les gènes pour essayer de faire apparaître des individus plus adaptés.

Il existe des fonctions de sélection standards qui sont fournies avec AForge.Genetic, comme EliteSelection ou RouletteSelection, mais nous proposons ici d’utiliser une fonction spécialisée qui mélange un peu ces deux comportements :

class RouletteEliteSelection : ISelectionMethod
{
    public void ApplySelection(List<IChromosome> chromosomes, int size)
    {
        // On commence par reprendre systématiquement le meilleur chromosome
        List<IChromosome> NouvelleGeneration = new List<IChromosome>();
        double BestFitness = 0.0;
        foreach (IChromosome Chromosome in chromosomes)
            BestFitness = Math.Max(BestFitness, Chromosome.Fitness);

        IChromosome MeilleurChromosome = chromosomes.Find(delegate(IChromosome Chromosome)
        {
            return Chromosome.Fitness == BestFitness;
        });

        NouvelleGeneration.Add(MeilleurChromosome);
        double TotalDesFitness = 0.0;
        chromosomes.ForEach(delegate(IChromosome Chromosome)
        {
            TotalDesFitness += Chromosome.Fitness;
        });

        // Ensuite, on choisit au hasard le reste de la population, en donnant d'autant
        // plus de chance d'appartenir à la nouvelle génération que la fitness est élevée.
        Random Generateur = new Random(DateTime.Now.Second + DateTime.Now.Millisecond);
        while (--size > 0)
        {
            double PositionHasard = Generateur.NextDouble() * TotalDesFitness;
            double FitnessCumulee = 0.0;
            foreach (IChromosome Chromosome in chromosomes)
            {
                FitnessCumulee += Chromosome.Fitness;
                if (FitnessCumulee > PositionHasard)
                {
                    NouvelleGeneration.Add(Chromosome);
                    break;
                }
            }
        }

        chromosomes.Clear();
        chromosomes.AddRange(NouvelleGeneration);
    }
}

Cette classe n’est peut-être pas le top de ce qu’on peut faire, car elle ne fait pas de croisement, et n’empêche pas de reprendre plusieurs fois le même chromosome, mais elle ne fonctionne au final pas trop mal. Pour les résultats finaux (voir plus bas), on utilisera plutôt une simple EliteSelection, qui au moins est validée. Bref, je la fais plus voir pour expliquer ce qu’on peut faire, mais si on veut vraiment la mettre en oeuvre en production, il vaudrait mieux la valider fortement, ou au moins la réécrire en fonction de fonctions elles-mêmes déjà validées.

Lancement

Revenons à notre méthode de tests. Il nous faut créer un objet représentant la population de chromosome, ou en termes plus techniques le génome souhaité :

Population Population = new Population(100, 
    IndividuRacine, 
    new FitnessRepartitionActions(), 
    new RouletteEliteSelection());

Cette population porte le nombre de chromosomes à générer par itération, le chromosome que nous avions défini au départ qui sert de clone de base, plus une instance de la classe de fitness, et enfin une instance du mécanisme de sélection que nous avons créée également. Nous pouvons ensuite passer à l’exécution proprement dite, en utilisant le code ci-dessous :

int Iteration = 0;
ShortArrayChromosome Meilleur = null;
while (Iteration++ < 500)
{
    Population.RunEpoch();
    Meilleur = (ShortArrayChromosome)Population.BestChromosome;
}

A la fin de l’exécution des tests, on espère avoir une fitness pour la meilleure solution trouvée après les 500 itérations sur 100 chromosomes d’au moins 70% :

Assert.IsTrue(Meilleur.Fitness > 0.7);

On pourrait jouer sur quelques paramètres des algorithmes génétiques, mais il se trouve que leur valeur par défaut est très bien ajustée dans notre cas simple d’utilisation :

//Population.AutoShuffling = false;
//Population.CrossoverRate = 0.01;
//Population.MutationRate = 0.01;
//Population.RandomSelectionPortion = 0.5;

Voila : le programme est prêt à tourner. Vous pouvez le récupérer dans sa version complète à partir de ce lien.

Résultats

Le test passe correctement, avec une fitness de 84% au final. Attention, la partie aléatoire constitutive des algorithmes génétiques fait que vous pouvez trouver une fitness différente au final.

L’évolution de la fitness peut être suivie en modifiant légèrement le code comme ceci :

// Boucle sur les époques de la population
int Iteration = 0;
ShortArrayChromosome Meilleur = null;
using (StreamWriter Scribe = new StreamWriter(@"resultats.csv"))
{
    while (Iteration++ < 500)
    {
        Population.RunEpoch();
        Meilleur = (ShortArrayChromosome)Population.BestChromosome;
        Scribe.WriteLine(Meilleur.Fitness);
    }
}

Le résultat ressemble alors à :

image

Cette évaluation correspond à une petite quarantaine de chèques à échanger, soit une belle optimisation par rapport aux 64 chèques en théorie si on n’avait pas cherché à ordonner les acheteurs sur les vendeurs.

En espérant que ça vous donne envie d’essayer les algorithmes génétiques, qui sont relativement simples à mettre en place, et permettent de se sortir de situations compliquées à peu de frais.

Posted in .NET, C# | Tagged | Leave a comment

50 astuces de performance pour ASP.NET

Red Gate vient de publier un e-Book gratuit avec 50 conseils de performance pour ASP.NET. Ce livre fait suite à un concours, et regroupe les meilleures astuces de plein de développeurs de la communauté. Pour avoir écrit un bouquin sur le sujet, je peux vous dire que cette cinquantaine de pages est une mine !

Le livre est sur http://www.red-gate.com/products/dotnet-development/ants-performance-profiler/entrypage/avoid-find-fix-asp-problems

50 Ways to Avoid, Find, and Fix ASP.NET Performance Issues cover

Comme je fais partie du panel de juges pour déterminer le gagnant de la tablette Surface RT, j’ai étudié en détails les 50 (en fait 51) conseils, et j’ai eu du mal à trier les 20 que je trouvaient très bons, les 10 excellents, et au final, j’avais beau filtrer et filtrer, je n’arrivais pas à trouver comment descendre en dessous de 6 qui devraient absolument être enseignés à chaque développeur.

En fait, presque tous devraient être obligatoires pour quelqu’un qui doit programmer du ASP.NET pour la production ! Bonne lecture, donc Sourire

Posted in .NET, Performance | Tagged , | Leave a comment

FabLab Arduino à Vannes

La semaine dernière, premier atelier Fabrication Lab à Vannes, au VIPE, par Christophe Augier. Une association est montée, qui se réunira tous les mercredis à 20h00 au VIPE, au Parc Innovation Bretagne Sud. Je vous redirige sur le site http://makerspace56.org/ pour plus de détails “administratifs”, et venons-en tout de suite à ce qui nous intéresse le plus : la technique Sourire

Au menu de ce premier mercredi (c’était donc le 9 janvier), programmation d’une carte Arduino. Pour ceux qui ne connaissent pas – comme moi il y a une semaine – il s’agit de ce genre de petite bête :

Matos

Quand je dis “petite”, vous voyez que je n’exagère pas : la carte électronique mesure moins de 10 centimètres dans sa plus grande dimension.

Après une petite difficulté pour installer les pilotes sur Windows 8 (il faut redémarrer avec une option permettant d’accepter temporairement les drivers non signés), on peut brancher la carte en USB, et c’est parti pour un premier montage simple, où on ne fait que piloter le clignotement d’une LED. La carte Arduino possède des sorties dont on peut piloter la puissance en mode digital (ON / OFF), mais aussi des sorties simili-analogiques (avec des pulsations dont le ratio ON / OFF augmente au fur et à mesure de la valeur envoyée, un peu comme dans les trains électriques).

Après, deuxième montage avec un potentiomètre sur les entrées analogiques pour faire varier la puissance dans la LED. L’IDE est simple mais complet, et surtout bourré d’exemples très bien classés, ce qui permet de démarrer facilement, et même – je pense – de progresser dans de bonnes conditions par la suite :

image

Voici par exemple le type de code correspondant à l’exemple Blink :

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
 */
 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Ca ressemble très fort à du Java ou du C#, donc pour moi, c’était idéal. J’avais l’impression que les autres étaient en grande partie à l’aise avec la partie hardware et moi avec le soft, moi c’était l’inverse.

Un truc marrant sur l’Arduino est que le programme se répète toujours : tout est basé sur la boucle, et même quand on fait un reset de la carte, dès qu’elle redémarre, elle repart sur le même programme. Ca paraît logique quand on pense aux usages (domotique, robotique, etc.) mais la première fois, en bon développeur, on se prend à chercher ce qu’on doit lancer !

Ce qui est surtout bien dans le FabLab, c’est qu’on ne se contente pas de faire voir comment faire quelque chose, mais que le “prof” nous explique comment ça marche, pourquoi, et tout ça en détails. Du coup, j’ai enfin compris des bases de l’électronique qui m’avaient toujours posées un problème de compréhension depuis la terminale. Le pont de diode, avec une carte devant soi, c’est tout de suite beaucoup plus compréhensible…

Et puis, surtout, excellente ambiance avec beaucoup de participants. Une quinzaine… La dernière fois que j’ai fait un dojo, on était cinq, en me comptant moi-même : je suis jaloux !

Groupe

J’espère que ça continuera comme ça, surtout après les premières sessions et l’effet de nouveauté. Perso, j’ai rameuté quelques collègues intéressés que j’espère amener un mercredi soir. Et demain, j’y retourne ! Peut-être que dans quelques sessions, Christophe nous permettra de programmer son imprimante 3D Sourire

Imprimante

Posted in Uncategorized | Tagged , | 1 Comment

Noms avec parenthèses dans les interfaces réseau : problème avec les compteurs de performance

Si vous vous retrouvez avec une InvalidOperationException en .NET lorsque vous utilisez les classes PerformanceCounter pour accéder aux compteurs de performance sur les interfaces réseau, avec un message “l’interface n’existe pas dans cette catégorie”, et que le nom de l’interface qui apparaît quand vous faites un ipconfig /all contient des parenthèses, méfiez-vous : elles sont automatiquement tranformées en crochets dans le gestionnaire de performance.

image

Evidemment, si vous mettez des parenthèses dans le code .NET pour accéder aux classes de performance, ça plante… Il faut donc écrire le code de façon à obtenir ceci :

image

Encore une heure de perdue si des trucs tellement bêtes. J’espère au moins que ce message servira ; j’ai essayé de mettre tous les mots-clés qui correspondent à la recherche de mon problème.

Posted in C# | Tagged | Leave a comment

Comprendre Async (troisième étape)

Contexte

Dans l’étape précédente, j’avais promis de revenir sur Async, avec une application plus adaptée.

Pour ceux qui prennent en cours, ces quelques articles ont pour but de faire découvrir Async en montrant toutes les étapes de découverte, y compris et surtout les échecs. Ne prenez donc surtout pas le contenu pour argent comptant : il s’agit de manipulations et de bidouilles destinées à montrer la progression d’une personne pour appréhender les concepts d’Async, en espérant que ça serve à d’autres.

Nous allons donc repartir ce coup-ci d’une application avec GUI. Le problème en effet avec l’application de type Console est qu’elle est fondamentalement basée sur un thread de déroulement ordonné, unique, et donc synchrone. Nous avons besoin d’une application graphique pour montrer le réel intérêt d’Async.

L’application

Pour cela, une bête application simpliste de type WPF suffira. Un bouton pour lancer une commande, une TextBox pour afficher un résultat variable, et roule !

image

Si on travaille en mode synchrone, on utiliserait ce genre de code :

image

Evidemment, entre le moment où on clique sur le bouton et le moment où la GUI rend la main, impossible d’interagir avec elle, car tout fonctionne dans le même thread, qui s’occupe ici de l’affichage et de l’appel à un site web.

C’est précisément le scénario type pour lequel Async a été créé.

Solution à l’ancienne

Le problème étant posé, nous allons d’abord voir comment il était possible, avant Async, de le résoudre. L’idée était de mettre en place de l’asynchronisme, c’est-à-dire la séparation du traitement qui se déroule en parallèle de la gestion de la GUI. Pour cela, on utilisait un évènement de type Completed, et on associe un traitement qui s’occupe de récupérer le résultat du téléchargement pour le traiter :

image

Le problème est qu’on a tellement séparé qu’on se retrouve avec les deux parties du traitement qui se trouvent dans deux fonctions distinctes. Ceci pose problème, car on rompt la lecture du code, et ainsi qu’on ne manifeste pas correctement l’intention du développeur.

Solution de type Async

C’est pour cela qu’il fallait quelque chose de plus propre, comme Async. Async permet de concentrer l’asynchronisme dans une seule et même fonction, qui est syntaxiquement très proche du premier code que nous avions montré et qui était synchrone. Il “suffit” d’utiliser une fonction asynchrone qui renvoie une Task<string>, de rajouter le mot-clé await pour signifier que la TextBox sera remplie lorsque cette tâche sera terminée, et de mettre devant la fonction le mot-clé async, qui est nécessaire dans toute méthode employant l’asynchronisme :

image

Le gros avantage est bien sûr qu’on est très proche du code synchrone, et que la complexité est masquée. En arrière plan, c’est bien une vraie machine à état qui a été déclenchée. Si on jette un oeil avec ANTS Performance Profiler (attention, seule la toute dernière version Beta est capable de gérer de l’asynchronisme), on voit ce mécanisme sur la fonction marquée d’un tag Async (celle sélectionnée), ainsi que dans le code source retrouvé par décompilation (panel du bas), où on voit AyncStateMachine dans les attributs de la méthode :

image

Si on ouvre le graphique correspondant à cette méthode, le profileur de Red Gate nous montre bien le contenu déroulé par cette machine à état :

ANTS

On commence par un Start, puis un MoveNext qui nous amène sur la fonction de téléchargement au final.

Pourquoi cette machine à état ? Tout simplement parce que le mode d’Async est de ne pas utiliser un thread à part, mais bien de rester dans le thread principal en utilisant une machine à état qui se déroule dans ce même thread. Ceci permet d’éviter les problèmes de basculement de threads, traditionnellement associés au retour d’un thread de traitement dans le thread principal, celui de la GUI, pour l’affichage associé en retour.

Gérer l’attente

Après avoir abordé cet exemple simple (et sans avoir parlé de ce qui se passe dans DownloadStringTaskAsync, qui mériterait un autre article le jour où j’aurai suffisamment bien compris le contenu pour en parler), je fais juste un petit détour par autre chose qui m’a permis de comprendre un peu mieux Async. C’est tout bête, mais comme ces articles sont censés montrer tout le cheminement étape par étape de la compréhension d’Async (en tout cas, mon cheminement, en espérant qu’il conviendra à expliquer les concepts à d’autres), je le fais voir quand même.

Supposons que le clic sur un bouton appelle une fonction Attente définie comme ceci :

image

Logiquement, la GUI bloquera pendant les 3 secondes. Si on fait quelque chose qui pourrait paraître similaire dans Async, on a un comportement différent :

image

En effet, pendant les trois secondes, on peut manipuler l’interface. Ce qui se passe est qu’on est entré dans la machine à états, que le thread est repassé au traitement de la GUI, et qu’au bout de trois secondes, le thread est passé sur l’étape suivante de la machine à états, qui a consisté à redonner la main au code au niveau du await. Il se trouve qu’il ne fait rien, mais au moins pendant le délai, on n’a rien bloqué.

Conclusion

Voici pour un troisième article sur Async. Promis, il y en aura un autre quand j’aurai mieux compris ce qui se passe dans la fonction DownloadStringTaskAsync : est-ce qu’elle est elle-même déclarée async ? Comment fonctionne-t-elle ? Comment peut-on utiliser Async pour créer des fonctions avec le même type de fonctionnement ?

Posted in .NET | Tagged | Leave a comment

Tuiles Windows 8 : le nouveau ruban ?

En lisant les nombreux articles critiques sur l’absence de menu démarrer dans Windows 8 (remplacé par les tuiles permettant de lancer les applications), je me rends compte que le cycle et les arguments sont à peu près les mêmes que ce qu’on entendait il y a quelques années quand le ruban a remplacé la barre d’outils dans Microsoft Office…

Le tout premier argument était en général que ça ne servait à rien. Rétrospectivement, on se rend bien compte que l’augmentation en taille des menus ne pouvait pas continuer sans que l’utilisateur ne s’y perde totalement. La plupart des utilisateurs, d’ailleurs, mettait dans leur barre d’icones les principales fonctions dont ils avaient besoin, pour aller vite. De la même manière, il est tout-à-fait vrai qu’on pourrait continuer à utiliser le menu démarrer, mais qui n’a jamais pesté contre le fait qu’il soit par défaut organisé par éditeur, rendant ainsi difficile de trouver un logiciel par son nom ?

Le second argument était que ça nuisait à l’ergonomie. Cet argument est bien sûr à laisser complètement de côté, chacun voyant midi à sa porte, et se prévalant d’un talent d’ergonome parce qu’il est utilisateur averti. Je n’ai pour l’instant vu aucun article critique du ruban ni des tuiles par quelqu’un avec un vrai background d’ergonome. S’il y en a, merci de me mettre les liens dans les commentaires, ça m’intéresserait. Le nouveau modèle d’interface de Microsoft a été pensé par des équipes conséquentes d’ergonomes, et les retours de personnes même traditionnellement pas très orientées Microsoft donnent une bonne idée du boulot réalisé. Que cela ne plaise pas à certains, pas de souci, mais n’invoquons pas le “manque d’ergonomie” si on n’est pas ergonome soi-même.

Le troisième argument est celui asséné en général en désespoir de cause, à savoir que les utilisateurs ne comprennent pas et n’adopteront pas. Une bonne partie de ces commentaires prennent en général l’utilisateur pour un doux crétin, perdu comme un mouton dans la montagne dès qu’un menu change de forme. Une autre partie se drape dans une aura de Cassandre pour prévoir le rejet argumenté et effectif par des millions d’utilisateurs, faisant ainsi montre d’un culot assez stratosphérique.

Bref, ne nous laissons pas embêter par les empêcheurs d’évoluer en rond. Il y a de bonnes chances pour que, tout comme le ruban Office en son temps, après avoir fait coulé des rivières d’encre électronique, les tuiles en remplacement du menu démarrer se coulent gentiment dans le paysage et que plus personne n’en parle. ce qui rejoint très bien la définition que m’avait donnée une ergonome de son métier : faire en sorte que plus personne ne voit son travail !

Posted in Uncategorized | Tagged | Leave a comment

Gagnez une tablette Surface RT avec une astuce de perf en ASP.NET ou SQLServer !

Nos amis de Red Gate ont lancé un petit concours très sympa, et pour récompenser la meilleure astuce de performance en SQL Server ou en ASP.NET, il offre une tablette Surface RT dans chaque catégorie, et en plus votre astuce sera mise dans un livre électronique diffusée à grande échelle !

image

En plus, vous avez vos chances, car je ne participe pas Sourire. Je serai juge ! Donc, tous sur http://www.simple-talk.com/blogs/2012/11/15/application-performance-the-best-of-the-web/ et bonne chance à tous !

Posted in Performance | Leave a comment

Déboguer un “Skipping logentry” dans le WS-I Basic Profile Testing Tool

This article is also available in English.

Les outils du Web Service Initiative permettent de tester un service web en termes de compatibilité avec la norme Basic Profile, et ce de manière statique par une simple analyse du WSDL, mais également en complétant par une analyse dynamique qui se base sur des captures de messages.

Pour cela, on utilise le moniteur fourni comme un proxy / Man In The Middle, qui enregistre et repasse tout ce qu’on fait. Jusque là, pas de souci, mais lorsqu’on passe l’analyseur pour créer le rapport final, on peut se retrouver avec ce genre de message :

image

Là où c’est gênant, c’est bien sûr que ça veut dire que les messages ne sont pas pris en compte, et qu’on retombe sur un bête rapport statique.

Et là où ça devient carrément embêtant, c’est qu’il n’y a vraiment rien sur le net sur ce problème :

image

La seule page trouvée qui y fait référence (quand on restreint la recherche à la première partie, on n’a que deux pages de plus et ce sont des faux positifs) ne fait que poser le problème, sans réponse :

image

Bref, ça commence à pas sentir bon, et il va falloir rentrer dans le code. Heureusement, le WS-I a la bonne idée de fournir une version .NET de leur outil (ils auraient pu mettre les PDB et le source, mais bon). Bref, à l’attaque des différentes DLL, qu’on passe à ILDASM. Je vous donne tout de suite la bonne, c’est WSITest-Assertions.dll qui contient notre message d’erreur. On vérifie ça en ouvrant la librairie dans ILDASM :

image

Puis on fait un dump :

image

On accepte les options par défaut. Rien de compliqué, de toute façon : on ne fait que chercher une chaîne…

image

Pour chercher plus facilement, on enregistre ça sous forme de code IL :

image

Et on peut ensuite ouvrir le fichier qui a été créé. Il se trouve que le message “Skipping logentry” se trouve à trois endroits différents du code, et à chaque fois avec le même sous-message “not from specified service” :

image

En remontant, on trouve la classe et on peut utiliser Reflector ou ILSpy pour voir le code correspondant :

image

Il se trouve que les trois portions de code font appel à la même fonction “Process Message”, qui vient d’une autre librairie :

image

En cliquant sur cette fonction, on passe sur la librairie en question, qui est WSITest-AnalyzerCore :

image

Et à l’intérieur, on arrive bien sur notre fonction ProcessMessage :

image

Quand on regarde le code, on voit qu’il y a un lien avec le mode de corrélation. Logique, puisque c’est le code qui fait le lien entre les paramètres de configuration et ceux en provenant du log. Il faut bien que les logs correspondent au service web étudié :

image

Mais là où se trouve apparemment le problème, c’est que le code ne traite pas le mode de corrélation “operation”. Il ne traite que les cas Endpoint et Namespace :

public bool ProcessMessage(HttpSoapLog logRequest, HttpSoapLog logResponse, CorrelationType correlation, WsdlOperation wsdlOperation)
{
    return this.MessageInEndpoint(logRequest) && (correlation == CorrelationType.Endpoint || (this.MessageInNamespace(logRequest) && (correlation == CorrelationType.Namespace || wsdlOperation != null)));
}

Or, dans le fichier de configuration de l’outil WS-I Basic Profile, à savoir analyzerConfig.xml, la valeur de corrélation proposée par défaut est “operation” :

<logFile correlationType=”operation”>traceLog.xml</logFile>

Du coup, on tente avec un mode de corrélation Endpoint, qui parait plus adapté :

<logFile correlationType=”endpoint”>traceLog.xml</logFile>

Et ça marche ! Les messages du log sont désormais bien pris en compte par l’analyzeur :

image

Question : que ferait-on sans ILDASM / ILSpy ?

Bon, je sais la réponse en fait : on enverrait un mail au WS-I pour leur demander de corriger, mais la FAQ n’est pas technique, et il n’y a qu’une adresse pour les commentaires généraux (ni beaucoup d’activité sur les outils, d’ailleurs). Du coup, à part déboguer soi-même, point de salut rapide…

En espérant que ça serve à quelqu’un !

Posted in Retours | Tagged | Leave a comment

Travaux Pratiques sur Kinect en Test Driven Development

Le TDD à l’ancienne

Je fais de temps en temps des cours / TD ou TP à l’Université : ça oblige à formaliser les connaissances, à prendre du recul sur les méthodes, et c’est sympa de rester au contact de jeunes qui n’ont pas leur langue dans la poche pour critiquer un bout de code, une approche, etc.

Jusque l’an passé, je leur parlais de Test Driven Development à partir d’un algorithme supposé compter les mots dans une phrase. On partait du cas le plus simple possible :

image

Puis je leur demandais d’ajouter de plus en plus de tests, et de faire en sorte que l’algorithme suive, sans toutefois prendre trop d’avance sur ce qui était réellement nécessaire.

image

Après un peu de temps, on trouvait des cas un peu plus compliqués, et en général, les deux heures habituelles étaient passées.

image

De temps en temps, je fais ce TP en mode attaque / défense, en séparant les groupes en deux équipes de deux ou trois personnes : la première s’occupe uniquement de créer un test en plus pour faire planter l’algorithme, et la seconde s’occupe de faire la correction minimale pour que les tests passent.

Lors de la première itération, beaucoup d’étudiants ont du mal à comprendre pourquoi la fonction SUT prend la forme simpliste suivante :

image

Je dois bien avouer que cette approche “do the simplest thing that can possibly work” m’a souvent causé des noeuds aux méninges. Dans ma conférence “Architecture et Agilité : réconcilier les frères ennemis”, j’expose d’ailleurs mon point de vue dessus, à savoir que je trouve YAGNI supérieur en utilisabilité et en simplicité (point de vue binaire, au lieu de qualitatif). Or, cette première version de mon TP sur le TDD ne permettait pas vraiment d’aborder ce sujet. Il se trouve que la deuxième version, plus ludique, le fait apparaître, et ce sans même que je l’ai prévu à l’origine. Mais j’anticipe sur les résultats.

Un peu plus ludique grâce à la Kinect

Déjà, je souhaitais faire quelque chose de tout simplement plus fun. Vous savez comment sont les étudiants : dès que vous faites un truc un peu trop académique, certains sont fainéants, et ne veulent pas faire l’effort intellectuel pour s’approprier le problème. A l’inverse, si vous faites quelque chose de ludique, pas un seul à regarder en douce son portable ou son compte Facebook sur l’ordinateur de TP quand vous n’êtes pas derrière…

Du coup, quand on leur fait voir ceci, tout le monde cherche la solution du TP :

L’algorithme ciblé est tout simplement une recherche de lettres correspondant au positionnement du squelette. Pour faire simple, voici le A :

image

Ensuite, le C :

image

Ensuite, le M (cas un peu plus compliqué parce que le triangle Centre Epaule – Main Droite – Main Gauche est le même que pour une lettre A) :

image

Et en dernier le Y :

image

Le principe du TP est lui aussi simple : de la même manière que, dans une équipe de développement, il y a beaucoup moins de testeurs que de développeurs, dans le groupe de TP, il y a une vingtaine d’étudiants, mais une seule Kinect. Il est donc bien entendu hors de question que chacun transbahute son code par clé USB sur mon ordinateur pour tester à chaque fois qu’il réalise un changement dans son algorithme.

En ce sens, le capteur physique Kinect simule le goulet d’étranglement de la Quality Assurance dans une équipe de développement.

Approche TDD

Pour faciliter l’approche, je vais jusqu’à donner aux étudiants les deux premiers cas de test :

image

Ensuite, le TP permet de montrer que la signature de la fonction doit évoluer au fur et à mesure des tests, et donc qu’il y a bien émergence du code, y compris dans sa signature. En effet, pour traiter le M, on est obligés de rajouter deux points correspondant aux coudes. On les rajoute bien sûr à la fin pour la compatibilité ascendante, et on vérifie que les tests unitaires fonctionnent toujours bien.

Pour simplifier le TP pour ceux qui ne font pas trop de POO, je fais réaliser la signature avec des entiers plutôt que des instances de Point.

Premiers algorithmes, et coup de chaud pour le prof

Une fois les premières itérations réalisées sur ces quatre premières lettres cibles, je commence en général à avoir quelques premiers algorithmes qui font passer les tests unitaires de reconnaissance lettre par lettre au vert.

Et là, grosse frayeur : les premiers algos fonctionnels sont bien plus simples que celui que je leur ai préparé comme correction ! Le honte se profile Sourire. Voici par exemple le code d’un étudiant pour la détection de la lettre Y :

image

Simple, efficace : la lettre Y est la seule pour laquelle les deux mains sont au dessus des épaules (à noter que l’axe y augmente vers le bas pour le repère Kinect). Rien à redire là-dessus : je leur avais bien dit “le plus simple algorithme qui fasse passer les tests”.

Et moi, derrière, je n’ai pas l’air fin avec le mien :

image

Surtout qu’il faut en plus la fonction APeuPresEgal ci-dessous :

image

Et que, cerise sur le gâteau cageot, elle-même a besoin de EstEntre :

image

Pour un codeur “professionnel de l’agile”, ça s’annonçait mal…

Mais 25 ans d’expérience feront toujours la différence !

Je commençais à sentir le souffle de la guillotine sur ma nuque quand je me suis rendu compte que la faible différence entre A et M allait me sauver. Dans le même ordre d’idée, les étudiants avaient codé la reconnaissance de la forme A comme la seule avec les mains en bas, et à condition que les coudes ne soient pas au même niveau en x que les mains (sinon, il s’agit d’un M). Du coup, que se passe-t-il quand les mains passent de Y à M ? En descendant, il est extrêmement difficile d’avoir déjà les avant-bras verticaux au moment où les mains passent en dessous des épaules.

Résultat : aucun n’a réussi, malgré les 4 tests unitaires en vert, à écrire YMCA !

Le logiciel affichait toujours ceci :

image

Seul Olivier (félicitations à lui) a réussi à créer une itération supplémentaire avec le bon test et la modification de l’algorithme pour pouvoir passer le test et arriver ainsi à ceci :

image

Conclusion

Finalement, j’ai appris moi-même peut-être autant que mes étudiants sur ce TP. Ca faisait longtemps que cette idée de “simplest thing that could possibly work” m’embêtait, mais je ne trouvais pas de contre-exemple. Et bien en voici un… En faisant le plus simple possible pour chacune des lettres, on s’est d’une certaine manière forcés à réaliser un algorithme strict. Sans cette restriction, je suis parti sur un algo un peu plus souple, qui a dès le début été propre pour gérer les transitions d’une lettre à une autre.

Evidemment, en théorie, il aurait fallu commencer par faire les tests unitaires de transition d’une lettre à l’autre, mais :

  1. Ils sont beaucoup plus nombreux
  2. Ils sont complexes à réaliser, car fonctionnant avec n échantillons poussés à la suite
  3. Le rendement est moins bon au final, car on serait arrivés à l’algorithme souple en seconde version
Posted in Uncategorized | Tagged | Leave a comment