C# 6.0


Ci-dessous un ensemble de nouvelles fonctionnalités dédiée à l’arrivée parmi nous de C# 6.0, la plupart des nouveautés ont comme principal but de réduire le nombre de lignes de code, en réduisant les artefacts d’une classe,  tels par exemple les constructeurs primaires, initialiseurs de propriétés automatiques, propriétés automatiques en lecture seule, leur finalité aboutit à la suppression de membres etc.

Faciliter le développement en évitant des contraintes liées à des validations, inclusion ou autre.

Important : Les exemples ci-dessous ont été développés sous le Framewok 4.0.

Cela est désormais possible avec un constructeur primaire.

public class Sample(int id, int code) 
{     
public int Id { get; } = id;     
public int Code { get; } = code; 
}

Cela est désormais possible avec un initialiseur de propriété

public int Flow { get; set; } = 2210;

Ajouté à cela le using static sur une classe, qui correspond à importer  tous les membres statiques.

using System.Math;
…
// On invoque la méthode Round sans préfixer de la classe Math
double input = 123.45;
double target = Round(input, 1, MidpointRounding.AwayFromZero); // Rounds "up"

Pour les développement asynchrones il est désormais possible d’inclure le mot clé await.

private async Task NowIsPossible () 
{     
try     
{         
   // your treatment     
}     
catch (Exception ex)           
{         
    var exceptionMsg = new MessageDialog("Exception occured");         
    await exceptionMsg.ShowAsync();    
} 
}

Les filtres d’exception complètent les traitements d’exception comme ci-dessous.
Cela devient possible en ajoutant des filtres d’exception

Try
{
using (StreamReader sr = new StreamReader("TestFile.txt"))        
{                 
    string line;                
    // Read and display lines from the file until the end of                
    // the file is reached.                 
    while ((line = sr.ReadLine()) != null)                 
    {                     
      Console.WriteLine(line);                 
    }        
}
}
catch(IOException ex) if (ex.HResult == 0x80070020) 
{    
     // My resource is used by another process      
}

Le traitement de la nullabilité sans lever de NullReferenceException.
Cela devient possible, en interprétant le nom juste dans le cas de figure ou l’objet geek est différent de null.

string name = geek?.Name;  

Avant : 

 string name = geek!= null ? geek.Name : null;

Voir plus en détail http://msdn.microsoft.com/fr-fr/magazine/dn683793.aspx

GC.Collect

Web forms to MVC (First step)


Bonjour ce post a pour but d’exposer une stratégie de passage d’une application Webform vers une architecture MVC, en limitant les perturbation sur votre conteneur Webform.

Rappelons que le traitement classique MVC intercepte une requeête Http, celle ci est décortiqué suivant les pattersn enregistrés grace au UrlRoutingModule (HttpModule), ensuite sollicite un gestionnaire http, notament le MvcHandler, celui ci utilise la classe factoryHandler, qui instancie un controleur (IOC) et invoque l’action correspondante.

Dans notre cadre de figure, nous devons penser a invoquer une action d’un controlleur (Correspondant à un refactoring d’une page Web form).

Ci-dessous une portion de code permettant de simuler un contexte dédié.

 
    /// <summary>
    /// Class permit to get http request, simulate creating of route data, create controller instance et calculate render
    /// </summary>
    public static class RoutingWebFormSimulator
    {
         /// <summary>
        /// Enumeration permit to define type of view
        /// </summary>
        public enum TypeView
        {
            /// <summary>
            /// The normal.
            /// </summary>
            Normal, 
 
            /// <summary>
            /// The partial.
            /// </summary>
            Partial
        }
 
        /// <summary>
        /// Method permit to define render of partial view
        /// </summary>
        /// <param name="name">permit to define partial name</param>
        /// <param name="model">permit to define model</param>
        /// <param name="type">permit to define type</param>
        /// <remarks>Get a wrapper for the legacy WebForm context</remarks>
        /// <remarks>Create a mock route that points to the empty controller</remarks>
        /// <remarks>Create a controller context for the route and http context</remarks>
        /// <remarks>Find the partial view using the viewengine</remarks>
        /// <remarks>Create a view context and assign the model</remarks>
        /// <remarks>Render the partial view</remarks>
        public static void Render(string name, object model, TypeView type = TypeView.Normal)
        {
            const string NameController = "WebFormController";
            IView view;
 
            var httpContextWrapper = new HttpContextWrapper(HttpContext.Current);
            var controller = new WebFormController();
            controller.ViewData.Model = model;
            var routeData = new RouteData();
            routeData.Values.Add("controller", NameController);
            var controllerContext = new ControllerContext(new RequestContext(httpContextWrapper, routeData), controller);
            if (type == TypeView.Partial)
            {
                view = ViewEngines.Engines.FindPartialView(controllerContext, name).View;
            }
            else
            {
                view = ViewEngines.Engines.FindView(controllerContext, name, string.Empty).View;
            }
            var viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary { Model = model }, new TempDataDictionary(), new StreamWriter(Stream.Null));
            view.Render(viewContext, HttpContext.Current.Response.Output);
        }
    }

