Naming conventions, xml doc et warnings

26. February 2011 13:02 by Renaud in   //  Tags:   //   Comments (0)
Cette semaine, Pierre a mis les choses au clair ! ^^ Premièrement, il ne veut plus voir de variables, de classes ou de méthodes nommées n'importe comment. Interdiction évidemment de nommer en français! Vous trouverez ici l'ensemble des règle Microsoft : http://msdn.microsoft.com/en-us/library/ms229002.aspx Deuxièmement, il nous a demandé de tout documenter (toujours en anglais évidemment!) C'est vrai que plus on attend avant de le faire, plus c'est fastidieux! Il nous a conseillé un plugin pour Visual Studio qui s'appelle GhostDoc et qui aide à générer la doc. C'est très pratique si justement vous respectez bien les conventions de nommage! Prenons par exemple une méthode avec la signature suivante: public bool IsVisible(), un petit coup de GhostDoc et hop!
        /// <summary>
        /// Determines whether this instance is visible.
        /// </summary>
        /// <returns>
        ///   <c>true</c> if this instance is visible; otherwise, <c>false</c>.
        /// </returns>
        public bool IsVisible()
        {
            // insert code here
        }
Voilà maintenant y'a plus d'excuse pour ne pas faire la doc :) Téléchargez GhostDoc ;) Troisième et dernière chose, à partir de maintenant il faut activer le code analysis dans les properties comme ceci: - On coche Enable Code Analysis on Build et dans Rule Set on choisit Microsoft All Rules

Désormais, on doit considérer que chaque warning est une erreur!   Voilà en gros ce à quoi j'ai passé les premiers jours de la semaine! J'avais pas mal de soucis au niveau des conventions de nommage... Notamment dans ma base de données que j'ai dû complètement revoir du coup. Au niveau des commentaires, la plupart étaient en français! ^^ Il a donc fallu traduire ça du mieux que je le pouvais. Ca m'a pris un peu de temps mais je sais que c'est du temps que je gagnerai plus tard, ou que d'autre gagneront quand ils devront relire mon code!

[WP7] La classe WebClient et le cache sur Windows Phone 7.

16. February 2011 22:02 by Renaud in   //  Tags:   //   Comments (3)

Background story:

Pour l'application que je réalise durant mon rarissime temps libre, je travaille beaucoup avec la classe WebClient. J'ai en fait un projet ASP.NET qui répond à des requêtes POST envoyées par des WebClient depuis mon téléphone. En présentant une ébauche de mon application à des amis, je me suis rendu compte qu'il y avait un petit soucis: Au lancement de l'application, une requête est faite pour savoir si je suis enregistré sur mon service. Si c'est le cas, un bouton s'affiche pour me proposer de me désinscrire. Si par contre je ne suis pas enregistré, un autre bouton me propose de m'inscrire. Dans les deux cas, après l'inscription ou la désinscription, je refaisais une requête pour vérifier mon nouveau statut. Lorsque je m'inscrivais, la réponse était positive pour me dire que l'inscription avait bien fonctionné, mais étrangement, lors de la vérification de mon statut, la réponse était que je n'étais pas inscrit. Ce scénario était le même pour la désinscription: tout se passe bien, mais à la vérification, il semblait que j'étais toujours inscrit. Jusque là, le problème pourrait encore venir de moi. Mais il faut savoir que si je quittais l'application pour la relancer juste après, mon statut était correctement mis à jour! So what? J'ai un peu retourné tout mon code, après quoi j'ai filé mon projet à Kévin Rapaille pour qu'il jette un oeil également puisque deux yeux valent mieux qu'un tiens tu l'auras! Et là, en blaguant, Kévin me dit "bah chez nous, quand un truc marche pas, on dit que c'est à cause du cache :) " et de là on en est arrivé à se dire que non, ce n'était peut-être pas si con! Parce que oui, il faut le savoir, le WebClient dans Silverlight pour WP7 utilise le cache. Ca signifie concrètement que dans le cycle de vie d'une application WP7, si vous appelez plusieurs fois la même URI, et ça même avec des instances différentes de WebClient, le résultat sera toujours le même! Il est où ce cache? Je n'en sais trop rien et je n'ai pas trouvé comment le vider, mais par contre on a une petite alternative: pour chaque requête, insérez une clé unique quelque part dans l'URI. Kévin m'a proposé un timestamp, ce qui me plaisait bien :-) Finalement j'ai ajouté dans toutes mes requêtes l'heure actuelle en seconde, ce qui évitera, à moins d'être vraiment un acharné, d'avoir deux requêtes identiques :-)  

