Nuget – Bonnes Pratiques

Pourquoi choisir Nuget ?

Prenons une situation classique d’un développement en entreprise…

Contexte:

  • Nombreux projets
  • nombreuses libs communes interdépendantes
  • peu ou pas de stockage partagé ou mal utilisé
  • Svn ou Git

Sans Nuget

  • bibliothèques communes éparpillées sur chaque poste en différentes versions
  • plusieurs répertoires de bibliothèques communes avec leurs dépendances mélangées et incomplètes, avec pour seuls critères le nom du fichier dll et son numéro dans les propriétés du fichier.
  • Chaque développeur va compiler ces bibliothèques sans formalisme particulier à partir du gestionnaire de source, impossible de savoir quel version est réellement utilisée dans le projet, la version a-t’elle bien été incrémentée? …etc.
  • une bibliothèque X dépend de A en version 1.0 seulement, une bibliothèque Y dépend de A en version 2 ou +, le développeur ne sera pas averti du problème, et perdra du temps à comprendre son problème.
  • une bibliothèque X dépend de A en version 1.0 ou +, une bibliothèque Y dépend de A en version 2 ou +, X est installé en premier avec A1.0, Y ensuite, le développeur devra penser à upgrader A, fait non évident.

Résultats

  • Partage entre équipes très compliqué et non interactif
  • difficulté d’installer une lib en version précise et ces dépendances
  • Difficulté de monter en version sur une lib, car impossible de connaître rapidement toute les ramifications
  • Option viable pour un petit projet d’entreprise (un seul produit, très peu de lib, 2-3 développeurs max), mais pas industrialisable sur X projets et X bibliothèques. contre-productif…

Avec Nuget:

  • bibliothèque formalisée dans un paquet avec une version précise
  • paquet centralisé dans un serveur ou espace partagé
  • les dépendances entre lib sont définies au niveau du paquet, l’outil Nuget permet de rapatrier l’ensemble des dépendances d’une lib dans une version compatible.
  • lisibilité du nom de la lib, de la version, de ces dépendances, de son origine, de sa licence, …etc, directement dans Visual Studio.
  • la montée de version des bibliothèques d’une solution est automatisée avec une fonction d’update de Nuget.
  • une bibliothèque X dépend de A en version 1.0 seulement, une bibliothèque Y dépend de A en version 2 ou +, le développeur sera averti du problème.
  • une bibliothèque X dépend de A en version 1.0 ou +, une bibliothèque Y dépend de A en version 2 ou +, X est installé en premier avec A1.0, Y ensuite, Nuget met à jour automatiquement A.
  • partage entre équipes simplifié et synchronisé, toujours accès aux dernières versions sans interventions extérieures.

Relation Nuget / SCM / restauration automatique

Une source de problèmes liés à Nuget est les restaurations des dépendances.
2 politiques s’opposent, l’une consiste à commiter toutes bibliothèques au prix d’une charge de stockage plus grande sur le SCM (git / svn / …) l’autre à restaurer dynamiquement au risque de ne plus retrouver de vieilles version de dépendance aujourd’hui supprimée.
Ce choix dépend de votre infrastructure et de la durée de vie de votre projet…

Pour plus d’informations :

Une description plus complète de cette problématique est faite sur l’article suivant :
http://blog.ploeh.dk/2014/01/29/nuget-package-restore-considered-harmful/

Documentation officiel
http://docs.nuget.org/docs/workflows/migrating-to-automatic-package-restore

Blog d’un mainteneur du projet Nuget :
http://blog.davidebbo.com/2014/01/the-right-way-to-restore-nuget-packages.html

Versionnement des bibliothèques

Nuget se base sur la version de votre paquet pour résoudre les dépendances. L’algorithme de résolution utilise la nomenclature SemVer, un standard en numérotation de version.
Si vous ne respectez pas cette nomenclature, la résolution sera faussée et ça sera l’enfer sur votre solution !

Semantic Versioning (SemVer) en bref

SemVer décrit, pour les auteurs, une manière de définir des versions sémantiquement cohérentes. En un mot, les versions sémantiques ressemblent à MAJEURE.MINEURE.CORRECTIF(optionel=+metaData)), tels que:

  • le numéro de version MAJEUR quand il y a des changements rétro-incompatibles,
  • le numéro de version MINEUR quand il y a des changements rétro-compatibles,
  • le numéro de version de CORRECTIF quand il y a des corrections d’anomalies rétro-compatibles

Optionnellement un numéro de build ou de révision peut être ajouté en méta-données comme par exemple 1.0.0-beta+exp.sha.5114f85. Cette extension est ignoré pour le calcul des releases mais pris en compte avec l’argument « -Pre ».
Règle de dépendances entre paquet

Algorithm de résolution

  • 1.0 = 1.0 ≤ x
  • (,1.0] = x ≤ 1.0
  • (,1.0) = x < 1.0
  • [1.0] = x == 1.0
  • (1.0) = invalide
  • (1.0,) = 1.0 < x
  • (1.0,2.0) = 1.0 < x < 2.0
  • [1.0,2.0] = 1.0 ≤ x ≤ 2.0
  • vide = dernière version.

Avoir une règle de versionnement n’est que la moitié du puzzle. L’autre moitié est d’être en mesure de choisir la meilleure version parmi tous les candidats qui sont disponibles.
Un scénario:

  • A dépend de X 1.1 (qui signifie « >= 1.1 » comme indiqué ci-dessus)
  • B dépend de X 1.2
  • C dépend de X 2.0.1
  • X a des versions 1.0, 1.1, 1.2, 2.0 , 2.0.1+alpha, 2.0.1, 3.0, 3.0.1, 3.0.2+beta et 4.0 disponible.

