Skip to content
May 18 / davidalpert

More Sprache goodness

Following my experiment to write a parser for Visual Studio solution files using the Sprache library, I’d like to share a few Sprache techniques that I found useful.

Parse a token into an enum value

The Visual Studio solution file format includes a set of Project definitions, each with one or more ProjectSection definitions, as well as a collection of GlobalSection definitions.

    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
        Release|Any CPU = Release|Any CPU
    EndGlobalSection

Each ProjectSection and GlobalSection contains a token (preSolution in this case) that instructs Visual Studio when it’s contents are required during the process of opening a solution file:

To represent this in my data model I created the following enum to express these loading sequence tokens:

    public enum SectionLoadSequence
    {
        Unrecognized,
        PreSolution,
        PostSolution,
        PreProject,
        PostProject
    }

The Pre- and Post- nodes should be self-explanitory, but I want to temporarily call attention to the Unrecognized value.

I have found it useful to introduce in my grammars the concept of an unrecognized section which, while it may not survive into the final draft of a particular grammer, has allowed my parsers to handle structured content for which I have not yet written a detailed parser. In short, it has helped me during development, and whether it survives into the final draft becomes a question of how you want your parser to respond to input that is either not well-formed, or for which the format has changed.

But I digress.

Two of the fun constructs that ship with the Sprache library are the concept of Or, which lets you link alternative elements together, and Return, which lets you substitute anything you want in place of the parsed input.

Using these constructs, it becomes straightforward to write a parser for a range of enum values:

    public static readonly Parser LoadSequence =
        from sequence in Parse.String("preSolution").Token().Return(SectionLoadSequence.PreSolution)
                     .Or(Parse.String("postSolution").Token().Return(SectionLoadSequence.PostSolution))
                     .Or(Parse.String("preProject").Token().Return(SectionLoadSequence.PreProject))
                     .Or(Parse.String("postProject").Token().Return(SectionLoadSequence.PostProject))
                                                    .Or(Parse.Return(SectionLoadSequence.Unrecognized))
        select sequence;

Very expressive.

Parse unique inner content based on an opening token

Another useful construct that ships with Sprache is Then, which lets you determine which expectation follows based on the contents matched in the previous expression.

This is useful in the case of solution files because there are different types of GlobalSection, each with their own inner format.

Take, for example, the difference between a SolutionProperties global section:

    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection

and a ProjectConfigurationPlatforms global section:

    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Release|Any CPU.Build.0 = Release|Any CPU
    EndGlobalSection

Parsing (and eventually visualizing or manipulating) this last section’s inner content was my whole motivation for parsing solution files in the first place, but looking at the two together it is clear that the parser required to extract relevant details from the ProjectConfigurationPlatforms section would fail to parse a SolutionProperties section.

Luckily, the Then construct takes a lambda accepting the parsed content as an argument, so you can do something funky like this:

    public static readonly Parser GlobalSection =
        from start in Parse.String("GlobalSection").Token()
        from section in RoundBracketedString.Then(s => 
            s == "SolutionProperties" ? SolutionPropertiesGlobalSection
            : s == "SolutionConfigurationPlatforms" ? SolutionConfigurationPlatformsGlobalSection
            : s == "ProjectConfigurationPlatforms" ? ProjectConfigurationPlatformsGlobalSection
                                                   : UnrecognizedGlobalSection(s))
        from end in Parse.String("EndGlobalSection").Token()
        select section;

In between the GlobalSection and EndGlobalSection tags, we first parse the RoundBracketedString that differentiates what kind of global section we’re dealing with. Then we accept the inner content of that round bracketed string and supply different parsers customized for the expected format of each type of section.

Notice again that I have created an UnrecognizedGlobalSection that accepts the section type as an argument. This parser simply swallows everything until the next EndGlobalSection tag, saving it for later use in a diagnostic message while allowing the parsing to continue without exception.

Tip of the iceberg

These two use cases represent just the tip of the iceberg in terms of the possibliies offered by Sprache.

I’m very excited by this library and look forward to using it to explore even more complex grammars.

