Archive for Level 300

New version of Code Contracts

Microsoft DevLabs released a new version of Code Contracts yesterday, for both .NET 3.5 and 4.0 frame­works. You can download it at http://​msdn​.microsoft​.com/​e​n​-​u​s​/​d​e​v​l​a​b​s​/​d​d​4​9​1​992.aspx.

Included in the new build are bug fixes and some nifty new features, such as the [ContractArgumentValidator] attribute to mark helper methods that perform if-​​then-​​throw style para­meter vali­dation (so the tools can recognize legacy "requires" methods) and the [ContractAbbreviator] attribute to mark methods that contain reusable Contract.Requires and Contract.Ensures calls.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Comments off

First Impressions: Scrum for Team System 3.0.3698.00 with Team Foundation Server 2010

A while ago, I installed a pre-​​release version of EMC's (previ­ously Conchango's) Scrum for Team System v3, using the RC version of Team Foundation Server 2010. Here are my first impressions.

Installation

Installation was a breeze. I installed the Process Template MSI on our server without a hitch.

Our envi­ronment was very simple, though:

  • VMWare virtual machine, 2 GB RAM, single "CPU"
  • Windows Server 2008 R2 x64
  • TFS 2010 RC

Configuration

After instal­lation, the SfTS Process Template Manager started and it was just a matter of clicking a few buttons to deploy the new templates to our existing Team Project Collection.

After that, we could create a new project based on the Scrum template using the Visual Studio Team Explorer.

Work Item Types

The first thing you notice after creating a new project, is that the Scrum template contains more types of work items than MSF-​​Agile:

Work Item Type Scrum MSF Agile
Acceptance Test Yes No
Bug Yes Yes
Impediment/​Issue Impediment Issue
Product Backlog Item Yes Yes ("User Story")
Acceptance Test/​Test Case Acceptance Test Test Case
Release Yes No
Shared Steps Yes Yes
Sprint Yes No *
Sprint Backlog Task Yes Yes ("Task")
Sprint Retrospective Yes No
Team Sprint Yes No

* : MSF Agile uses TFS' concept of an Iteration, but does not expose it as a Work Item.

We see that both templates, while supporting Scrum and being similar, approach the use of TFS differ­ently. In TFS, every work item type is trackable, and you can calculate statistics and run reports on it. This means that the Scrum template can easily track and compare releases, sprints and even retro­spec­tives. You can also specify which Release each Sprint belongs to.

I think it's unfor­tunate that MSF Agile 5 does not have a work item defi­n­ition for Retrospective, but luckily, SFTS3 does.

Let's have a look at some of the Scrum template's work item types:

Work Item Type: Product Backlog Item

The MSF-​​Agile template's standard type for filling up the Product Backlog is the "User Story", whereas in Scrum it's the "Product Backlog Item". I think the "PBI" notation is better; after all, you don't only want to add User Stories to the PB.

The input form for a PBI is nice, as you can see below:

Scrum Template for Product Backlog Item

Scrum Template for Product Backlog Item

I prefer this over the MSF-​​Agile template because it leaves me more room to type my Description, History is a separate tab, and "Feature Scope" to me is clearer than "Area" — even though it is the same thing.

Work Item Type: Acceptance Test

When writing a user story — sorry, a PBI — you also add one or more Acceptance Tests that define what criteria need to be fulfilled for the PO/​QA to accept the PBI as "done".

Scrum's Acceptance Test template is almost iden­tical to MSF-Agile's Test Case. In the former, you can link any other work item to a test as a source of failure (such as a contra­dicting user story). In the latter, you can add a priority to the test. Both features are nice.

Areas and Iterations

The Scrum template does not prepop­ulate these TFS value trees. I think this is a good thing; it annoys me that MSF-​​Agile prepop­u­lates the Iterations tree with 3 iter­a­tions, including report types, when I want to call my iter­a­tions "Sprints".

Work Item Hierarchy

