Refactor to the NUnit Fluent API with ReSharper Code Patterns

by Alex Meyer-Gleaves 15 April 2010 - 7:19 PM

ReSharper Logo One of the new features in the recently released ReSharper 5 is Structural Search and Replace. This allows you to perform complex searches on your code, and then make equally complex replacements on the resulting matches. You can read the Introducing ReSharper 5.0: Structural Search and Replace post on the JetBrains blog to quickly bring yourself up to speed.

Solutions are commonly flooded with various code smells that are hard to eliminate right away. ReSharper 5 helps you get rid of them in existing code, but more than that, it allows you to create custom inspections to remove poor coding artifacts on a recurring basis.

Specifically, ReSharper helps configure custom, sharable code patterns, search for them, replace them, include them in code analysis, and even use quick-fixes for regular code maintenance! Building patterns and enforcing good practices has never been this easy. Corporate and team policies, custom frameworks, favorite open source libraries and tools — structured patterns are able to cover them all.

The coolest part of all this is being able to save the Structural Searches and include them alongside the built-in code inspections. NUnit is my preferred unit testing framework and I really like the fluent API it offers for making assertions. This seemed like the perfect opportunity to test out Structural Search by creating some code patterns that would find usages of the regular API and convert them to the new fluent API.

I basically wanted to find assertions that look this this.

object foo = new object();
object nullFoo = null;

Assert.AreEqual(1, 1);
Assert.AreNotEqual(1, 2);
Assert.AreNotSame(1, 2);
Assert.AreSame(foo, foo);
Assert.Contains(1, new List<int> {1, 2, 3});
Assert.False(false);
Assert.Greater(2, 1);
Assert.GreaterOrEqual(2, 1);
Assert.IsAssignableFrom(typeof(int), 1);
Assert.IsNotAssignableFrom(typeof(int), false);
Assert.IsEmpty(new List<int>());
Assert.IsFalse(false);
Assert.IsInstanceOf(typeof(int), 1);
Assert.IsNaN(double.NaN);
Assert.IsNotEmpty(new List<int> {1});
Assert.IsNotInstanceOf(typeof(int), false);
Assert.IsNotNull(foo);
Assert.IsNotNullOrEmpty("Foo");
Assert.IsNull(nullFoo);
Assert.IsNullOrEmpty(string.Empty);
Assert.IsTrue(true);
Assert.Less(1, 2);
Assert.LessOrEqual(1, 2);
Assert.NotNull(new object());
Assert.Null(nullFoo);
Assert.ReferenceEquals(foo, foo);
Assert.True(true);

And make them look like this instead.

object foo = new object();
object nullFoo = null;

Assert.That(1, Is.EqualTo(1));
Assert.That(2, Is.Not.EqualTo(1));
Assert.That(2, Is.Not.SameAs(1));
Assert.That(foo, Is.SameAs(foo));
Assert.That(new List<int> {1, 2, 3}, Contains.Item(1));
Assert.That(false, Is.False);
Assert.That(2, Is.GreaterThan(1));
Assert.That(2, Is.GreaterThanOrEqualTo(1));
Assert.That(1, Is.AssignableFrom<int>());
Assert.That(false, Is.Not.AssignableFrom<int>());
Assert.That(new List<int>(), Is.Empty);
Assert.That(false, Is.False);
Assert.That(1, Is.InstanceOf<int>());
Assert.That(double.NaN, Is.NaN);
Assert.That(new List<int> {1}, Is.Not.Empty);
Assert.That(false, Is.Not.InstanceOf<int>());
Assert.That(foo, Is.Not.Null);
Assert.That("Foo", Is.Not.Null.Or.Empty);
Assert.That(nullFoo, Is.Null);
Assert.That(string.Empty, Is.Null.Or.Empty);
Assert.That(true, Is.True);
Assert.That(1, Is.LessThan(2));
Assert.That(1, Is.LessThanOrEqualTo(2));
Assert.That(new object(), Is.Not.Null);
Assert.That(nullFoo, Is.Null);
Assert.That(foo, Is.SameAs(foo));
Assert.That(true, Is.True);