Donc au sein de votre Webforms, vous faites juste appel a ce routeur specifique, qui lira du code MVC.

RoutingWebFormSimulator.Render(« Sample », null, RoutingWebFormSimulator.TypeView.Partial);

Sample représente une vue compatible MVC.

GC.Collect

Multithreading Favorite patterns


Le multithreading comporte un ensemble de dérives sur lesquelles il est important de se pencher, les étudier et proposer des solutions permettant de les contourner, parmi les problématiques rencontrées auxquelles on  fait face sont un inter blocage et une synchronisation oubliée, une granularité incorrecte et trop large, une inversion des priorités générant le blocage d’un thread important et l’exécution d’un thread non signifiant, l’immutabilité ou l’absence de pureté etc.

Pour faire face a ces différents problèmes il est necessaire de mettre en place un ensemble de bonnes pratiques de développement , ci-dessous un listing des qualités aue j’affectionne particulièrement.

  • Favoriser l’utilisation de la TPL
  • Favoriser  l’utilisation du Async Result Pattern
  • Favoriser l’utilisation du Background Work Pattern

Ci-dessous un descriptif plus détaillé de trois principes mis en place qui sont les : le pattern Boss Worker, le patern Pipeline et le Producer/Consumer (Une démonstration sera réalisée en utilisant des notions telle Task et BlockingCollection).

Boss/Workers pattern :

Chaque requête soumise à une classe Boss se transforme en une tache à exécuter sur un thread définit par la classe Boss, les threads sont gérés au niveau de la classe Boss, les taches sont encapsulées dans des classes Worker, il présente l’avantage de simplicité de lecture et une isolation bien définie.

Boss : 
foreach {					
	//get a request
	switch(request)
	{
   case X: new Thread(taskX);
     	   case Y: new Thread(taskY);
                 …
              }}

Worker :
taskX();

Pour affaiblir le couplage on pourrait imaginer l’existence de classes requêtes implémentant une interface IRequest et de même pour les classes Worker.
Souvent ce pattern est associé à l’utilisation de la classe ThreadPool.

Pipeline pattern :
Le principe consiste à faire exécuter par un thread une portion d’une tache et passer le résultat au prochain thread.
Ci-dessous un exemple de code de pipeline

class Pipeline
{
Main()	
{	
 createThread( ... stage1 )	
 createThread ( ... stage2 )	
 ...
 wait for all pipeline threads to finish	
 do any clean up	

}	

Stage1()	
{	
  foreach {	
         get next input for the program	
         do stage 1 processing of the input	
         pass result to next thread in pipeline	
  }	
}	
Stage2()	
{	
  foreach {	
         get input from previous thread in pipeline	
         do stage 2 processing of the input	
         pass result to next thread in pipeline	
  }	
}	
..
StageN()	
{	
  foreach {	
         get input from previous thread in pipeline	
         do stage N processing to the input	
         pass result to program output	
  }	
}
}

Ci-dessous un lien décrivant de manière plus détaillée l’aspect implémentation http://msdn.microsoft.com/en-us/library/ff963548.aspx

Producer/Consumer pattern :

Le principe consiste à utiliser un flux de données pour faire communiquer un thread producteur et un un thread consommateur.
Ci-dessous une implémentation réalisée en utilisant des classes telles Task et BlockingCollection qui représente la structure tampon.

