The Tyranny of NuGet

If you are a reader of my blog then you are probably fairly firmly planted within the demographic of people that know what NuGet is, and what problem it is designed to solve. Just in case you aren't familiar with NuGet here is the elevator pitch.

NuGet is a package management tool used by (predominantly) .NET developers to share reusable libraries of code. It includes tools to specify what is in a package, create a package, distribute packages and download and install packages into your own software projects. When .NET was first introduced it didn't have a streamlined way of doing this so the community stepped in and created it in conjunction with Microsoft. NuGet has been very successful and is now the preferred way to share binary dependencies between .NET developers - even within the same team.

This post is about NuGet, but it isn't about how awesome NuGet is - it is more of a reflection on where we as a community find ourselves with NuGet today and whether it is the right solution for all of the places it has been employed.

NuGet Today

NuGet is used in a variety of places today. Obviously it is used within Visual Studio, or on the command-line to manage the packages that make up the dependencies of software that developers write. This is it's intended use. Not long after NuGet emerged the Chocolatey project was launched which leverages the same NuGet package format, and distribution technology but exploits it for installation of software. For example you can use Chocolatey to install text editors, browsers and any other manner of tools.

In addition to these two popular uses, NuGet is also used by the new PowerShell Package Management tools as one possible source/provider of packages, once again for installation of software. And finally, NuGet is also exploited by deployment management tools, one of the most popular being Octopus Deploy as a way of shipping files from the package source to an agent responsible for remotely installing software.

Broader Perspective

Having a good package management story, is, in my opinion one of the critical success factors for your development platform and/or operating system. The fact that the lines a blurred between package management for code dependencies, and package management for software installation is not unexpected as there is about 80% overlap in the requirements.

Looking around the rest of the technology landscape other communities have all evolved their own approaches to sharing libraries and software for installation. The Node.js community for example uses NPM which can install packages globally onto a machine or locally within an individual project. This is used to great effect by tool developers as a way of dropping down developer tools such as Bower, Grunt, and Gulp (to name but a few).

Each operating system also tends to have its own blessed package management format. For example, Linux has a few package management tools to support software installation, such as apt-get, RPM and others. On Windows we have the Windows Installer (MSI) framework which everyone loves to hate, and more recently the *.appx package format for more modern applications based on Windows Runtime or the Universal Windows Platform.

The Software Installation Gap

Personally I think that using NuGet for software installation as opposed to dependency management is an abuse of the technology.

Despite its unpopularity amongst developers I believe that the MSI format is superior in terms of its ability to express a complex installation, and when used correctly you can almost guarantee a clean uninstall experience. Where most people stumble is understanding the lifecycle of an MSI-based installation and the toolchain to build the packages themselves (most people lose a few fingers when they pick up WiX.

The more recently *.appx file format for modern applications which doesn't seem to have any relationship to the Windows Installer file format is also interesting because the package itself is largely self contained and doesn't result in files being sprinkled all over the users disk. The ability to declare what resources the application will use in the package manifest and then create a sandbox environment that holds the application to that is also a welcome addition in the packaging space.

Coming back to my thoughts on NuGet, I think it is an excellent dependency management tool for .NET based code, and it is nice to see it being backed in further into the .NET Core projects expressing their external dependencies explicityly in the project.json file.

As the Windows platform evolves I'm sure the trend to self contained applications that don't drop down lots of files in system directories and leave foot prints in the registry will continue (the *.appx format is good step, but limited in the kinds of applications it presently supports). Until that day arrives I think that Windows Installer is still the best format going on Windows for complex installations and formats like NuGet will be used to zip up MSI files which are then delivered to a machine via tools like Octopus Deploy, or alternatively the MSIs will be pulled down directly onto machines by configuration management tools like Chef, Puppet or PowerShell DSC.

Hope on the Horizon

On Windows specifically I think that there is hope on the horizon. PowerShell is the logical owner of package management, and their package management framework has been designed to be open in terms of the different sources of packages it can consume. With this I guess we'll at least end up with a consistent command surface for applying packages to a specific Windows box.