The Scrum template supports TFS' new feature of hier­ar­chical work items. That is, you can link one work item as a child of another. A typical example would be a Sprint Backlog Task that is a child of a Product Backlog Item.

Team Site

The Windows SharePoint Services (WSS) Team Site that the Scrum template produces is, alas, no more impressive than the one from MSF-​​Agile. In fact, they are nearly iden­tical. I think there is a lot of oppor­tunity for improvement here, both on the Conchango/​EMC2 side and on the Microsoft side. Right now, if you want a really useful team site, you need Microsoft Office SharePoint Server (MOSS) 2010, which provides a far richer team envi­ronment. We chose not to go that route, and used the WSS portal instead.

Of course TFS' built-​​in Team Web Access also works with team projects created with SFTS3.

No Visual Management

Unfortunately neither the team portal nor the Web Access site provides a visual interface for managing work items. But Conchango/​EMC2 is preparing the Task Board appli­cation for just that purpose, priced at about $90 per developer (< 10 devel­opers) down to about $76 (> 50 developers).

Third-​​party products like Urban Turtle can also fill that gap, priced at about $50 per developer. I will have a look at Urban Turtle later; I was not able to install the pre-​​release builds on our Team Foundation Server, but I'm sure now that Visual Studio 2010 and TFS 2010 are released, Urban Turtle will not be far behind.

Compatibility with TFS 2010 RTM

In a test TFS envi­ronment, I upgraded a TFS 2010 RC with the prelease version of Scrum for Team System v3 to the RTM version of TFS 2010, and it worked without a hitch. This means the existing Scrum for Team System template works fine with the TFS RTM, and existing work items remain unchanged and continue to work just fine. I really like this; I feared it would be a real pain to migrate our project to the newer bits. It will probably also enable Conchango/​EMC2 to release the updated bits of Scrum for Team System 3 quickly.

Early Conclusion

My, admit­tedly limited, expe­rience with the Scrum for Team System v3 template is very positive, and we will defi­nitely continue to use this template at my current customer. I think it is a much better fit for Scrum teams than Microsoft's MSF Agile is, and it has some nifty features such as the Retrospective work item type to complete the expe­rience. Granted, there is some work to be done in the WSS Team Portal area, and I could not test the difference between Conchango/EMC2's template and Microsoft's when it comes to a SharePoint Server-​​based Team Portal. But all in all I can say that I think Scrum for Team System v3 is a winner.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Comments (1)

Tfs 2010 Error Tf203028 — No support for nested branch folders

There is a limi­tation in TFS 2010: it does not support nested branch folders.

Today I converted a directory, $/​MyProject/​Main/​Src/​MyFolder, to a branch. Later on I decided that I wanted a different structure, and deleted the MyFolder folder — even though it was converted to a branch. So, now I had no more branches, right?

Wrong. Later in the day I tried to convert $/​MyProject/​Main to a branch, and TFS complained because I had defined a branch in a subfolder of the Main folder:

TF203028: You cannot create a branch at $/​folder because a branch already exists at $/​folder/​subfolder.

There is no way in the UI to fix this.

So I did what I normally avoid: go directly to the TFS database. I made a backup of my Tfs_​DefaultCollection database — the project was in my DefaultCollection — and deleted the offending (and only) row from the dbo.tbl_Branch table. I then exited Visual Studio 2010 and restarted it, tried again to convert $/​MyProject/​Main to a branch, and it worked!

I'm not advo­cating this tech­nique as a Best Practice — it seems that the Best Practice is actually to convert only the root folders of branches to branch folders. But when in a mess like this, when the UI does not offer any way of resolving the issue, this tech­nique is probably the best alternative.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Comments off

Yes! Pex 0.23 is out, the first Pex that is compatible with Visual Studio 2010 Release Candidate!

Not only is the new Pex actually compatible with the recently-​​released VS 2010 RC, it also sports a few new features and bug fixes.

Check out the Release Notes and Download this puppy today!

If you need some visuals on Pex, check out this excellent video (which demon­strates Pex in Visual Studio 2008).

