ASTUCE VISUAL STUDIO #2 : Résoudre la référence

J’évalue actuellement les nouvelles fonctionnalités de Visual Studio 2012 depuis maintenant quelques semaines. Afin de bien comprendre comment il fonctionne, je n’emploie aucune extension, comme le très populaire ReSharper, à titre d’exemple.

Il y a une fonctionnalité que j’aime beaucoup dans ReSharper. Il s’agit de la possibilité d’ajouter les références manquantes à votre classe l’aide du raccourci clavier Alt-Enter. D’une seule combinaison de clavier, il détecte toutes les références manquantes et les ajoute automatiquement.

Vous remarquez le petit « gusse » qui fait le soulignement bleu sous la classe FileInfo. Il est là depuis très longtemps dans Visual Studio. Personnellement, je ne l’ai jamais trouvé très pratique à atteindre avec la souris. Pour y arriver, il faut :

  1. Positionner son curseur sur le type en question.
  2. Passer la souris devant le petit carré (« gusse ») bleu pour faire apparaître le menu contextuel
  3. Ajouter la/les références manquantes

Vous êtes-vous déjà demandé comment faire pour accéder au petit « gusse » bleu avec le clavier? Facile! La réponse est la combinaison des touches CTRL et . (Point).

Évidemment, il fallait seulement se poser la question afin d’avoir la réponse. C’est pourtant si simple. Pourquoi je ne me suis pas posé la question avant?

Création de fichiers Zip avec .NET 4.5

Le framework .NET offre beaucoup de fonctionnalités aux développeurs afin d’éviter à avoir à écrire et réécrire certaines fonctionnalités avec le temps. Un domaine qui a toujours manqué à .NET à travers le temps est au niveau de la compression de fichiers.

Sans avoir recours à une librairie externe, il y a les deux choix qui s’offraient au développeur :

Le tout est bien et assez fonctionnel. Dans les deux cas, il est possible de prendre un fichier en mémoire et de le compresser pour ainsi économiser en espace lors du transport.

J’ai toujours trouvé l’opération assez fastidieuse et très répétitive. Sommairement, compresser un fichier équivalait à :


namespace Compression
{
public class Compression
{
public static void Compress(FileInfo fi)
{
using (FileStream inFile = fi.OpenRead())
{
if ((File.GetAttributes(fi.FullName) & FileAttributes.Hidden) != FileAttributes.Hidden & fi.Extension != ".gz")
{
using (FileStream outFile = File.Create(fi.FullName + ".gz"))
{
using (GZipStream Compress = new GZipStream(outFile, CompressionMode.Compress))
{
inFile.CopyTo(Compress);
}
}
}
}
}
}
}

view raw

gistfile1.cs

hosted with ❤ by GitHub

Prenez note que j’ai laissé la mention du Namespace pour avoir encore plus une plus belle pyramide de code!

Le vrai problème est que l’algorithme Deflate est utilisé pour les fichiers Zip mais la classe DeflateStream ne fournit pas les entêtes de fichiers nécessaires pour la création de fichiers Zip. Cela n’est pas très pratique.

L’alternative à tout ça aura été la librairie DotNetZip. Cette librairie a été  le choix de-facto afin de compresser des fichiers dans le format Zip. Le résultat est à la hauteur sans artifices et à la hauteur des attentes  :


using (ZipFile zip = new ZipFile())
{
zip.AddFile("c:\\images\\personal\\7440-N49th.png", "images");
zip.AddFile("c:\\Reports\\2008-Regional-Sales-Report.pdf", "files");
zip.AddFile("ReadMe.txt");
zip.Save("MyZipFile.zip");
}

view raw

gistfile1.txt

hosted with ❤ by GitHub

La nouveauté

Avec .NET 4.5, cette époque est révolue. La gestion de fichier archives .NET est maintenant intégrée directement dans le Framework sous le namespace System.IO.Compression.

Au total, il y a quatre classes vous permettant de faire la gestion de vos archives. À chacune son rôle bien spécifique :

  • ZipFile
    • Offre les méthodes nécessaires pour la création, extraction et ouverture des fichiers Zip.
  • ZipFileExtensions
    • Ajoute certaines extensions aux fonctionnalités pour la gestion des archives compressées. Par exemple. il est possible de compresser un répertoire entier ou même d’ajouter des fichiers à une archive Zip existante.
  • ZipArchive
    • Représente une archive Zip. Le conteneur des fichiers compressés.
  • ZipArchiveEntry
    • Représente un fichier à l’intérieur d’une archive Zip.

Exemples

La manipulation de l’API est très simple. Il faut reconnaître que l’équipe du développement de .NET a fait du beau travail avec la gestion des archives Zip.