// Declarer la structure tampon
var blockingCollection = new BlockingCollection();
// Lancer le premier consomateur qui attend que la données soit disponible sur le tampon
var consumer1 = Task.Factory.StartNew(() =>
{
	foreach (int data in blockingCollection.GetConsumingEnumerable())
   	{
	Console.Write(string.Concat("consumer1= ", data, ","));
	}
});

// Lancer le second consomateur qui attend que la données soit disponible sur le tampon
var consumer2 = Task.Factory.StartNew(() =>
{
	foreach (int data in blockingCollection.GetConsumingEnumerable())
	{
	Console.Write(string.Concat("consumer2= ", data, ","));
	}
});

// Le thread producteur produit les données sur la structure tampon
var producer = Task.Factory.StartNew(() =>
{
	for (int i = 0; i < 100; i++)
	{
	blockingCollection.Add(i);
	}
	blockingCollection.CompleteAdding();
});
producer.Wait();
// Attendre que tous les consomateurs finissent de consommer et relance le traitement
Task.WaitAll(consumer1, consumer2);
Console.WriteLine();

Vous avez des principes supplémentaires tels le up-calls, qui consiste à faire communiquer les couches dans un sens ascendant en utilisant une ThreadPool au sein de chaque couche etc.

GC.Collect

TPL is nice