Enough said.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Comments off

Conchango Scrum Template for Team Foundation Server 2010 R.C. now Available

EMC2, who took over Conchango, has made available a Release Candidate version of their Scrum templates for Team Foundation Server 2010 RC.

The download consists of a Scrum Masters' Workbench desktop utility and the actual process template. I'll be eval­u­ating this soon, so expect a "first impres­sions" review here on my blog in a week or two. I'm espe­cially inter­ested to see how it compares to the MSF-​​Agile 5 template, since Microsoft has revamped it to be (much) more like Scrum.

I've used Scrum for Team System 2008 about a year ago and was quite happy with it.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Comments off

Code Contract Coding Conventions

As in Brad Abrams' Framework Design Guidelines [Amazon][Barnes & Noble], which docu­ments coding and naming conven­tions for .NET, we need coding conven­tions for the new Code Contracts feature. What are yours?

These are mine:

DO use pre– and post­con­di­tions on all methods, public and private.

DO prefer to write contracts on inter­faces, then on abstract classes, then on concrete classes.

DO specify ArgumentNullException for non-​​null input parameters.

DO specify ArgumentOutOfRangeException for input para­meters that have to be within a certain
range.

DO specify post­con­di­tions, when possible, on functions.


   1:  public string NoSpacesAnywhere(string input, int range)
   2:  {
   3:      Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(inpu
   4:      t));
   5:      Contract.Requires<ArgumentOutOfRangeException>(range < 0 || range >
   6:      100);
   7:      Contract.Ensures(Contract.Result<string>() != null);
   8:  
   9:  }

DO write object invariant methods on classes that have prop­erties, even if they are not public. Write the invariants on the place­holder fields instead of on the prop­erties them­selves. This guar­antees that even if a method tries to be “clever” by updating a place­holder field directly, which it should not do, the condi­tions are still checked.


   1:  [ClassInvariantMethod]
   2:  void ObjectInvariant()
   3:  {
   4:      Contract.Invariant(_age >= 16);
   5:      Contract.Invariant(!string.IsNullOrEmpty(_name));
   6:  
   7:  }

DO write pre– and post­con­di­tions on prop­erties, unless you use auto­matic prop­erties. In that case, you must just write the condi­tions in the invariant, and they will auto­mat­i­cally be compiled into the property code.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Comments (1)

Code Contracts By Example

Earlier, I blogged about Code Contracts as a tool to help you specify and verify code behavior. Today let's have a closer look with a prac­tical example.

Say that we need to create a new class, a priority queue. We write the spec­i­fi­cation of the new class, natu­rally, as an interface to implement:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
namespace AdvancedCodeContracts
{
	/// <summary>
	/// Interface for priority queue classes.
	/// </summary>
	/// <typeparam name="T">Item type.</typeparam>
 
	public interface IPriorityQueue<T> where T : class
	{
		/// <summary>
		/// Gets the number of items in the queue.
		/// </summary>
		int Count { get; }
 
		/// <summary>
		/// Enqueues a new item with a priority (higher is better).
		/// </summary>
		/// <param name="priority">Priority between 1 and 100.</param>
		/// <param name="item">Item to enqueue.</param>
		void Enqueue(int priority, T item);
 
		/// <summary>
		/// Dequeues the item with the highest priority.
		/// </summary>
		/// <returns></returns>
		T Dequeue();
 
		/// <summary>
		/// Clears the queue.
		/// </summary>
		void Clear();
	}
}

This is a straight­forward, plain-​​vanilla priority queue as I'm sure we've all written at one stage or another. It is, of course, a Best Practice to imme­di­ately document the interface.

Now, can we already define what constraints to put on the implementation(s) of this interface? That is, can we write, per method and property, a set of pre– and post­con­di­tions that must be satisfied? Can we write an object invariant for the class?

Of course we can. We can also write unit tests for it. After all, we are all doing Test-​​Driven Development, aren't we?

So we must make a choice: either we write the contracts first, or the unit tests.

