Dot.Blog

Consulting DotNet C#, XAML, WinUI, WPF, MAUI, IA

Un excellent livre sur LINQ : "LINQ in Action"

LINQ (encore ! dirons certains, mais c'est justifié je vous l'assure) est une technologie qui décuple la puissance de C#, encore faut-il bien maîtriser toutes les nouveautés syntaxiques de C# 3.0 (voir mes articles sur ce sujet*) et bien comprendre comment tirer partie du meilleur de LINQ lui-même.

Pour cela rien ne vaut un bon livre. Sur le sujet ils ne sont pas très nombreux et quand on fait un peu le tri, il en reste fort peu qui valent l'achat. Ce n'est pas le cas de "LINQ in action" un excellent bouquin qui utilise une approche très pédagogique pour "monter en puissance" au fur et à mesure de la progression des chapitres. C'est d'ailleurs peut-être aussi parce que les auteurs reprennent justement cette logique que j'applique dans mes propres cours sur LINQ que j'apprécie ce livre.

Il s'agit bien entendu d'un ouvrage en anglais, si vous ne maîtriser pas la langue il faudra hélas passer votre chemin. Les concepts avancés dans le livre peuvent s'avérer suffisament sophistiqués en eux-mêmes sans ajouter la difficulté de décryptage si on n'est pas totalement à l'aise avec la prose d'outre-Atlantique.

Pour acheter le livre au moins cher, je vous conseille l'excellent librairie anglaise The Book Repository qui livre en France et qui applique des tarifs généralement hors concurrence. La page du livre est ici "Linq in Action". L'ouvrage possède aussi son propre site avec le téléchargement des exemples ainsi qu'un forum.