Notez que, dans tous les cas, il est important d’ajouter les références à System.IO.Compression ainsi que System.IO.Compression.FileSystem pour que le tout puisse compiler.

Création


using (ZipArchive archive = ZipFile.Open(@"c:\frenchcoding\start.zip", ZipArchiveMode.Create))
{
archive.CreateEntryFromFile(@"c:\frenchcoding\test.txt", "test_compress.txt");
archive.CreateEntryFromFile(@"c:\frenchcoding\test2.txt", "test_compress2.txt");
archive.CreateEntryFromFile(@"c:\frenchcoding\test3.txt", "test_compress3.txt");
}

view raw

gistfile1.cs

hosted with ❤ by GitHub

Extraction


using (ZipArchive archive = ZipFile.Open(@"c:\frenchcoding\start.zip", ZipArchiveMode.Read))
{
archive.ExtractToDirectory(@"c:\frenchcoding\extract\");
}

view raw

gistfile1.cs

hosted with ❤ by GitHub

Suppression d’éléments


using (ZipArchive archive = ZipFile.Open(@"c:\frenchcoding\start.zip", ZipArchiveMode.Update))
{
archive
.GetEntry("test_compress2.txt")
.Delete();
archive
.GetEntry("test_compress3.txt")
.Delete();
}

view raw

gistfile1.cs

hosted with ❤ by GitHub

SPDY – Le nouvel acronyme du web à venir

L’internet a toujours été une source d’innovation et de tentatives pour rentre l’expérience utilisateur la plus agréable possible. Cette amélioration se fait à plusieurs points. Il va d’améliorations à l’ergonomie design des pages web en passant par la façon dont les pages web sont indexées par les moteurs de recherche.

Un facteur reste, toutefois, au cœur des préoccupations lorsqu’il est temps d’améliorer l’expérience utilisateur sur le web : La vitesse. La rapidité à laquelle les données doivent être communiquées au visiteur est littéralement le nerf de la guerre. Ce constat est très analogue au concept de la saucisse Hygrade : Plus tu sers de contenu rapidement, plus tu seras capable d’en servir, plus ton site paraîtra rapide et mieux il sera référencé.

SPDY, c’est quoi?

SPDY (Comme dans l’expression Speedy) est un protocole développé par Google depuis déjà 2009. Le but de ce protocole est de remplacer directement HTTP 1.1 qui est le protocole de-facto sur Internet.

Un groupe de travail de l’IETF (Internet Engineering Task Force) a été mis en place pour définir quel sera le protocole sera utilisé pour ce qui a été nommé comme HTTP 2.0. Comme tout ce qui a trait à la standardisation des procédures et technologies entre les gros joueurs d’internet, l’enjeu est important car il est de déterminer quel protocole sera recommandé pour l’implémentation de HTTP 2.0.

Au menu, il y a trois protocoles à l’étude :

D’un point de vue technique

L’avantage proposé par SPDY est qu’il est conçu pour utiliser moins de connexions TCP que HTTP et il est aussi conçu pour utiliser TLS par défaut. Ceci veut donc dire que SPDY est par design plus rapide et surtout plus sécuritaire que HTTP.

Il faut aussi noter que SPDY est un ajout au fonctionnement actuel de HTTP. C’est à dire que SPDY modifie seulement la façon que les paquets de données sont envoyées par les serveurs aux clients. Cette modification se fait au niveau de l’ajout d’une couche Session (Bien située entre HTTP et SSL) lors d’une connexion TCP.

Comment plus rapide?

Le gain de vitesse de téléchargement est très intéressant. Selon les scénarios suggérés (Section Preliminary results), le gain de téléchargement varie entre 30% et 63%.

À titre d’exemple, un téléchargement qui prend 3111.916 millisecondes avec HTTP son équivalent avec SPDY prend environs 1695.72 millisecondes. Ici, on parle d’un gain de 45%.

Vocabulaire

La venue de ce nouveau protocole implique aussi un changement au niveau de la terminologie utilisée pour désigner les éléments faisant partie d’une connexion SPDY.

  • Stream : Représente l’équivalent d’une connexion / réponse du protocole HTTP.
  • Frame : Un Stream est divisé en Frames. Un Control Frame contient les entêtes HTTP et un Data Frame contient les données de ce frame.

L’ordre d’exécution

Le plus simple des scénarios prévoit l’exécution suivante  :

  • Le client initie une requête SYN_STREAM.
  • Le serveur envoie une réponse SYN_REPLY.
  • Le serveur envoie un ou plusieurs éléments DATA. Ceux-ci contiennent les données à retourner au client.

L’implémentation

SPDY est actuellement supporté entièrement par Google Chrome/Chromium et Firefox. Toutefois, il n’est pas activé par défaut chez Firefox. Pour l’activer, il faut aller mettre la variable network.http.spdy.enabled à true dans la section about:config.

Tout récemment, Opera a mis de l’avant le support de SPDY dans une version expérimentale de leur navigateur.

Il reste maintenant à Internet Explorer et Microsoft d’implémenter SPDY dans leur navigateur. Le chemin ne semble tout à fait clair de ce côté. Microsoft propose lui aussi un protocole visant à améliorer la vitesse de connexion au web : HTTP Speed+Mobility. Il semble donc que, tant et aussi longtemps qu’il n’y aura pas consensus sur le protocole à utiliser, Microsoft va être adepte du statut quo pour Internet Explorer.

Engagement envers SPDY

Il va de soi que Google a déjà mis de l’avant, il y a de ça un bon moment, SPDY sur ces services. SPDY est utilisé notamment chez GMail, Google+ ainsi que la recherche Google.

Des acteurs  importants du web ont signifié leur intérêt envers la bonification proposée du protocole HTTP.  Il y a notamment :

Est-ce que mon site est déjà SPDY?

Il y a actuellement deux indicateurs permettant d’identifier si un site utilise déjà SPDY.

La console interne de Google Chrome. Cet outil est accessible par l’adresse chrome://net-internals/#spdy. Dans la section « SPDY Sessions », vous pouvez voir un résumé des sites ainsi que certaines statistiques d’utilisation de SPDY du navigateur. En bonus, vous pouvez voir en temps réel le déroulement des connexions SPDY en cliquant sur le lien View live SPDY sessions.

Dans le cas où vous n’êtes pas très orienté statistiques et détails internes, je vous conseille d’installer l’extension vous permettant d’activer un témoin visuel pour indiquer la présence d’une connexion SPDY.

Ce qu’attends SPDY

SPDY / HTTP 2.0 a un bel avenir devant lui.

Le protocole livre exactement ce qu’il promet : Une amélioration de la vitesse de téléchargement du contenu qu’une page web. Le plus magique dans tout cela est que la transition à SPDY se fait sans aucun impact aux applications et aux utilisateurs. Cela veut dire que l’implémentation de SPDY se fait de façon transparente.

Le support pour SPDY est encore embryonnaire. Nous allons entendre encore plus en parler à mesure que les grands joueurs (ex: Facebook) vont le proposer à ses utilisateurs.

Expérimentation avec System.Tuple – Du code sans DTO conventionnels?

Par définition, un DTO (Data Transfer Object) permet l’échange de données à travers différentes couche logicielles d’une application. À titre d’exemple, un DTO permet de représenter par une structure de données l’information qui va provenir de votre base de données. L’utilisation est au coeur même du principe qui permet d’écrire du code réutilisable et facilement maintenable.

Tuple, c’est quoi ça?

Un Tuple ou même n-uplet en français est une structure de données permettant de regrouper des types hétérogènes ensemble. Pour ceux plus familier avec l’aspect mathématique de la chose, un Tuple est le concept de Couple étendu à N types.

Avec .NET, il y a huit variations de la classe Tuple. Chacune des variations a son nom qui la distingue :

  • Tuple<T1> : Singleton
  • Tuple<T1, T2> : Couple
  • Tuple<T1, T2, T3> : Triplet
  • Tuple<T1, T2, T3, T4> : Quadruplet
  • Tuple<T1, T2, T3, T4, T5> : Quintuplet
  • Tuple<T1, T2, T3, T4, T5, T6> : Sextuplet
  • Tuple<T1, T2, T3, T4, T5, T6, T7> : Heptuplet
  • Tuple<T1, T2, T3, T4, T5, T6, T7, T8> : Octuplet
Il est possible de créer un Tuplet considéré comme infini ayant la signature Tuple<T1, T2,T3, T4, T5, T6, T7, TRest>. Il est considéré infini car le dernier type TRest peut être utilisé pour imbriquer d’autres Tuplets. Il n’y a pas de limite théorique au nombre de Tuplets qui peuvent être imbriqués.
Un Tuple ayant la signature Tuple<string, string, string, int, Image> peut se créer de la façon suivante, par exemple :


var tuple = Tuple.Create("Pascal", "Paradis", "pascal.paradis@gmail.com", 26, Image.FromFile("pparadis_avatar.png"));

view raw

gistfile1.cs

hosted with ❤ by GitHub

Le concept proposé

Mon but initial lorsque j’ai lu à propos de Tuple serait de savoir s’il serait réellement pratique de l’utiliser avec ExpandoObject pour transporter un certain nombre de données.

Avec la venue de la classe ExpandoObject dans .NET4, il est possible d’ajouter dynamiquement des propriétés à un objet. L’idée m’est venue de tenter de combiner, le temps d’un essai, de combiner ExpandoObject et Tuple ensemble.

Le concept que j’ai développé est disponible pour consultation sur GitHub. Il y a deux méthodes qui sont à regarder : TupleExemple.(Tuple<string, string, string, int, Image> user) et UserRepository.GetRegisteredUserList(). De plus, l’appel à ces deux méthodes est fait dans le constructeur de TupleExemple.

Le constat

Initialement, lorsque j’ai pondu ce code, j’ai été sur l’impression d’avoir trouvé une nouvelle façon d’écrire du code. Mon impression était, qu’avec un nombre limité de propriétés à transporter, un Tuple serait un excellent moyen de transport. Le seul facteur qui me permettait d’affirmer cela est que, dans ce cas-ci, je n’aurais pas à eu besoin de recourir à une classe servant de DTO.

Après relecture de ParseUserInformations, je crois qu’il faut utiliser beaucoup de jugement lorsqu’il est temps d’utiliser un Tuple pour exposer une structure de données qui sera au cœur de votre application. Sur 50 lignes de code, il est facile de se souvenir qu’Item3 est relié au courriel. Toutefois, qu’en sera-t-il lorsque vous tenterez de le faire la même chose avec 10 000 lignes de code?

À mon avis, un scénario idéal pour utiliser Tuple, serait dans le cadre d’opérations très ciblés ayant un contexte précis. Ce que j’ai souvent en tête, c’est une classe en charge de l’importation d’une liste d’utilisateurs dans votre base de données.

Le but serait d’avoir, au sein de la même classe ou méthode, tout ce qu’il faut pour récupérer la source de données originale. Soit la représenter avec un Tuple, faire les transformations nécessaires et l’importer dans votre base de données.

Un hommage à String.IsNullOrEmpty()

Il faut du recul pour se donner de la perspective sur le chemin qui a été parcouru dans les dernières années. En tant que développeur, il est force d’admettre que les choses évoluent dramatiquement rapidement.

Du côté de .NET, vous vous souvenez de l’époque de .NET 1.1? Comparé à ce qui est possible de faire aujourd’hui, il est à se demander comment il était même possible d’arriver à développer avec ce Framework là!

De mémoire, vous vous souvenez ce qui vous a marqué le plus avec la version 2.0 de .NET? Est-ce que ce serait l’un des points suivants ?

Providers

  • Membership
  • Role
  • Sitemap
  • Profile
  • Session
  • Web events
  • Web Parts

ASP.NET Code behind

/app_code ?

Generics?

ASP.NET Thèmes et skins ou même les Master Pages ?

Classes partielles

Itérateurs?

Non!

Pour moi, l’amélioration la plus marquante a été String.IsNullOrEmpty() aura été celle que j’utilise le plus dans tout le Framework. Elle fait, dans une très grande majorité de cas, partie de la première validation sur l’état d’une string lorsqu’on la reçoit en paramètre.

Son implémentation est très simple. Par son nom, il est très facile de déterminer son but : Est-ce que cette chaîne de caractères est de type null ou vide?

Sommairement, cette fonction permet de convertir le code suivant :

var isValid = (maString== null || maString.Length == 0);

de cette façon :

var isValid =  (string.IsNullOrEmpty(maString));

Un hommage

À la blague, j’ai même démarré avec la collaboration d’un ami un micro-blogue en hommage à String.IsNullOrEmpty(). Un billet que j’aime particulièrement est l‘internationalisation de String.IsNullOrEmpty(). L’article met en lumière qu’il n’est quand même pas si simple d’écrire cette même validation en Javascript.


String.IsNullOrEmpty = function(value) {
var isNullOrEmpty = true;
if (value) {
if (typeof (value) == 'string') {
if (value.length > 0)
isNullOrEmpty = false;
}
}
return isNullOrEmpty;
}

view raw

gistfile1.js

hosted with ❤ by GitHub

La validation poussée à son maximum

Lorsque j’ai eu à chercher des idées pour ce billet, j’ai trouvé le gist suivant sur Github (note : ne pas faire lire aux enfants) :

https://gist.github.com/1583796

Élégant, clair, très expressif et surtout vulgaire. Adorable! Pourquoi faire simple lorsqu’on peut littéralement inclure la totalité des validations de String dans la même fonction?

Conclusion

Je vais l’avouer, mon affection envers String.IsNullOrEmpty est légèrement démesurée.

Toutefois, à quand revient le dernier moment où vous avez écrit une validation pour déterminer si votre String était null ou vide à l’ancienne? Probablement que ça date de l’instant où vous avez découvert que la fonction existait.

Si vous êtes arrivés sur le billet et que vous venez d’apprendre l’existence même de cette fonction, je crois alors que ma mission de prêcher la bonne nouvelle aura été accomplie!