Une des façons les plus élégantes de faire de la programmation asynchrone est l’utilisation de la TPL (Task Parallel Library : http://msdn.microsoft.com/en-us/library/dd460717.aspx) en utilisant des notions rudimentaires telle le DataFlow.

La première étape à réaliser est tout d’abord de récupérer la bibliothèque Nuget associée.

NugetTPL

Saisir DataFlow dans le moteur de recherche des extensions et sélectionner TPL Dataflow.

 ExtensionTPL

Vous noterez l’ajout de référence fait dans votre projet

ReferenceTPL

Au cours de l’exercice on utilise deux classes principales qui sont ActionBlock et TransformBlock.

La classe ActionBlock vous permet de definer une fonctionnalité asynchrone.

ActionBlock action = new ActionBlock(
 	(p) => {
	        for(int indexThread = 0 ; indexThread < 5; indexThread++)
	        {
		Thread.Sleep(1000);
		Console.WriteLine(p);
	        }});
action.Post("Nice");
while(true)
{
 Thread.Sleep(300);
 Console.WriteLine("Good");
}

Vous remarquerez que le Dataflow s’exécute en même temps que la boucle faite.

TPLTP

Nous utiliserons au niveau de cette deuxième étape la classe TransformBlock, qui a cette particularité d’appliquer une transformation à un flux d’entrée et produire un flux de sortie.

Ci-dessous une desciption des auters blocs :

  • BatchBlock : Aggrèger un flux en un flux de sortie agissant comme une mémoire tampon.
  • BroadCastBlock : Transfèrer un flux à un ensemble de blocs traitant parallèlement ce flux entant
  • BufferBlock : Fournir à un ensemble de blocs de sortie un même flux.
 
TransformBlock transformBlock = new TransformBlock(
(p) =>
   {
      return string.Concat("We transform this flow", p);
   });

GC.Collect

Organize solution WAF


Pendant la mise en place de votre solution il est important de structure vos projets en se basant sur des bonnes pratiques, l’un des concepts les plus utilisés est le WAF, Il aide à organiser les types et les espaces de noms dans une structure à grande échelle, les couches «inférieures» sont des services de bas niveau et générale, et les couches «supérieures» sont plus spécifiques de l’application, les couches «supérieures» référencient les types de couches «inférieures» et non l’inverse.
Ci-dessous un diagramme de package exemple à partir duquel on peut s’en inspirer, le préfixe peut correspondre au nom de votre organisation.

Package

Les packages cités ci-dessous peuvent aussi correspondre au nom de répertoires de la solution pour faciliter la lecture de la solution, ou imaginer des scénarios plus compliqués ou figure plusieurs point d’entrées au sein de la couche Presentation, ou cette voir cette nécessité de séparer les classes de collection de données  et les services de traçage au sein de la couche Foundation, d’où le fait de réaliser deux projets distincts Foundation Prefix.Foundation.Util et Prefix.Foundation.Data au sein du répertoire Prefix.Foundation.

Ci-dessous un descriptif exhaustif  des différentes couches : 

  • La couche Presentation contient les vues de l’application, les fichiers XAML, cela peut être des pages ou des contrôles utilisateurs, ces fichiers sont faiblement couplées à la mécanique de transformation de données, voir le cas ou on utilise un pattern MVVM pour tuner notre application cliente WPF (Voir PRISM ou Light Toolkit).
  • La couche Application contient les ViewModels, les interfaces des vues, les commandes etc.
  • La couche Domain contient des façades, des services métier et les objets métier propre à notre scope fonctionnel.
  • La couche Business Infrastructure contient les services métier réutilisés, la particularité des classes existantes ici par rapport à celles existantes au sein de la couche Domain, est cette possibilité d’être réutilisée sur d’autres solutions sans référencer les aspects métier, souvent on y retrouve des classes utilisant des types primitifs, dans un cas concret d’une application WPF on y retrouve des Converters, il peut aussi s’agir de classes Helpers techniques intervenant dans l’application. 
  • La couche Technical Services contient tous les services permettant de répondre à des besoins techniques, notez que l’accès aux données est considéré comme une fonctionnalité technique permettant d’interagir avec la structure de stockage, donc on peut aisément avoir un projet  ORM Entity Framework. On peut aussi retrouver la mise en place d’une sonde de sécurité (Identity, Principal) ou un socle de validation tel celui basé sur System.ComponentModel.DataAnnotation.

          Remarque : L’ajout d’un service WCF trouverait sa place aussi au sein de cette couche technique.

  • La couche Foundation contient tous les services techniques tels le traçage de l’applicatif (Best Practise : Entreprise Library Framework), les collections de classes.

Ci-dessous un exemple d’une solution mise en place respectant les artefacts cités ci-dessus :

 SampleSolution

GC.Collect

Easy Code Metric 2013


L’outil Code Metric permet de calculer quelques métriques importantes indiquant le niveau de maintenance du code source, la complexité cyclomatique, le niveau d’héritage, le couplage des classes ou le nombre de lignes de code.
Rien de plus facile pour lancer l’analyse code métrique, celà se fait en cliquant sur le lien Code Metric de la section Analyse, cependant le plus important est la manière d’interprêter ces données et les décisions à prendre pour réduire certaines données afin d’optimiser votre qualité.

Ci-dessous un lien décrivant exaustivement les Code métriques :
http://msdn.microsoft.com/en-us/library/bb385914.aspx

Ci-dessous un imprime écran décrivant l’exécution de Code Metric sur un de mes projets.

CM

On peut décrypter les informations avec ces indicateurs de bonne pratique :

  • Maintainability Index : Bon rating (20-100) / Moyen (10-19) / Mauvais (0-9)
  • Cyclomatic Complexity : réduire la complexité cyclomatique du code afin de faciliter sa compréhension sur le projet 2, 6 et 10, et afin de faciliter la couverture de code. (L’indice correspond a son emplacement au sein de la pile de resultats, en allant du haut vers le bas)

            Solution : Veillez à sélectionner la règle Code Analysis 1502.

  • Depth of Inheritance : il est nécessaire de réduire le niveau d’héritage à une valeur moyenne de 4

           Solution : Veillez à sélectionner la règle Code Analysis 1501.

  • Class Coupling : il est nécessaire de réduire la valeur du couplage entre les classes pour faciliter la réutilisation, le nombre magique à ne pas dépasser par classe est 9.  

          Solution : Veillez à sélectionner la règle Code Analysis 1506. 

              LineCode

  • Lines of code : On peut envisager de ne pas dépasser les 200 lignes de code par classe, cela reste un bon ratio.

Other

Aprés effectivement le fait d’implémenter des patterns de développement tels SOLID, GOF, Entreprise peut forcément vous aider à améliorer ces ratios, la mise en de tests unitaires aussi est un facteur important pour augmenter la qualité de votre code.

GC.Collect

 

Windows Workflow Foundation 4.5 News (WindowsIdentity, hébergement, génération, NoPersistScope, Designer, …)


Sur la plateforme Windows Workflow Foundation 4.5 un ensemble de nouveautés font leur apparition sur différents thèmes tels la conception d’un flux, développements associés, utilisation du concepteur visuel etc. Ce billet a pour objectif de citer les évolutions les plus importantes à mon sens.

L’apparition d’une nouvelle classe WorkflowIdentity, elle permet d’héberger plusieurs versions d’un flux de travail côte à côte, ensuite le chargement d’une instance persistante se fait via la classe WorkflowApplicationInstance puis DefinitionIdentity peut être utilisé par l’hôte pour fournir la version appropriée de la définition de flux en instanciant WorkflowApplication.
Ci-dessous un fragment de code permettant de mettre en œuvre la classe WorkflowIdentity, elle est créée et associée à une instance.

WorkflowIdentity identityFirstVersion = new WorkflowIdentity
{
    Name = "YourWorkflowFirstVersion",
    Version = new Version(1, 0, 0, 0)
};
WorkflowApplication wfApp = new WorkflowApplication(new YourWorkflow (), identity);
// Configurer les services de persistence.
ConfigureWorkflowApplication(wfApp);
// Exécuter le flux.
wfApp.Run();

Ci-dessous un fragment de code permettant de mettre en œuvre le chargement du flux.

WorkflowApplication wfApp = new WorkflowApplication(new YourWorkflow (),identityFirstVersion);
ConfigureWorkflowApplication(wfApp);
// Charger le flux.
wfApp.Load(instanceId);

WorkflowServiceHost prend en compte le multi-versioning. Lorsqu’une nouvelle version d’un service de flux est déployée, les nouvelles instances sont créées à l’aide du nouveau service, mais les instances existantes s’exécutent à l’aide de la version antérieure.

WorkflowServiceHost contient deux propriétés pour configurer plusieurs versions d’un flux de travail de s’exécuter côte à côte : SupportedVersions qui contient les versions prises en charge du service de workflow et DefinitionIdentity qui permet d’identifier chaque service de workflow.

//Configurer WorkflowServiceHost une version actuelle.
WorkflowServiceHost host = new WorkflowServiceHost(serviceActualVersion, 
    new Uri("http://localhost:8080/YourWorkflow"));
//Créer une version précédente du flux.
WorkflowService serviceOldVersion = new WorkflowService
{
    Name = "YourWorkflow",
    Body = new YourWorkflow(),
    DefinitionIdentity = new WorkflowIdentity
    {
        Name = " YourWorkflow",
        Version = new Version(1, 0, 0, 0)
    }
};
//Ajouter une version précédente du service à SupportedVersions.
host.SupportedVersions.Add(serviceOldVersion);

Vous pouvez valider la structure du flux de travail au moment de la génération, sur la version précédente de la plateforme .NET Framework 4, les erreurs de validation du flux n’étaient pas été comptées comme des erreurs de compilation pendant la génération du projet.
Dans le .NET Framework 4.5 RC, les erreurs de validation provoquent l’échec de la génération.

Un ensemble de nouveautés dédiées au flux de travail de type machine à état telles :
La possibilité de définir des points d’arrêt sur des états, la possibilité de copier et coller des transitions dans le concepteur visuel du flux, la prise en charge du concepteur pour la création de transition de déclencheur partagé et

De nouvelles activités telles NoPersistScope permettant de désactiver la persistance d’un flux de travail lorsque des activités enfants de NoPersistScope sont en cours d’exécution, cela s’avère utile dans les scénarios ou on fait appel à des transactions en base de données.
Améliorations du concepteur visuel de flux de travail, dorénavant on peut supprimer l’élément de menu contextuel dans le concepteur de variable et d’argument

On dispose d’un encadrement automatique avec séquence, certaines activités comme NoPersistScope peut uniquement contenir une seule activité de corps, l’ajout d’une deuxième activité sur la version 4.0 exige que le développeur supprime la première activité, ajoute une activité Sequence, puis ajoute les deux activités à l’activité de séquence.
À partir du .NET Framework 4.5 RC, lors de l’ajout d’une deuxième activité sur l’aire du concepteur, un activité Sequence est créée automatiquement pour encapsuler les deux activités.

Pour faciliter le développement de plus grands workflows, le concepteur prend désormais en charge l’ajout d’annotations pour faciliter le suivi du processus de création. Une annotation peut être ajoutée aux activités, états, nœuds d’organigramme, variables et arguments. La capture d’écran suivante montre le menu contextuel utilisé pour ajouter des annotations au concepteur.

Pour parcourir un flux de travail au sein du concepteur, le mode panoramique peut être activé plutôt que d’utiliser les barres de défilement.

Microsoft – .Net C#

Suivre

Recevez les nouvelles publications par mail.