Scénario:

Imaginez que votre application WP7 aille lire le flux rss de votre blog et permette de rafraichir la liste des articles: Vous affichez vos articles une première fois sur votre Windows Phone, et juste après vous publiez un nouvel article. Si vous tentez maintenant de rafraîchir la liste des articles sur votre Windows Phone, rien ne se passera.

Solution simple:

Faire en sorte de créer des URI uniques en ajoutant une variable de cette façon:
String myURI = String.Format("http://www.myuri.com/rss&key={0}",
                               Environment.TickCount);
Environment.TickCount retourne le nombre de milli-secondes écoulées depuis le lancement de l'application, ce qui vous assure une clé unique :-)  

Base de données - Suite (2)

15. February 2011 21:02 by Renaud in   //  Tags:   //   Comments (0)

Ca avance petit à petit :) J'ai commencé par créer la base de données, à partir de laquelle j'ai créé un modèle Entity Framework 4. Ensuite, j'ai commencé l'implémentation du Repository Pattern. En fait, les difficultés maintenant ce sont: 1°) Le fait que les anciens appels à la base de données soient dispersés un peu partout. On a une partie, dont l'authentification, dans un projet utilisant LinqToSql, et une autre partie utilisant des SQLCommand. 2°) La base de données a fondamentalement évolué. La multiplicité, les relations a changé. Toutefois, le projet a déjà un certain nombre d'utilisateurs, et il faut récupérer les anciennes données pour les stocker dans la nouvelle base. Cela signifie de créer un petit projet permettant de faire le transfert etla conversion d'un modèle à l'autre. 3°) En plus de la conversion des données, il faut se dire que certaines fonctionnalités du programme devront être modifiées pour correspondre au nouveau modèle, comme par exemple les ajouts d'adresses mail ou de numéros de téléphone. Au passage, j'en profite pour faire du nettoyage: A la base, l'utilisateur connecté était référencé dans chaque applications. (pour rappel on a une architecture qui devrait fonctionner avec MEF, c'est-à-dire un hôte et des plugins). Ca ne me plaisait pas trop, alors je vire toutes les références pour n'en avoir qu'une seule, dans l'hôte. J'ai également rajouté le cryptage des mots de passe vu qu'on stockera en partie des informations à caractère médical, et donc probablement confidentielles. En dehors de ça, j'ai fait un petit témoignage vidéo pour David Hernie à propos de mon intérêt pour la nouvelle plateforme WP7 :) Il faut dire qu'on est plutôt bien lancés en Belgique avec notamment Matthieu Vandenhende (aka Sogalas sur le Market) qui a publié près d'une trentaine d'application en un mois! Et pour terminer, on a pris le temps avec Suzanne Kieffer pour refaire le tour de la version actuelle de KIT et refaire une liste de TODO. Globalement, je suis pas prêt de manquer de boulot :) Demain, je continuerai ces histoires de base de données. J'espère en avoir fini le plus rapidement possible en étant sûr que le projet tourne exactement comme avant. Je vous tiens au courant ;)

Base de données - suite

12. February 2011 23:02 by Renaud in   //  Tags:   //   Comments (0)

Aujourd'hui, j'ai passé ma journée à réfléchir à l'utilisation d'Entity Framework 4 pour exploiter notre base de données. J'me suis pas mal documenté, et j'dois dire que pour le moment je nage un peu. Ma principale préoccupation vient du fait que les objets créés par Entity Framework sont liés à un ObjectContext (qui doit avoir une durée de vie la plus limitée possible). Une fois qu'on dispose notre ObjectContext, les propriétés de navigation de nos objets n'ayant pas été explorées ne sont plus accessibles, une exception est lancée. Cas de figure:

Client   ==>   Produit
Client (IDClient, nom, prénom, ...)
Produit (IDProduit, IDClient, libellé, type, prix, ...)

Dans ce cas-ci, si je récupère un Client depuis EF4, et que je dispose l'ObjectContext, je pourrai toujours atteindre le nom et le prénom du client, mais impossible d'atteindre la liste de ses produits. J'ai lu beaucoup de choses, qui se mélangent un peu dans ma tête pour le moment: lazy-loading, POCO, self-tracking entity, UnitOfWork, ... J'dois avoir lu tous les posts taggés entity framework et repository pattern de stackoverflow :) Au final, pour me changer les idées j'ai commencé une nouvelle appli WP7 qui sera, je pense, assez chouette une fois terminée :) J'arrête pour ce soir! Besoin de dormir et d'avoir les idées claires demain matin pour reprendre mes lectures où je me suis arrêté...

MCD, MLD, MPD, LDD, ETC...

9. February 2011 21:02 by Renaud in   //  Tags:   //   Comments (0)

Cette semaine on fait le ménage dans la base de données de KIT. Il s'agit ici de tout envisager pour mettre au point un modèle conceptuel flexible pour la suite, histoire qu'on ne doive pas re-modifier la base de données d'ici un an! Le MCD (modèle conceptuel de données) semble quasi définitif maintenant! Il permet de représenter les différentes entités de notre modèle de données, ainsi que leur multiplicité dans les différentes associations. De là j'ai fait le MLD (modèle logique de données), qui lui représente les tables de manière logique, c'est-à-dire sans les types des données. On indique les attributs de l'entité en précisant les clés primaires et clés étrangères. Ensuite, on passe à la représentation physique des tables, en précisant pour chaque attribut le type de données. Et pour terminer, ou presque, je pourrai créer la table :) L'ensemble de toutes ces étapes prend pas mal de temps, mais il faut que le modèle mûrisse bien avant de s'en servir réellement! Ceci nous évitera de devoir le modifier encore régulièrement à chaque problème. Quand la nouvelle base de données sera opérationnelle, il faudra refaire la librairie d'accès aux données du projet KIT. Pour ça, j'utiliserai l'Entity Framework 4 qui me plaît assez bien :)

MEF (Managed Extensibility Framework) en C#

5. February 2011 22:02 by Renaud in   //  Tags:   //   Comments (7)

Chose promise, chose due! Je vous avais parlé d'un article sur MEF, et le voici avec à peine un peu de retard!

MEF (pour Managed Extensibility Framework)est une librairie du framework .Net 4 qui permet de créer facilement des applications modulaires avec des plugins.

Concrètement, l'idée est de créer un premier projet servant d'hôte. Ce projet n'a aucune idée des plugins présents, et c'est seulement au runtime qu'il en prend connaissance! Il sait juste que tous les plugins répondront à un contrat. Le contrat ici, c'est l'implémentation d'une interface.

En vis-à-vis, on crée donc toute une série de projets "librairies", avec à chaque fois une classe implémentant l'interface attendue par l'hôte.

Pour notre exemple on va imaginer une application qui va servir à jouer des sons, des samples. Chaque plug-in permettra de lancer un sample différent.

Vous pouvez télécharger les sources complètes du projet ici:

1°) Voici donc notre interface:

    public interface ISamplePlayer
    {
        void PlaySound();
        string GetName();
        string GetDescription();
    }

J'ai créé cette interface dans un projet séparé du reste, ainsi je pourrai l'ajouter en référence à notre projet hôte et aux sous-projets!

2°) Le projet hôte:

Pour profiter des bienfaits de MEF, il vous faudra ajouter une référence à System.ComponentModel.Composition dans votre projet.

 namespace MEFSamplePlayer{
    /* Ceci est notre classe hôte.
     * Pour le moment elle ne sert à rien
     */
    public partial class MainWindow : Window
    {

        /* La liste des plugins à importer.
         * Les plugins doivent implémenter l'interface ISamplePlayer */
        [ImportMany(typeof(ISamplePlayer))]
        private IEnumerable<ISamplePlayer> Players = null;

        public MainWindow()
        {
            InitializeComponent();

            /* On lance la composition */
            Compose();

            /* On rempli l'ObservableCollection bindée dans notre listbox */
            PluginList list = this.Resources["PluginList"] as PluginList;
            foreach (ISamplePlayer player in Players)
            {
                list.Add(player);
            }
        }

        private void Compose()
        {
            /* Un AggregateCatalog dans lequel on va répertorier la liste des assembly à charger */
            var catalog = new AggregateCatalog();

            /* On va parcourir le dossier courrant de cette application et
             * y chercher d'autres assembly */
            catalog.Catalogs.Add(
             new DirectoryCatalog(
              Path.GetDirectoryName(
              Assembly.GetExecutingAssembly().Location)));

            /* On crée un CompositionContainer sur base du catalog créé ci-dessus */
            CompositionContainer container = new CompositionContainer(catalog);
            /* Et pour terminer on va remplir les listes d'imports de cet objet.
             * C'est maintenant que notre liste Players va se remplir des différents plugins. */
            container.ComposeParts(this);
        }

        /* On demande au plug-in sélectionné de jouer son sample. */
        private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            (listBox1.SelectedItem as ISamplePlayer).PlaySound();
        }
    }
}

Ici, on va donc d'abord peupler notre IEnumerable<ISamplePlayer> Players, et ensuite remplir notre ObservableCollection pour l'afficher dans une ListBox.

Une fois arrivé ici, ce projet n'aura plus besoin d'être re-compilé. Il ne nous reste qu'à créer des centaines de plugins et les placer dans le dossier de l'assembly pour qu'ils soient pris en compte au runtime :)

On va immédiatement créer un premier plugin pour être convaincu d'à quel point c'est facile:

3°) Les plugins:

Créez un nouveau projet de type librairie:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MEFSamplePlayerLibrary;
using System.ComponentModel.Composition;
using System.Reflection;
using System.Media;

namespace SampleHallelujah
{
    [Export(typeof(ISamplePlayer))]
    public class SampleHallelujah: ISamplePlayer
    {
        private SoundPlayer player;

        public SampleHallelujah()
        {
            player = new SoundPlayer();
            player.Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SampleHallelujah.hallelujahshort_1.wav");
        }

        #region ISamplePlayer Membres

        public void PlaySound()
        {
            player.Play();
        }

        public string GetName()
        {
            return "Hallelujah!";
        }

        public string GetDescription()
        {
            return "Ca maaarche!";
        }
        #endregion
    }
}

Ici encore on commence par une référence à System.ComponentModel.Composition. On peut alors indiquer que cette classe est à exporter sous le contrat ISamplePlayer, et on implémente bien évidemment l'interface!

Dans le constructeur on instancie un SoundPlayer qui permet facilement de jouer un son. Le Build Action du sample est sur Embedded Resource pour qu'il soit contenu directement dans le .dll.

Une fois que tout ça est fait, compilez votre projet et déposez le .dll résultant dans le dossier de votre hôte! Maintenant, ré-exécutez votre application MEFSamplePlayer, et vous pourrez voir que votre listbox n'est plus vide :)

Et voilà, ce n'est pas plus compliqué!

Il ne vous reste plus qu'à créer plein de plugins :)

MEF (Managed Extensibility Framework) in C#

5. February 2011 17:27 by Renaud in   //  Tags:   //   Comments (0)

I promise you a blog post talking about MEF, and actually I wrote it a few month ago... but in french! Now it's time to release the english version! So here it is! :) MEF (for Managed Extensibility Framework) is a .NET library that allows you to easily design reusable, extensible applications using plugins. The concept uses a project as a host. This project doesn't really know which plugins are available until runtime. The host just expects to find some plugins that correspond to a syntaxic contract which is defined in an interface.

Then, we can create several library projects with at least one class that implements the interface expected by the host, that you defined earlier. There is a lot of way to use Managed Extensibility Framework. You could use it to create extensible web services. In this example, we are going to create an application that will play sounds. Each plugin will be able to play a different sound. You can already download the code here:

1°) Here is the interface that describes what is a plugin:

    public interface ISamplePlayer
    {
        void PlaySound();
        string GetName();
        string GetDescription();
    }

I've created this interface in a separate assembly so that I will be able to reference it in the main project, and distribute it. Then, everybody can take my assembly and create his own plugin. 2°) The host: To user Managed Extensibility Framework capabilities, add a reference to System.ComponentModel.Composition in the main project.

 namespace MEFSamplePlayer{
    /* This is the host class. */
    public partial class MainWindow : Window
    {
        /* This collection will be populated with plugins discovered at runtime.
         * The ImportMany instruction said the plugins must implements ISamplePlayer.*/
        [ImportMany(typeof(ISamplePlayer))]
        private IEnumerable<ISamplePlayer> Players = null;

        public MainWindow()
        {
            InitializeComponent();

            Compose();

            /* Add every plugin to an ObservableCollection binded to a ListView */
            PluginList list = this.Resources["PluginList"] as PluginList;
            foreach (ISamplePlayer player in Players)
            {
                list.Add(player);
            }
        }

        private void Compose()
        {
            /* The catalog will be populated with the assembly that could contains plugin */
            var catalog = new AggregateCatalog();

            /* We look into the current folder */
            catalog.Catalogs.Add(
             new DirectoryCatalog(
              Path.GetDirectoryName(
              Assembly.GetExecutingAssembly().Location)));

            /* Create the CompositionContainer with the catalog */
            CompositionContainer container = new CompositionContainer(catalog);
            /* This line will populate the collection of this instance
               that we flaged with the ImportMany attribute */
            container.ComposeParts(this);
        }

        /* Call the PlaySound method of the selected item. */
        private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            (listBox1.SelectedItem as ISamplePlayer).PlaySound();
        }
    }
}

In short, we will populate the IEnumerable<ISamplePlayer> Players,  and display the plugins that have been found in the ListView. After this, we can build the application. We won't have to rebuild this project anymore! :) If we want to extend this application, we just have to create some plugins and put the assemblies in the same folder as the executable. After this, we can launch the application and, with MEF, plugins will be discovered at runtime :) Now let's create our first plugin. This is the easy part: 3°) The Plugins: Create a new project of type Library:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MEFSamplePlayerLibrary;
using System.ComponentModel.Composition;
using System.Reflection;
using System.Media;

namespace SampleHallelujah
{
    [Export(typeof(ISamplePlayer))]
    public class SampleHallelujah: ISamplePlayer
    {
        private SoundPlayer player;

        public SampleHallelujah()
        {
            player = new SoundPlayer();
            player.Stream = Assembly.GetExecutingAssembly()
                        .GetManifestResourceStream("SampleHallelujah.hallelujahshort_1.wav");
        }

        #region ISamplePlayer Membres

        public void PlaySound()
        {
            player.Play();
        }

        public string GetName()
        {
            return "Hallelujah!";
        }

        public string GetDescription()
        {
            return "Wow, an amazing plugin!";
        }
        #endregion
    }
}

Here again, you need to add a reference to the System.ComponentModel.Composition assemblyYou can then add the[Export(typeof(ISamplePlayer))] attribute. It means that this class can be used by an application that looks for ISamplePlayer plugin. Of course we need to implement the interface. In the constructor, we instanciate a new SoundPlayer object to easily play a sound. The build action of the wav file is set ton Embedded Resource, so that it is wrap in the assembly. Once it's done, you can build the project and place the .dll assembly in the same folder as the main application. And if you execute it, you will see that the listbox isn't empty anymore. Yep, it now contains your first plugin :)

Sortie à Dinant

3. February 2011 21:02 by Renaud in   //  Tags:   //   Comments (1)
Ce jeudi 3 février, j'ai accompagné Suzanne sur le terrain, à Dinant cette fois. On a interviewé 3 des utilisateurs de KIT ainsi que Denis, qui consacre une partie de son temps au suivi et au coaching de ces personnes dans leur apprentissage. L'expérience a été vraiment intéressante. On peut voir leur satisfaction à apprendre quelque chose de nouveau, mais également parfois leur frustration lorsqu'ils sont confrontés à un problème. Je retiendrai plusieurs choses de cette journée:

Premièrement, l'importance de la relation qu'a Denis avec les utilisateurs. L'outil Keep-In-Touch doit bien évidemment être facile d'utilisation pour que les personnes âgées puissent s'en servir de manière relativement autonome, mais il faut éviter que cela aboutisse à l'isolement de l'utilisateur. Dans les cas observés aujourd'hui, j'ai pu constater que les résidants disposant de KIT ont toujours besoin d'une aide, mais qu'ils sont fiers de pouvoir montrer ce qu'ils savent faire par eux-mêmes.

Deuxièmement, cela a permis de se rendre compte de quelques problèmes. J'ai notamment pu remarquer la difficulté liée au touch pour les personnes âgées atteintes de tremblements. J'ai quelques idées pour améliorer KIT en terme d'utilisabilité, d'une part en facilitant la perception de l'état du système et d'autre part en améliorant la sensation de contrôle.

Une journée plutôt bénéfique en somme!

Emotive Neuroheadset

28. January 2011 20:01 by Renaud in   //  Tags:   //   Comments (0)
L'un des nombreux avantages d'être stagiaire au MIC, c'est qu'on a accès à des technologies assez énorme :) On vient juste de faire l'acquisition d'un neuroheadset d'Emotive qui enregistre l'activité du cerveau et permet globalement de faire de vos émotions et de vos pensées des triggers que l'on peut associer à des actions. Y'a quelques années on rigolait des gens qui ne pouvaient plus se passer d'une télécommande pour changer de chaîne... bientôt vous ne pourrez même plus imaginer devoir en toucher une! Vous n'aurez qu'à penser à passer à la chaîne suivante :)

Semaine tranquillou!

26. January 2011 20:01 by Renaud in   //  Tags:   //   Comments (0)

Non je déconne. Veuillez m'excuser du peu d'activité sur ce blog mes chers lecteurs assidus que vous êtes (et je sais que vous êtes rares, c'est vous dire si vous m'êtes chers!), je dois vous avouer qu'en ce moment je manque un peu de temps pour écrire de beaux articles. Faut dire qu'en deux semaines on a pas arrêté au MIC:

  • boulot du stage proprement dit
  • bricolage de quelques applications WP7 (parce que c'est cool d'avoir une appli sur le market)
  • penser à étudier un peu pour passer une certif!
  • plus un dernier truc qui va encore me prendre du temps et qui arrive très très bientôt :)

On ajoute à ça pour le compte de l'école:

  • boulot pour le projet de C++
  • rédaction des synthèses hebdomadaires
  • rédaction d'un premier descriptif de stage pour vendredi
  • et pour ce même vendredi, rédaction d'une première partie du TFE.

Bref, je suis absolument overbooké! Mais malgré ça, j'vais vous trouver le temps de vous rédiger un petit article sur MEF avec un exemple de projet judicieux qui sera du plus bel effet, croyez-moi! Ca arrivera certainement ce weekend ;) A part ça, j'ai posté ma première application sur l'App Hub. Cette application affiche votre biorythme du jour et s'intitule sobrement... Biorythme! Votre biorythme c'est votre horoscope mais en mieux. Réfléchissez-y, ça ne coûte que 0,99€ :) Demain je clôturerai ma vérification d'identité et mon application pourra rentrer en phase de test! Verdict très bientôt! On sent que le stage est bien lancé! Le premier semestre de cette année scolaire a été cool, mais maintenant c'est du sérieux!

TextBox

About the author

I'm a developer, blog writer, and author, mainly focused on Microsoft technologies (but not only Smile). I'm Microsoft MVP Client Development since July 2013.

Microsoft Certified Professional

I'm currently working as an IT Evangelist with an awesome team at the Microsoft Innovation Center Belgique, where I spend time and energy helping people to develop their projects. I also give training to enthusiastic developers and organize afterworks with the help of the Belgian community.

MIC Belgique

Take a look at my first book (french only): Développez en HTML 5 pour Windows 8

Développez en HTML5 pour Windows 8

Membre de l'association Fier d'être développeur

TextBox

Month List