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

Liftweb sample bootstrap with sbt-plugins

Project source accessible in github at https://github.com/heralight/lift_basic_runmode

  • Lift 2.5-M3
  • sbt-runMode (development, production)
  • sbt-js
  • sbt-less
  • modernizr
  • jquery 1.8.3
  • conditional runMode snippet
  • Twitter Bootstrap included to illustrate the use of sbt shell tasks

Goal

Optimize build process in development and production by:

  • conditional compilation js and style files depending on mode configuration.
  • concat file or not
  • compress file or not
  • simplify debugging by separating files in development mode.
  • test production output easily
  • Add custom sbt task like bash script and link to actions

Installation

Uses sbt-plugins plugins.

The current version 0.6-M1 does not work properly with jetty v8. To fix this problem, you can use my fork.


In a temp directory git clone git://github.com/heralight/sbt-plugins.git 
cd sbt-plugin
clean-cache publish-local 

Structure

css and less in main/css js, coffeescript, template in main/js

These directories will be filtered and copied to resourceManaged and include in webappResources.

main js and css name : « app »

naming convention

if filename contains (rules in build.sbt)

  • .p. == production
  • .d. == development
  • .a. == add to output directory, will be included in webAppRessources path and war package.(a.p.xxx, a.d.xxx, a.xxx)

e.g.:

  • app.a.d.css => main css file in development and this file will be included to output directory.
  • app.a.p.js => main js file in production and this file will be included to output directory.
  • app-part.less => not parsed if not import in any « a » file.

Usages

start in development:

development:start 

start in production:

production:start 

stop in development:

development:stop 

stop in production:

production:stop 

dst and pst will do a stop and a start.

compile css manually:

xxmode:less 

compile js manually:

xxmode:js 

clean output:

xxmode:clean 
to clean only css xxmode:less::clean
to clean only js xxmode:js::clean 

Alias

already set in .sbtrc

 

    alias dst=;development:stop;development:start
    alias pst=;production:stop;production:start
    alias dsl= ;development:stop;~development:start
    alias psl= ;production:stop;~production:start
    alias dstop=development:stop
    alias dstart=development:start
    alias dc = development:compile
    alias pstop=production:stop
    alias pstart=production:start
    alias pc = production:compile
    alias dclean=development:clean
    alias pclean=production:clean
    alias djclean=development:js::clean
    alias dlclean=development:less::clean

 

Recommendation

make a clean before swapping modes.

For more details on sbt-plugins, refer to sbt-plugins Readme.

To go further, I recommend you mix this project with the lift-mongo.g8 produced by Tim Nelson.

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)