I think this choice is a matter of personal pref­erence. You have to write both before you do the imple­men­tation anyway… OK, true, you don't really have to, but it's a Best Practice to write code contracts before imple­men­tation, and it's another Best Practice to write unit tests before imple­men­tation. Why? Just because.

No, because this saves valuable devel­opment time as it cuts short debugging. It forces us as devel­opers to think about our approach before we start hacking away at the code.

OK, then, let's do those code contracts first.

But we don't have an imple­men­tation yet! So how do we approach this?

We can actually specify a code contract on an interface. Think inher­i­tance: all classes that implement the interface, inherit the code contract and thus must satisfy it. They can also extend the contract by adding extra post­con­di­tions to methods (not precon­di­tions) and extra object invariants. How cool is that?

So let's add a code contract to the interface. We start by adding a using and an attribute to the interface:

?View Code CSHARP
1
2
3
using System.Diagnostics.Contracts;
 
[ContractClass(typeof(IPriorityQueueContract<>))]

As you would imagine, this tells the compiler that there exists a class called IPriorityQueueContract that imple­ments a code contract on this interface. Notice the absence of the T in the attribute, though; you cannot use that syntax in an attribute, so you have to leave the generic T out. Believe it or not, this actually compiles, and it works, too.

Incidentally, if you are using .NET 4.0, you don't need to add any refer­ences to your project. The System.Diagnostics.Contracts name­space is included in mscorlib. But if you're old-​​school (still working with .NET Framework 3.5), you'll need to download the Code Contracts library and reference it.

OK, fine. Problem is of course that we don't have that class yet, so we create it:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using System;
using System.Diagnostics.Contracts;
 
namespace AdvancedCodeContracts
{
  [ContractClassFor(typeof(IPriorityQueue<>))]
  public class IPriorityQueueContract<T> : IPriorityQueue<T> where T : class
  {
    public int Count
    {
      get
      {
        return 0;
      }
    }
 
    public void Enqueue(int priority, T item)
    {
    }
 
    public T Dequeue()
    {
      return (T)new object();
    }
 
    public void Clear()
    {
    }
  }
}

It is my habit to call contract classes simply Contract. That is the convention I use, but you may have a policy against classes having names that start with I.

In this class, we specify that this is a contract class for the IPriorityQueue interface, and we actually implement that interface. That is why the Count property and the Dequeue() method are actually returning values; because we must implement the interface. The values that this class returns are irrel­evant and are ignored by the Code Contracts system.

Let's fill in the pre– and post­con­di­tions and the object invariant now:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System;
using System.Diagnostics.Contracts;
namespace AdvancedCodeContracts
{
 
  [ContractClassFor(typeof(IPriorityQueue<>))]
  public class IPriorityQueueContract<T> : IPriorityQueue<T> where T : class
  {
    [ContractInvariantMethod]
    void ObjectInvariant()
    {
      Contract.Invariant(this.Count >= 0);
    }
 
 
    // dummy implementation, we don't need a contract here
    public int Count
    {
      get
      {
        return 0;
      }
    }
 
 
    public void Enqueue(int priority, T item)
    {
      Contract.Requires<ArgumentOutOfRangeException>(priority >= 1 && priority <= 100);
      Contract.Requires<ArgumentNullException>(item != null);
      Contract.Ensures(this.Count == Contract.OldValue(this.Count) + 1);
    }
 
 
    public T Dequeue()
    {
      Contract.Requires<InvalidOperationException>(this.Count > 0);
      Contact.Ensures(Contract.Result<T>() != null);
      Contract.Ensures(this.Count == Contract.OldValue(this.Count) - 1);
      return (T)new object();
    }
 
 
    public void Clear()
    {
      Contract.Ensures(this.Count == 0);
    }
  }

In the object invariant, we say that the Count property must always return a positive number. Because we do so, we do not need to specify this again as a post­con­dition in the property itself.

The Enqueue() method lays down two preconditions:

  • The priority para­meter must be between 1 and 100, inclusive;
  • The item to enqueue may not be null.

The method further spec­ifies a post­con­dition that stip­u­lates that the Count property is increased by 1; so at the end of the method, the new value of Count must be the old value + 1. Note that currently, the Contract.OldValue() method is only valid inside a Contract.Ensures().

Next, we define a single precon­dition on Dequeue(): the queue may not be empty. We throw an InvalidOperationException if it is. We also specify two post­con­di­tions for this method:

  • The result is never null. We can guar­antee this because we don't allow enqueing null in the first place.
  • The Count property is always decreased by 1.

Finally, the Clear() method guar­antees, by means of a single post­con­dition, that the queue will be empty.

Are we having fun yet?

Note that all condi­tions in the code contract use public prop­erties or input para­meters only. There is no reference to any private vari­ables. This is logical even if the code contract is not just defined on an interface; it is a code contract after all, so its details must be visible outside of the implementation.

This code can compile, even though we don't have a concrete imple­men­tation of our priority queue yet.

So let's write a set of unit tests. Let's throw every­thing we can think of right now at that interface:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
using System;
using AdvancedCodeContracts;
using Microsoft.VisualStudio.TestTools.UnitTesting;
 
namespace AdvancedCodeContractsBlackboxTests
{
  [TestClass]
  public class PriorityQueueOfStringUnitTests
  {
    private IPriorityQueue<string> sut;
 
    [TestInitialize]
    public void TestInitialize()
    {
      sut = new PriorityQueue<string>();
    }
 
    [TestMethod]
    public void PriorityQueue_InitialState_Ok()
    {
      Assert.IsNotNull(sut);
      Assert.AreEqual(0, sut.Count);
    }
 
    [TestMethod]
    public void PriorityQueue_AddSingleItem_CountIs1()
    {
      sut.Enqueue(1, "This is one");
      Assert.AreEqual(1, sut.Count);
    }
 
    [TestMethod]
    public void PriorityQueue_AddSingleItemAndDequeue_Ok()
    {
      sut.Enqueue(1, "This is one");
      string result = sut.Dequeue();
      Assert.AreEqual(0, sut.Count);
      Assert.AreEqual("This is one", result);
    }
 
    [TestMethod]
    [ExpectedException(typeof (InvalidOperationException))]
    public void PriorityQueue_DequeueFromEmptyQueue_ThrowsInvalidOperationException()
    {
      string result = sut.Dequeue();
    }
 
    [TestMethod]
    [ExpectedException(typeof (ArgumentNullException))]
    public void PriorityQueue_EnqueueNull_ThrowsArgumentNullException()
    {
      sut.Enqueue(1, null);
    }
 
    [TestMethod]
    [ExpectedException(typeof (ArgumentOutOfRangeException))]
    public void PriorityQueue_EnqueuePriority0_ThrowsArgumentOutOfRangeException()
    {
      sut.Enqueue(0, "dummy");
    }
 
    [TestMethod]
    [ExpectedException(typeof (ArgumentOutOfRangeException))]
    public void PriorityQueue_EnqueuePriority101_ThrowsArgumentOutOfRangeException()
    {
      sut.Enqueue(101, "dummy");
    }
 