Nothing particularly difficult in this task other than a fair dose of pounding on the keyboard. After creating the first couple of patterns using the Pattern Catalogue dialog in Visual Studio, I exported the patterns to an XML file and continued my editing from there. Working directly with the XML in your favourite editor will certainly save you some time when making edits to your patterns in bulk. The end result was the list of code patterns below.

Pattern Catalogue

Now ReSharper will include these code patterns into its code inspections, and show the usual visual indicators for the Suggestion severity level.

Visual Indicators

JetBrains have given me yet another reason to love ReSharper. You can find an XML export of the code patterns attached.

NUnit Fluent API Code Patterns.xml (12.61 kb)

Tags: ,

Development Tools

Autofac 2.0 Podcast

by Alex Meyer-Gleaves 6 April 2010 - 5:47 PM

Make sure you have a listen to Nicholas Blumhardt talking about Autofac 2 on the Talking Shop Down Under podcast.

It's Inversion of Control Time! This week Nick Blumhardt talks about IoC containers in general, the problems with the service locator pattern and why constructor injection is considered a better choice, a little about how MEF and Autofac differ in purpose and a lot about Autofac 2's new features.

Nick was also a guest on .NET Rocks! last year, and that episode is definitely worth listening to as well.

The .NET dudes talk to Nicholas Blumhardt about Autofac, an IoC container that uses lambda expressions in C# 3.0 to create components.

Keep spreading the good word Nick!

Tags:

Autofac

Framework Design Guidelines Second Edition

by Alex Meyer-Gleaves 6 April 2010 - 5:33 PM

Framework Design Guidelines Second Edition I have just finished reading Framework Design Guidelines Second Edition and must say that I enjoyed the read. The first edition of this book was good enough to find a place on my shelf at the office and the second edition expands and improves upon the first. The many annotations dispersed throughout the book by various experts provide some interesting insight into the challenges they have faced. Best practice is not something that is immediately apparent, and often comes from having made mistakes and seeing how things pan out in the real world. It is very refreshing to see people like Brad Abrams and Krzysztof Cwalina drawing attention to the mistakes they made in designing the .NET Framework in order to help others avoid similar issues.

Brad Abrams: We added a set of controls to ASP.NET late in the ship cycle for V1.0 of the .NET Framework that rendered for mobile devices. Because these controls came from a team in a different division, our immediate reaction was to put them in a different namespace (System.Web.MobileControls). Then, after a couple of reorganizations and .NET Framework versions, we realized a better engineering trade-off was to fold that functionality into the existing controls in System.Web.Controls. In retrospect, we let internal organizational differences affect the public exposure of the APIs, and we came to regret that later. Avoid this type of mistake in your designs.

You can now see in the documentation that every type in the System.Web.UI.MobileControls namespace has been marked as obsolete. Working on a large product with a substantial investment in the underlying framework I can certainly appreciate that you will make mistakes despite your best efforts. Creating guidance that reflects what you have learned from past issues is a great way of limiting the accumulation of future technical debt. When the code you write represents a public API you need to very carefully consider each of your decisions. I too have a laundry list of things that I wish had been done differently, and I think anyone who has worked on a product or framework of a substantial size would as well. It is important to not just dismiss your mistakes, but to highlight them along with a means of avoiding in them in the future, and make sure they everyone on your team can learn from them.

Tags:

Microsoft .NET

About the author

Alex Meyer-Gleaves I'm a Technical Architect living in Australia (that island like continent in the southern hemisphere). I love Microsoft .NET and C#. I hate early mornings, slow drivers and Lotus Notes.

Twitter

Google Shared

 

Month List

Recent Comments

Comment RSS

Links

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010