What content have you had to parse that could benefit from this level of expressiveness?

May 5 / davidalpert

Parsing VS Solution files with Sprache

Anyone who has worked with Visual Studio and more than one branch of active development has been bitten by the friction of merging solution files.

The format of solution files is a bit esoteric, with lots of key=value pairs and guids representing projects, project types, and build configurations. Merging individual lines often requires so much effort that most devs I’ve spoken wtih recommend picking one branch or the other and manually re-constructing the other branch’s changes. Needless to say this work is fidly and error-prone.

Somewhere I got it into my head that building a tool to help this would be a good idea, and apparently I’m not alone in that thought. When sitting down to write this post, I discovered the SLNTools project on codeplex; it looks interesting and I’ll have to try it out.

In the meantime, however, I wanted to share with you a bit about my experience building a parser for solution files using the Sprache library developed by Nicholas Blumhardt.

Some background

The idea behind Sprache is to fill the void between Regular Expression for parsing simple things and using full-blown DSL or parsing toolkits to describe complete grammars on the other.

Sprache takes a functional or parser combinator [PDF] approach; the library provides a set of .NET classes and extension methods that handle low-level parsing jobs like consuming input one character at a time and defining sequence and look-ahead expectations. These tools are exposed as a collection of Parser<T> constructs (where T is the type returned by a successful parse) that can be composed in a declarative style using LINQ query comprehension syntax.

The resulting parser can be very expressive, readable, and testable.

I’ll share some examples as I build up my SolutionFileGrammar below, but here’s a taste to whet your whistle:

public static readonly Parser<SolutionFile> Solution =
        from header in Header
        from projects in Project.Many().Optional()
        from globals in Global
        select new SolutionFile(header, projects, globals);

About Solution Files

In order to define a parser for the Solution File format we have to understand how it is structured.

The best description of solution file syntax I have found is this excerpt: Hack the Project and Solution Files.

Let’s take a look at a empty VS2012 solution file:

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Global
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
EndGlobal

And now one with a single project and it’s default build configurations:

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpWebAdapters", "HttpWebAdapters\HttpWebAdapters.csproj", "{AE7D2A46-3F67-4986-B04B-7DCE79A549A5}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
        Release|Any CPU = Release|Any CPU
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Release|Any CPU.Build.0 = Release|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
EndGlobal