La résolution de la version utilisée par NuGet est de toujours choisir la version la plus basse d’une dépendance.

Voyons donc ce qui se passera dans les différents scénarios :

  • Si vous venez d’installer A, vous aurez X 1.1
  • Si vous installez juste B, vous aurez X 1.2
  • Si vous venez d’installer C, vous aurez X 2.0.1

Si vous installez d’abord A, puis B , puis C

  • Vous obtenez d’abord X 1.1 lorsque vous installez A
  • X sera mis à jour en 1.2 lorsque vous installez B
  • X sera mis à jour en 2.0.1 lorsque vous installez C

Remarque : X.Y.Z+meta sera toujours inférieur à X.Y.Z et sera pris en compte qu’avec l’option « Prerelease ».

Mise à jour de dépendance après installation de paquet

Avant NuGet 2.5, quand un paquet à installé dépend d’un paquet déjà installé dans le projet, la dépendance sera mis à jour dans le cadre de la nouvelle installation, même si la version existante satisfait la dépendance. Cette mise à jour se limitera aux versions rétro compatibles.

À partir de NuGet 2.5, si une version de la dépendance est déjà satisfaite, la dépendance ne sera pas mis à jour lors d’autres installations de paquets.

Le scénario :

Le référentiel source contient le paquet B avec la version 1.0.0 et 1.0.2 . Il contient également un paquet qui a une dépendance sur B ( > = 1.0.0 ).
Supposons que le projet actuel a déjà la version du paquet B 1.0.0 installé . Maintenant, vous voulez installer le paquet A.

En NuGet 2.2 et plus:
Lors de l’installation du paquet A, NuGet mettra à mise à jour automatique B à 1.0.2, même si la version existante 1.0.0 satisfait déjà la contrainte de dépendance qui est > = 1.0.0.

En NuGet 2.5 et plus récent:
NuGet ne mettra plus mettre à jour B, car il détecte que la version existante 1.0.0 satisfait la contrainte de dépendance de version.
Pour plus de détails :

Documentation officiel
http://blog.davidebbo.com/2011/01/nuget-versioning-part-2-core-algorithm.html

Génération de paquet

Génération initiale du descriptif

Pour créer un descriptif de paquet, utilisez la commande ci-dessous à la racine de votre solution :

$> Nuget spec

Compléter ce fichier avec l’information dont vous disposez (licence, description,…). Vous pouvez laisser les token $xxx$ intact, ils seront rempli automatiquement par les informations de AssemblyInfo.cs

Générer le paquet

Remplissez le fichier AssemblyInfo.cs comme vous le feriez pour produire votre release.

Compilez en release ou exécutez la commande suivante :

$> msbuild votre-projet-ou-solution /target:Rebuild /property:Configuration=Release

Créez le paquet avec ces symbols de débogage :

$> nuget pack votre-projet-ou-solution -Symbols -Prop Configuration=Release

Uploader sur le serveur Nuget les 2 fichiers générés en même temps, le xxxx.nupkg et le xxxx.symbols.nupkg.

Bibliothèques interdépendantes

Ajouter le flag –IncludeReferencedProjects si votre projet a pour dépendance d’autre projet locaux à la solution qui vont être également converti en paquet Nuget.

Débugger avec les paquets Nuget

Le paquet symbols.nupkg contient les symboles et le code source de votre paquet, il vous permet de débugger votre application en ayant accès au code de ces dépendances.

Ces symboles sont stockés sur le serveur Nuget de symbole.

Pour configurer Visual Studio afin qu’il utilise ces symboles, suivez le tutorial en lien

Visual Studio 2010 Trucs et Astuces

Ci-dessous quelques trucs et astuces pour une utilisation optimale de Visual Studio 2010.

Les raccourcis claviers

Tout d’abord un lien vers les raccourcis clavier de Visual Studio ils vous seront très utile.
http://www.microsoft.com/download/en/details.aspx?id=13189

Si vous en avez que 6 à retenir, les voici:
_Ctrl + ‘,’ pour le « Navigate To » qui regroupe le Ctrl + N et Ctrl + Shift + N de Resharper.
_Ctrl + K + C et K + U pour commenter et dé-commenter du code.
_Ctrl + K + D pour formater le document en cours.
_F12 -> go to reference.
_Ctrl + ‘.’ affiche les aides possible.
et l’indispensable IntelliSense Ctrl+Espace.
Je ne rappellerai pas toutes les nouveautés apportées à Visual Studio 2010, ces dernières ont été assez commentées sur internet.

Activer la compilation incrémentale en tâche de fond

Disponible depuis Visual Studio 2008 Sp1, cette fonctionnalité vous permet d’avoir une vérification en continue de votre code sans avoir besoins de recompiler votre projet.
Pour l’activer, allez dans Options->Text Editor->C#->Advanced, et cocher
« Underline errors in the editor »
et « Show live semantic errors »
Pour plus de détails : http://ira.me.uk/2008/09/01/switch-offon-visual-studio-2008-background-compilation/

Afficher les numéros de ligne

Options->Text Editor->C# cocher « Line numbers »

Suivre le fichier courant dans le solution explorer

Options->Projects and Solutions cocher « Track Active Item in solution Explorer »

Plugins

Pour améliorer votre environnement vous pouvez installer les plugins (extensions) suivant:
_Resharper de jetbrains (lien)
_Highlight all occurrences of selected word (lien)
_Productivity Power Tools (lien)

Désactiver l’analyse de code de Resharper 5 à la volée