    [TestMethod]
    public void PriorityQueue_Clear_Ok()
    {
      sut.Enqueue(1, "One");
      sut.Enqueue(1, "Two");
      sut.Enqueue(1, "Three");
      sut.Clear();
 
      Assert.AreEqual(0, sut.Count);
    }
  }
}

Yes, the unit tests are written against an interface (IPriorityQueue). We do assume that we'll write a concrete class called PriorityQueue. We'll do that as the next step.

But first, let's look at these tests. They are of course quite straight­forward. Any class that satisfies these tests can right­fully be called a priority queue, even though in the TestInitialize() method, we instan­tiate our subject under test (sut) as an instance of the PriorityQueue class.

Convention Alert: I use the test naming convention _​_​. I find it makes for readable unit test code as well as readable test lists. Again, your mileage may vary.

Let's add a couple more tests just for fun:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[TestMethod]
public void PriorityQueue_AddMultiplePrioritizedItemsAndDequeue_Ok()
{
  sut.Enqueue(1, "This is one");
  sut.Enqueue(2, "This is two");
  sut.Enqueue(5, "This is three");
  sut.Enqueue(3, "This is four");
  sut.Enqueue(4, "This is five");
  Assert.AreEqual(5, sut.Count);
 
  string result;
  result = sut.Dequeue();
  Assert.AreEqual(4, sut.Count);
  Assert.AreEqual("This is three", result);
 
  result = sut.Dequeue();
  Assert.AreEqual(3, sut.Count);
  Assert.AreEqual("This is five", result);
 
  result = sut.Dequeue();
  Assert.AreEqual(2, sut.Count);
  Assert.AreEqual("This is four", result);
 
  result = sut.Dequeue();
  Assert.AreEqual(1, sut.Count);
  Assert.AreEqual("This is two", result);
 
  result = sut.Dequeue();
  Assert.AreEqual(0, sut.Count);
  Assert.AreEqual("This is one", result);
}
 
[TestMethod]
public void PriorityQueue_EnqueueMultipleItemsWithSamePriority_Ok()
{
  sut.Enqueue(1, "One");
  sut.Enqueue(1, "Two");
  sut.Enqueue(1, "Three");
  Assert.AreEqual(3, sut.Count);
}
 
[TestMethod]
public void PriorityQueue_ClearOnEmptyQueue_Ok()
{
  sut.Clear();
  Assert.AreEqual(0, sut.Count);
}

Uh, those tests are actually necessary – not just fun. Good that we caught them before we started writing "real" code.

OK, now we're ready to actually write the implementation.

In case you've never done TDD before: how do you feel right now? Don't you feel pretty sure that whatever we'll come up with as code will be tested very well? And what are the odds that we'll come up with working code quickly, without too much "red" in our unit test results?

Here's a concrete, if simple, implementation:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
 
namespace AdvancedCodeContracts
{
  public class PriorityQueue<T> : IPriorityQueue<T> where T : class
  {
    private List<Item> _list = new List<Item>();
 
    public int Count
    {
      get { return _list.Count; }
    }
 
    public void Enqueue(int priority, T toEnqueue)
    {
      Item item = new Item { Priority = priority, Object = toEnqueue };
      _list.Add(item);
    }
 
    public T Dequeue()
    {
      int highest = _list.Max(i => i.Priority);
      Item item = _list.First(i => i.Priority == highest);
      _list.Remove(item);
      return item.Object;
    }
 
    public void Clear()
    {
      _list.Clear();
    }
 
    [ContractInvariantMethod]
    void SpecificObjectInvariant()
    {
      Contract.Invariant(_list != null);
    }
 
    #region Nested type: Item
 
    private class Item
    {
      public int Priority { get; set; }
 
      public T Object { get; set; }
    }
 
    #endregion
  }
}

This is a correct imple­men­tation. How do I know? Because all unit tests run and the code contract is satisfied – otherwise at least one pre– and/​or post­con­dition and/​or object invariant would have failed.

Did you notice that this concrete imple­men­tation adds post­con­di­tions and a more specific object invariant to the contract? This is allowed because specific imple­men­ta­tions may offer extra output guar­antees (post­con­di­tions), and may include specific (read: private field/​property) invariants. Extra precon­di­tions are not allowed; as we inherit from a public interface or even a concrete imple­men­tation, we may not narrow the contract.

Next, we may modify the code for more perfor­mance, or better yet, write another imple­men­tation (say, a FastPriorityQueue) that imple­ments the same interface, and therefore the same code contract, and therefore – with one small change in TestInitialize() – the same unit tests.

Good code docu­ments and verifies itself. Code Contracts are the way to do it. Will they be part of your team's Quality Assurance arsenal too?

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Comments (3)