And finally, one with Nuget Package Restore enabled, which adds a solution folder and some freestanding solution items:

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpWebAdapters", "HttpWebAdapters\HttpWebAdapters.csproj", "{AE7D2A46-3F67-4986-B04B-7DCE79A549A5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{8374A24A-6031-48CB-8B66-A2B510FA251F}"
ProjectSection(SolutionItems) = preProject
        .nuget\NuGet.Config = .nuget\NuGet.Config
        .nuget\NuGet.exe = .nuget\NuGet.exe
        .nuget\NuGet.targets = .nuget\NuGet.targets
    EndProjectSection
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
        Release|Any CPU = Release|Any CPU
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {AE7D2A46-3F67-4986-B04B-7DCE79A549A5}.Release|Any CPU.Build.0 = Release|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
EndGlobal

And now, the parser

In order to parse this with Sprache we need to decompose it into smaller and smaller pieces, build parsers for each of those pieces, then assemble those pieces into a grammar.

We experess that Grammar with a series of static methods that can be built-up test-first by starting with one of the smallest or inner-most pieces of nested content.

For eample, let’s take the header first:

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012

The relevant pieces of information are: - a version declaration; and - a product description

Taking that first part, the version declaration, we can focus smaller still on just the version number itself:

[Test]
public void SolutionVersionNumber_is_Number_period_Number()
{
    var input = @"12.00";

    var result = SolutionFileGrammar.SolutionVersionNumber.Parse(input);

    Assert.AreEqual(12, result.Major);
    Assert.AreEqual(00, result.Minor);
}

And write a parser for it:

    public static readonly Parser<SolutionVersionNumber> SolutionVersionNumber =
        from rawMajor in Parse.Number.Token()
        from period in Parse.Char('.')
        from rawMinor in Parse.Number.Token()
        let major = int.Parse(rawMajor)
        let minor = int.Parse(rawMinor)
        select new SolutionVersionNumber(major, minor);

There are a number of things going on here so let’s break it down.

First off we declare a Parser<SolutionVersionNumber> that will return our parsed result and then declare that a SolutionVersionNumber is composed of:

  • A number…

    from rawMajor in Parse.Number.Token()
    
  • …followed by a period…

    from period in Parse.Char('.')
    
  • …followed by a number

    from rawMinor in Parse.Number.Token()
    
  • then I use the let keyword to transform that parsed text into integers

    let major = int.Parse(rawMajor)
    let minor = int.Parse(rawMinor)
    
  • and finally the select keyword to create a new instance of my result:

    select new SolutionVersionNumber(major, minor);
    

Where a SolutionFileVersionNumber is part of our data model:

public class SolutionVersionNumber
{
    public SolutionVersionNumber(int major, int minor)
    {
        Major = major;
        Minor = minor;
    }

    public int Major { get; private set; }
    public int Minor { get; private set; }
}

then came the product name

Now let’s focus on the second piece that we want to parse, the product name:

# Visual Studio 2012

with a test:

[Test]
public void ProductName_is_pound_followed_by_text()
{
    var input = @"# Visual Studio 2012";

    var result = SolutionFileGrammar.ProductName.Parse(input);

    Assert.AreEqual("Visual Studio 2012", result);
}

and a parser:

public static readonly Parser<string> ProductName =
    from pound in Parse.Char('#').Token()
    from name in Parse.AnyChar.Until(NewLine.Or(Eof)).Text()
    select name;

and now the fun begins

Now that we have a simple, tested parser for the version number and another one for the product name, let’s write a test and parser for the whole header:

Given:

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012

here’s the test:

    [Test]
    public void Header_contains_version_information()
    {
        var input =
@"Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012";

        var result = SolutionFileGrammar.Header.Parse(input);

        Assert.AreEqual("Visual Studio 2012", result.ProductName);
        Assert.AreEqual(12, result.MajorVersion);
        Assert.AreEqual(00, result.MinorVersion);
    }

the parser:

public static readonly Parser<SolutionFileHeader> Header =
    from ignore1 in Parse.String("Microsoft Visual Studio Solution File, Format Version").Token()
    from version in SolutionVersionNumber
    from name in ProductName
    select new SolutionFileHeader(version, name);

and the object model:

public class SolutionFileHeader
{
    public SolutionFileHeader(SolutionVersionNumber version, string productName)
    {
        MajorVersion = version.Major;
        MinorVersion = version.Minor;
        ProductName = productName;
    }

    public int MajorVersion { get; private set; }
    public int MinorVersion { get; private set; }
    public string ProductName { get; private set; }
}

in conclusion

With that I hope that you can see how expressive a Sprache-based grammar is. It takes a bit of discipline to start with an individual token and grow your grammar test-first, but as your library of tokens grows, the size of your parsers grows also, and before long the declarative and combinatorial nature of Sprache has you moving along at a fast clip.

Full source code for this article, and a more comprehensive (though not yet complete) grammar, is available on github: https://github.com/davidalpert/viper

Apr 21 / davidalpert

NuGet Tip #3:
Manage packages at the solution level

Now that you’ve enabled package restore on build and set up your own package feed it’s time to take a closer look at how we add packages to our projects.

Most .NET developers spend a lot of time in visual studio and are more naturally comfortable with the GUI tooling than with command-line alternatives. The most common way that I see developers adding a NuGet dependency to a project is to right-click on the references node in the solution explorer and select “Manage NuGet Packages…”

right-click on the references node of a project

They pick their package, it downloads, the proper references are added to the project, and off they go.

manage project-level packages

Truthfully, this is all you need to get started and is enough for demos and screencasts, but let’s think about what is happening under the covers.

Under the covers

Once you select a package in the “Manage NuGet Packages” wizard and click install, here is roughly what happens:

  • Visual Studio reaches out through NuGet to download the latest version of the package bits into your packages folder.
  • If your project does not have a packages.config file, an empty one is added to your project.
  • If your packages.config file has an existing reference to an older version of the new package, the old one is removed, including the references into the old package folder.
  • A node describing the package is inserted into the project’s packages.config file
  • A reference into that package folder is added to the project.

There are two things about this process that may get you into trouble over time or on a large project:

  1. by default, nuget installs the latest version available at the time the reference is added.
  2. when nuget adds a package, it adds two independent references, one in the package.config file and one as a reference in the project file.

What’s wrong with the latest version?

On a large project, you often wind up adding new projects over time, often weeks or months apart. If you are always installing packages one project at a time, and a package author happens to release an update in between your two installs, you may wind up with two projects in your solution referencing different versions of a package.

In the best case, the updated package is fully backwards compatible with the old one and the difference may be transparent, or easily fixable with binding redirects. In the worst case, however, an upgraded package by contain breaking changes or expose a completely different API. Additionally, I have noticed that ClickOnce installs will fail if they contain two instance of the same assembly that are stamped with different version information.

When using nuget on the command line or in the powershell console inside visual studio you have options for specifying a specific version of a package, but no such luck in the “Manage NuGet Packages” dialog. So how to encourage our GUI-bound brothers and sisters to use consistent package versions across a project? Train them to manage packages at the solution level, as I explain below.

Where is my package reference?

Another quirk of the “Manage Package References” dialog is that its “Installed Packages” list appears to populate from the package.config file, ignoring completely any references that you have in your project. If for some reason you edit your packages.config file and remove a node, the visual studio tooling will no longer include that package under the installed list in the “Manage Package References” dialog nor will it restore that package on build, even if the reference in the project file remains pointed into the package folder.

Manage packages at the solution level

A good rule of thumb that addresses both of these issues is to always manage packages at the solution level. Right-click on the Solution node in the Solution Explorer and select “Manage NuGet packages for Solution“.

right-click on the solution node

The solution-level “Manage NuGet Packages” dialog is nearly identical to the project-level “Manage NuGet Packages” dialog, but instead of “Install” buttons you get “Manage” buttons and a list in the bottom part of the right-hand column of which projects have that package installed.

manage solution-level packages

Clicking on the “Manage” button will open a “Select Projects” dialog with a list of projects in your solution and checkboxes beside each one.

select projects

Check off the projects into which you want to install the new package, or check off new projects that you want to add this package to, click OK, and Visual Studio will loop through the projects uninstalling or installing the package based on the checkmark.

Were are my installed packages?

Similar to the project-level package dialog, this solution-level one has a quirk of its own. Rather than reading the packages.config files of each project in your solution, the “Installed” tab appears to populate based on scanning the packages folder of your project source files.

This means that if you have enabled package restore and not checked any projects into source control, a running this dialog after a fresh checkout will show you that no packages are installed.

As well, if you have been working with a solution over time and upgraded a package once or twice along the way, each version of that package that is living in the packages folder of your source files will appear in the “Installed” list of the solution-level packages dialog.

Apr 7 / davidalpert

This is me in grade 9; or
Nothing is real

To follow in the footsteps of fellow blogger Steve Rogalsky, this week I’d like to share with you a moment from my grade 9 chemistry class that changed forever the way that I learn and communicate.

I can still go back to that day, sitting in a school room on the west side of Montreal, watching Martin Hardiman draw circles around circles on a chalkboard and natter on about electrons, protons, and the periodic table.

Suddenly, he stopped writing.

Turning around, he said, “None of this is real.”

Dead silence.

Just like that he had all of our attention.

Bless his heart, for he went on to say something like this:

“We spend all this time teaching you about the structure of atoms and electrons and protons and chemical compounds and yet none of it is real; it’s only a model that approximates reality. In fact, there is no way to know what the structure of an atom actually looks like, in reality, because the act of looking at it changes it. Sometimes an electron behaves like a particle, sometimes it behaves like a wave. Is it either? I don’t think so. I think it’s something else entirely. The important thing is to remember is that both a particle and a wave are metaphors for this unapproachable reality. It can be useful to think in terms of models and metaphors because they allow us to understand and predict the behavior of the world around us, but don’t for a moment forget that models and metaphors are not, themselves, real.”

In the end, this concept helped to realize that the world that that I see is not the world that actually exists, but only my perception of it. Furthermore, the world that I perceive may differ wildly from the world that you perceive, and that is where life gets interesting.

When someone disagrees with me, that usually means that their mental model differs from mine. I find it helps to remember that neither of us is arbitrarily right or wrong, because it often leads me right into the more interesting questions about the impact or usefulness of my way of thinking, the other way of thinking, or sometimes even suggests an entirely new way of thinking.

Thank you, Martin. May you rest in peace knowing that you made a profound difference, well beyond the subject matter, on at least one of your students.

Mar 24 / davidalpert

Disable the XAML designer in Visual Studio

I interrupt my ongoing series of Nuget tips to bring you the following public service announcement.

After working on a WPF app for the past year or so, I have come to realize that no one on our team uses the XAML designer surface that ships with Visual Studio.  We all find it much faster to edit the XAML by hand, break up the XAML into manageable chunks, and generally stay away from the designer.

We also all notice that Visual Studio grows to consume large amounts of memory and locks up to a (Not Responding) message on a semi-regular basis.

This week a colleague showed me a couple of tricks to disable the XAML designer surface and squeeze a bit more performance out of Studio.

1. Default to full XAML view

Prior to this week our team had all done the obvious thing and told the XAML editor to default to XAML view, hoping that if we never opened the Designer view that would improve things.

image

In the Tools –> Options menu, open the Text Editor node, then the XAML node, then select the Miscellaneous node; make sure that under the Default View heading there is a checkbox beside Always open documents in full XAML view.

This got us part of the way there, with the code view opening by default when we opened XAML files, but Studio still locked up quite often.

2. Kill the designer rendering process

It appears that Visual Studio spawns a background process to render XAML for the Design tab of the default XAML editor so that it is ready to show on the design surface. 

image

Open the Task Manager, right-click on XDesProc.exe, and select End Process.

This process seems to start up whenever you open a XAML view in Visual Studio whether you ever click on the Design tab or not, which leads to the latest suggestion.

3. Open as source code

In order to prevent the designer from ever getting loaded, you can tell Studio to use a different editor entirely when opening XAML files.

image

Right-click on any .xaml file in your solution explorer and select Open With…

image

When the Open With dialog opens, you can pick anything you like as a default editor for XAML files.  The XAML UI Designer and XAML UI Designer with Encoding will both trigger the XDescProc.exe process to start up in the background, but the numerous other editors will not.

On our team we use the Source Code (Text) Editor.  Not only does it avoid slowing us down with the XAML UI editor, but it provides all the rich intellisense-supported goodness of the XAML tab from the default editor.  In short, our experience of editing XAML files is the same as when we tried to stay in the XAML tab of the default editor.

To do this, pick the Souce Code (Text) Editor and click Set as Default.

Happy XAML editing!

Mar 9 / davidalpert

NuGet Tip #2: Run your own package feed

Now that you’re using NuGet to manage the 3rd party code dependencies in your project and you’ve configured Visual Studio and MSBuild to restore missing packages as a pre-build step you can safely remove those packages from source control.

This provides a number of advantages, but it does expose you to a few risks:

  • The public NuGet feed may be unavailable when you need to download a missing package;
  • The specific version of a package that you depend on may be no longer available publicly;
  • The specific version of a package that you depend on may contain different code!

And so on; in other words, that convenience you gained by leaning on NuGet to manage your dependencies required you to give up a bit of control.

Reduce your risk with a private feed

Giving up control is a good thing in many situations, but when it comes to ensuring that you can reliably build and release your software it is sure helpful to make your process repeatable. When it comes to NuGet standing up a private package feed is one way to regain some of that stability.

Thankfully there are a number of options for creating a private NuGet feed:

  • myget is a software-as-a-service offering that provides externally hosted package feeds

  • the official NuGet docs describe two ways to Host your own nuget feed internally, one by standing up an in-house ASP.NET web site to serve packages and the other by simply pointing the NuGet tooling at a file share.

  • I experimented a while back with making it dead-simple to stand up a local NuGet server but I haven’t kept up with NuGet releases. When I revive that code I’ll be sure to write about it here.

Once you’re hosting your own internal feed you can configure Visual Studio’s NuGet tools or the NuGet command line app to include your feed when it looks for packages. For example, in the Visual Studio Tools –> Options menu, open the Package Manager –> Package Sources node:

Visual Studio Package Manager options

Back up your dependencies into your internal feed

Now that you are hosting your own package feed it’s a good idea to back up the packages that your projects depend on onto that internal feed. This is what enables you to take on management of the uptime of those particular packages rather than depending on the external state of the offical NuGet package feed.

Maarten Balliauw has a great post on how to Copy packages from one NuGet feed to another.

I personally recommend Rob Reynolds Nuget.Copy.Extension as I’ve used it several times:

NuGet.exe Install /ExcludeVersion /OutputDir %LocalAppData%\NuGet\Commands AddConsoleExtension

NuGet.exe addextension nuget.copy.extension

NuGet.exe copy castle.windsor –destination \\companyshare\nuget_packages

Prefer your local feed to the

Now that you have your own feed, you can tell MSBuild to use only your internal feed when downloading packages for a build. This will reduce the risk that a new build will mistakenly pull down a new version of a package dependency behind the scenes.

Open the NuGet.targets file:

Finding the NuGet.targets file

And change the following code:

<ItemGroup Condition=" '$(PackageSources)' == '' ">
    <!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
    <!-- The official NuGet package source (https://nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
    <!--
        <PackageSource Include="https://nuget.org/api/v2/" />
        <PackageSource Include="https://my-nuget-source/nuget/" />
    -->
</ItemGroup>

to:

<ItemGroup Condition=" '$(PackageSources)' == '' ">
     <PackageSource Include="http://myserver:8090/dataservices/packages.svc/" />
</ItemGroup>

with that middle line pointing to your internal feed; this will ensure that MSBuild only pulls packages from your feed.

Include your package repo in your backup and recovery plan

Finally, if you are hosting your own package repository internally in your organization, remember to include it in your backup strategy and your disaster recovery plan. There’s not much point in hosting your own feed if it goes down and you can’t recover the exact versions of the packages that your project depends on.

Remember also that the backup part of the plan is only a means to an end; it is the ability to recover and restore your package feed that will really matter if (or when) Murphy strikes.

Feb 24 / davidalpert

NuGet Tip #1: Restore Packages on Build

Nuget package restore is a way to tell MSBuild to download any missing packages as a pre-build step.

This means that you can exclude your packages from source control, making your repositories smaller, faster to work with, and cheaper to back up (as you have just removed a bunch of binary data that is painful to merge and doesn’t change very often).

Enabling package restore through Visual Studio is easy:

  1. Right-click on your solution node and select “Enable NuGet Package Restore”.

    alt text

  2. Click “Yes” in the confirmation dialog.

    alt text

  3. When the installation is finished you’ll have a new solution folder called “.nuget”.

    alt text

This process adds a copy of nuget.exe to your solution. It also adds some MSBuild targets that integrate with your project files to download missing packages as a pre-build step.

Check your .nuget folder into source control and anyone who donwloads your source will get nuget.exe and the MSBuild know-how to donwload missing packages as part of a build.

This is awesome, but brings with it a risk: what happens if your dependencies are not available when you go to build them?

Imagine that a new dev joins your team, gets latest on your source tree, and one of your package dependencies is not available in the public feed? How do they build the project?

Or…

Perhaps the package is available, but not the version specified in your projects’ packages.config files? You don’t want your team randomly getting the latest and greatest version of a dependent package any time they want, because we want to manage the risk that our code might break by using different versions of our dependencies.

To manage these risks I recommend that you set up your own internal package feed.

More on that next time.

Feb 24 / davidalpert

NuGet Tips

Nuget, the defacto package managment system for .NET development, has come a long way in a relatively short time. It does a pretty good job at simplifying and automating the process of downloading and referencing 3rd party libraries. It takes most of the guess work out of which versions of which dependencies need to come along for the ride in order for everything to work. It even works from both inside and outside of Visual Studio.

Kudos to Microsoft stepping into the package management space and working with the community to create a tool that many of us have come to depend on.

Using Nuget within a large project is not without it’s risks, however, so I share the following recommendations in the hopes that it saves someone else some time and trouble.

I will update this list as the tips come out.

Feb 10 / davidalpert

Testing should be fun

I had an interesting moment with a team member this week. We were pairing on a new feature that included some calculations and I suggested that this feature would be a great candidate for writing some unit tests. Despite showing a bit of hesitation, or at least none of the enthusiasm that I have come to associate with an experienced test-driven developer, he agreed to try it with me.

As we opened up some of the existing tests in the project that covered similar calculations I noticed that they were hard to read.

The tests were spread out with one test case per class/file and the test inputs and outputs buried in a lot of syntactical ceremony.

class When_converting_imperial_to_metric 
{
    void Should_have_expected_value()
    {
        result should be 23
    }

    void GivenThat()
    {
        mock unit.value to return 73
        mock unit.type to return Imperial
    }

    void WhenIRun()
    {
        result = calculator.Convert(unit, Metric)
    }
}

I’m using pseudo-code here rather than actual syntax but I think it makes the point.

After some basic refactoring to reduce ceremony and improving readibility we managed to reduce this quite a bit.

class When_converting
{
    void 73_imperial_should_become_23_metric()
    {
        unit = new Unit(73, Imperial)
        calculator.Convert(unit, Metric) should be 23
    }
}

Before moving on I want to call out a few things about this revised test:

  • it expresses the entire test as a single 2-line method that can be read and understood in a single chunk;
  • we are using a literal component instead of the mocked one;
  • the specific inputs and expected outputs are written with less noise so they can be identified more quickly;
  • the logic is ordered as
    [Given] setup, [When] I act, [Then] I expect
    which more closely matches a common pattern of speech than the original
    Should (behave as expected) - Given (mocked setup) - When (I act)

In the end, as we leaned back and looked at this revised test, my initially reluctant partner told me how this test made him want to write more tests.

And here we come to my ah-ha! moment.

Testing should be fun

If your tests are not fun to write, you have a problem.

Actually, you have a couple problems.

First off you are going to have a hard time convincing less experienced members of your team to climb up the learning curve and join you in covering your ass with tests while you are all coding up a storm under the heat of that upcoming deadline.

Beyond that, if your tests are not fun to write, the rest of your code probably isn’t either.

I’ve seen a high correlation between code that’s not fun to write and code that is difficult or expensive to maintain, so if your team isn’t having fun it’s likely to cost your busines real dollars.

Okay, I believe fun is cheaper. Now what?

So just how do we make testing fun?

Here are a few things that I’ve seen work well.

1. make testing accessible

  • name and organize your tests so that they describe business value, not implementation details;
  • favor specific scenarios over generic ones as they are often easier to read and understand;
  • remember that there is no one right size of unit for a unit test – the right size is the one that brings your team the most value for the investment;
  • favor literal components over heavy mocking as it’s more straightforward and can be a more realistic way of exercising your code;
  • introduce mocking only when needed to make tests fast or determinstic (see below) or else to ease setup;
  • I agree with Oren Eini on this one – I’d rather have 80 tests break at once and help me triangulate a problem than 100 tests that are so isolated they break one at a time.

2. make testing easy

  • invest constantly in removing friction from your tests;
  • ruthelessly drive out ceremony and repetitious setup and teardown so your devs can focus on verifying the business value of the test case at hand;
  • if tests are still hard to write review the code under test to see if responsibilities are broken out properly;

3. make testing fast and deterministic

  • the places to guard against coupling are at the latency boundaries or external dependencies of your code – database, internet, file system access, etc.
  • mocking here can increase the speed and predictability of your tests while reducing setup and teardown maintenance;
  • mocking inside those logical units, however, can make tests slow and cumbersome to write or debug.

4. make testing visible

  • the value of automated tests is when they provide tighter feedback loops that testers, stakeholders, and customers – run them often;
  • hooking up a continuous integration server to your source control system can ensure that tests are run on each checkin, nightly, or with whatever frequency makes sense for your team;
  • most continuous integration systems have some form of notifications or indicators that can signal team members when a test run passes or fails;
  • making the results of running your tests visible not only to individuals but across the team as a group can increase the accountability for team members to engage with tests and keep them passing;

In conclusion

If you have devs on your team who are reluctant to write tests, do some investigation.

Ask them why they don’t write tests in your system.

I bet that if you can put aside your ego and listen to their answer you will find something that can be done to improve the experience of writing tests.

That in turn will lead to more participation in writing and maintaining tests and that, finally, will lead to more participation in writing and maintaining your software.

Jan 27 / davidalpert

3 ways to remember which build you’re running

Often when building software we have to juggle several different build configurations, each pointing at different services, accessing different data, etc. During development it can be a huge time saver to have an easy way to know which build you’re looking at. I find this to be important when tracking features, defects, bug fixes, and deployments, for example, or that moment when you pause before submitting an order to check if it will actually be charged to the valid credit card number you’re using for integration testing.

Technique #1 – Color-Coded Icons

One of my favorite techniques for differentiating between builds during development is to use color:

image

In this case you see five different versions of the same icon, each one representing a different build configuration of the software my team is working on:

Configuration Description Color
DEV development/integration builds Red
QA internal releases to our QA/testing team Gold
UAT internal releases to our stakeholders Green
STAGE pre-releases to an environment that mimics production as closely as possible Purple
PROD production releases to our customers Blue

In our solution we have each icon named according to it’s configuration:

imageWe’ve used the VSCommands extension to group the configuration-specific ICO files “underneath” the one that the application is configured to use at build time.

We also use the following MSBuild target as a pre-build step to copy the configuration-specific icon into the right spot for the build to pick it up:

  <PropertyGroup>
    <BuildDependsOn>
      CopyEnvironmentSpecificAssets;
      $(BuildDependsOn);
    </BuildDependsOn>
  </PropertyGroup>

  <Target Name="CopyEnvironmentSpecificAssets">
    <ItemGroup>
      <AssetToUse Include=".\Application.$(Configuration).ico">
        <AssetToReplace>Application.ico</AssetToReplace>
      </AssetToUse>
    </ItemGroup>

    <Copy SourceFiles="@(AssetToUse)" DestinationFiles="@(AssetToUse->'%(AssetToReplace)')"/>
  </Target>

Technique #2 – Configuration-specific application name

Another technique that is useful is to add the configuration name to the application name that appears in the install shortcut, the window title, the add/remove programs dialog, etc.

Configuration Description Application Name
DEV development/integration builds Fancy App [DEV]
QA internal releases to our QA/testing team Fancy App [QA]
UAT internal releases to our stakeholders Fancy App [UAT]
STAGE pre-releases to an environment that mimics production as closely as possible Fancy App [STAGE]
PROD production releases to our customers Fancy App

We use this naming convention in our main WPF window, having it’s viewmodel read the title in dynamically from an application.resx resource file, though you could just as easily store it in an appSetting in your app.config file.  In either case the XmlTransform target is a handy way to use Web Config Transforms to swap in configuration-specific appSettings as a pre-build step.  And remember that RESX files are simply XML files:

image

so the Web Config Transform tooling works just great on those also:

image

Technique #3 – configuration-specific emails

In our case we have one email address to handle support requests. When a support or activation request email comes in it is important to know which build configuration sent it so that we can triage the email appropriately.

In the screenshots above you’ll notice that we transform the subject of our support email from:

  • Fancy App Support Request

to:

  • Fancy App [DEV] Support Request

or whatever other configuration we are targeting.  This let’s recipients quickly identify those emails that are sent by devs during integration testing (i.e. those with [DEV] in the subject line) and those that are sent by stakeholders (i.e. those with [UAT] in the subject line) and trim them out of emails without a configuration tag in the subject line that are sent by customers in the field.