(* Les nouveautés syntaxiques de C# 3.0 et Présentation des différentes facettes de LINQ )

LINQ et Réflexion pour obtenir les valeurs de System.Drawing.Color

LINQ... l'un de mes sujets préférés... Plus je l'utilise, à toutes les sauces, et plus je trouve cette technologie indispensable. Mais foin de propagande, voici encore un exemple qui prouve à quel point LINQ peut servir à tout, facilement.

Le but du jeu : récupérer la définition des couleurs de System.Drawing.Color, en faire un tableau trié par ordre alphabétique.

A la "main" je vous souhaite bien du plaisir... Avec LINQ cela donne la chose suivante :

namespace LinqColor
{
  class Program
  {
     static void Main(string[] args)
    {
       var color_type = typeof(System.Drawing.Color);
       var color_properties = from prop in color_type.GetProperties()
                                     where prop.PropertyType == color_type
                                     orderby prop.Name
                                     select prop;
       
       foreach (var color_property in color_properties)
       {
           var cur_color = (System.Drawing.Color) color_property.GetValue(null, null);
           uint rgb_int = (uint) cur_color.ToArgb() & (0x00ffffff);
           Console.WriteLine(" {0,-20} = ({1,-3},{2,-3},{3,-3}) = 0x{4:X00000000}",
           color_property.Name,
           cur_color.R, cur_color.G, cur_color.B,rgb_int);
       }
    }
  }
}

La sortie écran (console) donne la chose suivante :

Le projet VS 2008 pour les fénéants du clavier : LinqColor.zip (5,43 kb)

C'est pas merveilleux LINQ ?

Bien sûr que si... Alors Stay Tuned !

Internationalisez vos blogs et pages Web en 1 seul click avec Windows Live Translator

On aimerait parfois offrir certaines informations dans une langue étrangère mais traduire toutes les pages d'un site représente un coût non négligeable que seules de très grosses entreprises aux moyens financiers à la mesure d'une telle opération de communication peuvent se permettre.

Il existe toutefois une parade, certes pas absolue mais très pratique, elle s'appelle Windows Live Translator. En ajoutant un simple bout de script à vos pages les visiteurs pourront les consulter dans leur langue. J'ai ajouté cette fonction au présent blog (tout en haut à gauche), vous pouvez donc "jouer" avec pour vous rendre compte par vous mêmes de la qualité (assez bonne mais très variable malgré tout!) des traductions proposées.

Un Web totalement international, libre et sans frontières, c'est un rêve non ? (sauf si on est au gouvernement chinois bien entendu).

Stay Tuned !

Un livre à avoir : "Framework Design Guidelines"

J'achète assez peu de livres en général, en effet dès qu'on s'intéresse à ce qui est nouveau tous les livres potentiellement intéressants sont "à paraître", et quand ils paraissent l'info est déjà réchauffée par rapport à ce qu'on peut trouver des mois avant sur Internet. Bien entendu cela implique d'aller chercher l'information brute, éparpillée et en anglais. C'est pour cela que les ouvrages techniques en français trouvent toute leur utilité en offrant une information structurée, vérifiée et traduite pour tous ceux qui ne lisent pas l'anglais.

Toutefois il m'arrive d'acheter certains livres lorsqu'ils traitent de sujet plus "intemporels" comme la méthodologie ou ici le framework .NET.

Oui, ce livre est en anglais, et à votre prochaine question la réponse est non, je n'en connais pas de traduction en français ce qui est de toute façon rare dans ce domaine. L'exemple récent de la fermeture de l'antenne française de O'Reilly illustre la difficulté globale de vendre du livre technique en France malgré un catalogue attrayant. Quant à traduire un ouvrage et donc réengager des frais importants pour un public très restreint, fort peu s'y sont risqués ou s'y risquent. Dans mes propres "development guidlines", en position 1 je mettrais "faites du C#", en 2 "faites du LINQ", mais en position 0 "faites de l'anglais" !.

Framework Design Guidelines

Ce livre traite des bonnes méthodes à mettre en oeuvre pour développer des applications respectueuses du framework .NET. Ecrit par deux membres de l'équipe de développement de .NET il a aussi été relu et corrigé par d'autres personnes de cette équipe qui, chose originale, font apparaître ici et là des petits encadrés où ils apportent leur point de vue sur ce que les auteurs viennent d'écrire. C'est une approche intéressante qui rend le contenu plus vivant. L'avant propos est d'ailleurs signé par Anders Hejlsberg, difficle de trouver mieux...

Ce n'est pas un livre très récent, il a du paraître en 2006 la première fois, mais son contenu est "intemporel" dans le sens où il dépasse les modes ou les dernières options du framework pour parler de son coeur, ses API, sa structure et la façon de bien coder dans cet environnement.

Le contenu

Le sous titre est finalement clair "Conventions, Idioms and Patterns for Reusable .NET Libraries". Conventions, idiomes et patterns pour des bibliothèque de codes réutilisables.

La première partie traite des "qualités d'un framework bien conçu" et on entre un peu dans les coulisses de .NET, comment et pourquoi certains choix ont été arretés. Une façon agréable, au delà du côté anecdotique, d'aborder les qualités générales que se doit posséder toute bonne bibliothèque de code, comme celles que nous sommes amenées parfois à écrire.

Les fondamentaux du framework sont ensuite abordés puis on trouve les guidelines proprement dites. Stratégie de nommage, le choix entre classe ou structure, entre classe abstraite ou interface, la conception des membres d'une classe (propriétés, méthodes, champs...) tout cela est traité avec intelligence, à propos, et permet d'affiner ses propres vues sur ces questions ou parfois même de s'interroger sur des sujets dont on pensait avoir fait le tour.

Les exceptions sont traitées en détail, toujours sous l'angle de la meilleure mise en oeuvre possible plus que sur le code ou la syntaxe. Ce livre est un moyen terme entre théorie, design pattern, expérience de développeurs ayant écrit l'un des plus gros framework existant, sagesse et doutes que tout informaticien conscient de l'importante de ses choix se doit d'avoir.

Un final sur l'utilisation de FxCop, son évolution, comment il marche et comment en tirer le meilleur est tout à fait appréciable. Je parlais justement dans un dernier billet de la "sous utilisation" de cet outil fanstastique par la majorité des développeurs que je rencontre ou que je forme. Ce chapitre permettra peut-être aux lecteurs de ce livre de faire plus souvent usage de FxCop.

Le CD

Le livre est accompagné d'un CD contenant des exemples de code et plusieurs vidéo de conférences (en anglais aussi, ne rêvez pas :-) ), toutes particulièrement intéressantes et portant sur des sujets aussi variés que le garbage collector (et tout ce qui tourne autour de la libération de la mémoire et des ressources), les performances ou le packaging et le déploiement. Une vraie mine d'information, pas forcément récentes, comme le livre lui-même, mais qui abordent des fondamentaux parfois négligés.

Conclusion

Comme je le disais, ce livre est intemporel, en tout cas tant que vivra le framework .NET sous la forme que nous connaissons depuis plusieurs années maintenant. Il permet d'entrer un peu dans l'équipe de développement de cette plateforme, de comprendre les choix qui ont présidé à sa mise en oeuvre et surtout il permet, par cette vision "de l'intérieur" et les nombreux conseils qu'il contient de mieux concevoir son propre code, de mieux trancher entre certaines options parfois trop nébuleuses (classe ou interface, classe ou structure, par exemple) en sachant avec précision pourquoi on fera ou non tel ou tel choix.

C'est un livre plaisant à lire, qu'on peut "consommer" en piochant les chapitres, pas forcément dans l'ordre du livre. Un "must have" pour qui développe sous .NET, c'est une évidence.

Références

Framework Design Guidelines

Krzysztof Cwalina (au scrabble si vous le placez vous mettez à genou vos adversaires !)
Brad abrams

0-321-24675-6

Edité par Addison-Wesley

Une bonne librarie technique en ligne

Vous pouvez acheter ce livre dans toutes les bonnes librairies, toutefois si vous voulez le payer le moins cher possible, je vous conseille de le commander directement à "The Book Depository Ltd", une librairies anglaise qui livre vite et bien qui affiche des prix en général très bas. Leur site Internet : http://www.bookdepository.co.uk/WEBSITE/WWW/WEBPAGES/homepage.php

C'est un vendeur qu'utilise Amazon, mais si vous passez en direct c'est généralement moins cher...

Bonne lecture et Stay Tuned !

Appel d'un membre virtuel dans le constructeur ou "quand C# devient vicieux". A lire absolument...

En maintenant un code C# d'un client mon ami Resharper me dit d'un appel à une méthode dans le constructeur d'une classe "virtual member call in constructor". J'ai tellement pris le pli avec ce problème que je ne m'en souci plus guère dans mon propre code, j'évite soigneusement la situation... Mais vous ? Avez-vous conscience de la gravité de ce problème ?

Sans Resharper il faut passer volontairement une analyse du code pour voir apparaître le message CA2214 "xxx contient une chaîne d'appel aboutissant à un appel vers une méthode virtuelle définie par la classe.". D'une part je doute fort que tout le monde comprenne du premier coup ce message ésotérique mais le pire c'est que je sais par expérience que la grande majorité des développeurs n'utilisent, hélas, que très rarement cette fonction... Et à la compilation du projet, aucune erreur, aucun avertissement ne sont indiqués !

Vous allez me dire "ça ne doit pas être bien grave si le compilateur ne dit rien et que seul un FxCop relève un simple avertissement". Je m'attendais à ce que vous me disiez cela... Et je vais vous prouver dans quelques lignes que cette remarque candide est la porte ouverte à de gros ennuis...

Le grave problème des appels aux méthodes virtuelles dans les constructeurs

Ce problème est "grave" à plus d'un titre. Tout d'abord techniquement, comme le code qui suit va vous le montrer, votre programme aura un comportement que vous n'avez pas prévu et qui mène à des bogues sournois. Cela est en soi suffisant pour qualifier le problème de "grave".
Ensuite, moins on a conscience d'un problème potentiel et plus il est grave, par nature. Comme très peu de développeurs ont conscience du fait que ce comportement bien particulier de C# est une source potentielle d'énormes problèmes, sa gravité augmente d'autant.
Pour terminer et agraver la situation, le compilateur ne dit rien et seule une analyse du code (ou l'utilisation d'un outil comme Resharper qui l'indique visuellement dans l'éditeur de code) peut permettre de prendre connaissance du problème.
La chaîne ne s'arrête pas là (tout ce qui peut aller mal ira encore pire - Murphy ), puisque même en passant l'analyseur de code le message sera noyé dans des dizaines, voire centaines d'avertissements et que, cerise sur le gateau, même si on prend la peine de lire l'avertissement, son intitulé est totalement nébuleux !

La preuve par le code

Maintenant que je vous ai bien alarmé, je vais enfoncé le clou par quelques lignes de code (qu'il est méchant Laughing) !

class Program
{
     static void Main(string[] args)
     {
        var derivé = new Derived();
     }
}

public class Base
{
   public Base()
   { Init(); }

   public virtual void Init()
  { Console.WriteLine("Base.Init"); }
}

public class Derived : Base
{
   private string s = "Non initialisée!";
   public Derived()
  { s = "variable initialisée"; }

  public override void Init()
 { Console.WriteLine("Derived.Init. var s = "+s); }
}

La question à deux eurocents est la suivante : Au lancement de la classe Program et de son Main, qu'est-ce qui va s'afficher à la console ?

La réponse est "Derived.Init. var s = Non initiliasée!".

L'action au ralenti avec panoramique 3D façon Matrix : Dans Main nous instancions la classe Derived. Cette classe est une spécialisation de la classe Base. Dans cette dernière il y a un constructeur qui appelle la méthode Init. Cette méthode est virtuelle et elle est surchargée dans la classe Derived.
Lorsque nous instancions Derived, de façon automatique le constructeur de Base se déclenche, ce qui provoque l'appel à Init. Donc à la version surchargée de Derived puisque C# appelle toujours la méthode dérivée la plus proche du type en cours.

D'où vient le problème ? ... Il vient du fait que le constructeur de Base, d'où provient l'appel à Init, n'est pas terminé (il le sera au retour de Init et une fois sa parenthèse de fin atteinte), du coup le constructeur de Derived n'a pas encore été appelé !

Si le code de Init ne repose sur aucune initialisation effectuée dans le constructeur de cette classe, tout va bien. Vous remarquerez d'ailleurs que le message affiché prend en compte la valeur de la variable s qui est initialisée dans sa déclaration et non pas une chaîne nulle. Ce qui prouve que les déclarations de variables initialisées sont, elles, bien exécutées, et avant le constructeur. Mais si le code de Init dépend de certaines initialisations effectuées dans le constructeur (initialisations simples comme dans l'exemple ci-dessus ou indirectes avec des appels de méthodes), alors là c'est la catastrophe : le constructeur de Derived n'a pas encore été appelé alors même que la version surchargée de Init dans Derived est exécutée par le constructeur de la classe mère !

La règle

Elle est simple : ne jamais appeler de méthodes virtuelles dans le constructeur d'une classe !

La règle CA2214 de l'analyseur de code :

"When a virtual method is called, the actual type that executes the method is not selected until run time. When a constructor calls a virtual method, it is possible that the constructor for the instance that invokes the method has not executed. "

"Quand une méthode virtuelle est appelée, le type actuel qui exécute la méthode n'est pas sélectionné jusqu'au runtime [ndt: c'est le principe des méthodes virtuelles, le "late binding"]. Quand un constructeur appelle une méthode virtuelle, il est possible que le constructeur de l'instance qui est invoquée n'ait pas encore été exécuté".

C'est "possible", c'est même pas sûr, donc il ne faut surtout pas écrire de code qui repose sur ce mécanisme...

L'aide de l'analyseur de code m'amuse beaucoup car dans sa section "How to fix violations" ("comment résoudre le problème"), il est dit tout simplement de ne jamais appeler de méthodes virtuelles dans les constructeurs... Avec ça débrouillez-vous !

La solution

Comme le dit laconiquement l'aide de l'analyseur : "faut pas le faire". Voilà la solution... En gros, si le cas se produit, comme dans notre exemple, la seule solution viable consiste à prendre le code de la méthode Init et à le déplacer dans le constructeur, il est fait pour ça... La méthode Init n'existe plus bien entendu, et elle est n'est donc plus surchargée dans la classe fille.

Conclusion

J'espère que ce petit billet vous aura aidé à prendre conscience d'un problème généralement méconnu, une spécificité de C# qu'on ne retrouve ni sous C++ ni sous Delphi.

Le projet VS2008 pour les fénéants : VirtualInit.rar (5,41 kb)