zaterdag 30 september 2006

Changing the default access modifier when adding a new class in VS.NET 2005

When you add a new class or interface to an existing project in Visual Studio.NET 2005, VS.NET 2005 will not define this class (or interface) as public by default.
In Visual Studio.NET 2003 however, new classes and interfaces always received the public access modifier by default, and I do like this VS.NET 2003 approach far better.

When I create a class-library, most of the classes and interfaces that are contained in this library are meant to be used outside the library itself. This means that I have to explicitly add the public access modifier to most of my classes, and this is a dreadfull job.
Not only is it a boring job to manually define this access modifier for (almost) every new class that you create, it sometimes causes me loosing some time as well:
Today, I created a new class in VS.NET 2005 in where I've written some unit-tests. I'm using Testdriven.NET to execute my unit-tests in Visual Studio, and as long as I executed only one Test-method at a time, everything went fine.
However, when I wanted to run all the test-methods that I've written in that class, Testdriven.NET didn't execute a single one of them. I didn't get any error-message, I just received the message: '0 tests passed, 0 tests failed'.
After some investigating, it turned out that my class didn't had the public access modifier, and was therefore internal. Adding the public access modifier fixed the problem, and all my tests ran smoothly.

After living with this little annoyance for a while, I thought that it should be possible to change this behaviour and make sure that every new class I create in Visual Studio.NET 2005 is marked as public. In the rare cases that I'll need an internal class, I'll just explicitly change the public modifier to internal.

Since every new item that you can create in VS.NET is based on a template (just like a Word document is based on the normal.dot Document Template), it should be rather easy to change this behaviour.
After some digging in the directory-structure of VS.NET 2005, I've finally found where those templates are being kept. They're in this directory:

<PF>\Microsoft Visual Studio 8\Common7\IDE\ItemTemplates\CSharp\1033

(where <PF> is your Program Files directory, or the directory where you've installed VS.NET)

In this directory, you'll find a number of zip files. I've just unzipped the Class.zip file, and editted the Class.cs file that was in it to this:

using System;
using System.Collections.Generic;
using System.Text;

namespace $rootnamespace$
{
public class $safeitemrootname$
{
}
}

Then, I've just added the changed template-file back into the zip-file and thought the job was done, so I tried to create a new class in an existing Class Library... Sadly, the new class was still not public by default...
After some searching, it appeared that I had to execute a command which would load the Item Templates into Visual Studio. The command to do so is:

devenv /InstallVsTemplates

This finally did the trick! When I add a new class in VS.NET 2005, this new class now has the public access modifier by default!

donderdag 28 september 2006

Session on Unit Testing & TDD

Tomorrow, I'll be giving a talk on Unit Testing and Test Driven Development at work. I just hope that everything will go smoothly, and that I can encourage a few collegues to effectively use Unit Testing. :)


VS.NET 2003 not supported on Vista ?

Today, I've encountered some articles on blogs that some unpleasant news.
It seems that Microsoft will not support Visual Studio .NET 2003 on Windows Vista; however, Visual Basic 6 will be supported. I do not understand the logic behind this;
I thought VB6 was deprecated ?
Why is VS.NET 2003 not supported ?

I hope that these rumours will not turn into reality, since I'm still using VS.NET 2003 as my primary dev-tool at work.


Frans Bouma: So, VB6 is more important then VS.NET 2003
Fear and Loathing: Join the Windows XP club ... for 5 more years or so
Paul Wilson: Vista will NOT support developers

zondag 3 september 2006

Collections in Business Entities

A while ago, I've been thinking on what would be the best approach to work with collections inside business entities.

As an example, I'll refer back to the domain classes I'm using in another post of me.
There, I have a class Order, and an OrderLine class. The Order class contains a collection of OrderLines.
In C# 2.0, this could look like this:

public class Order
{
private List<OrderLine> orderLines
= new List<OrderLine>();
}
The problem here, is that I want to have 'controlled access' to the OrderLines collection in the Order class.
What I mean is, that a consumer of these classes should not be able to add an OrderLine to the Order directly, since some additional action(s) need to be executed.



More precisely, if an OrderLine is added to the Order, I want to set a member of the OrderLine, so that the OrderLine knows to which Order it belongs.
Therefore, I create an AddOrderLine method in the Order class:
public void AddOrderLine( OrderLine ol )
{
ol.OwningOrder = this;
this.orderLines.Add (ol);
}
A consumer of the code should always use the AddOrderLine method if he wants to add an OrderLine to the Order.
You can enforce this easily by not making the orderLines member public; easy enough.
However, at one time, the consumer of your code (or you :) ) will want to iterate through the OrderLines of the Order, or he will want to know how many OrderLines an Order contains.



Now, you'll have several options to achieve this:

One solution is to expose the orderLines collection to the public. In other words: create a public property which exposes the collection to the outside:

public class Order
{
private List<OrderLine> orderLines
= new List<OrderLine>();

public List<OrderLine> OrderLines
{
get
{
return orderLines;
}
}
}

Although this is a solution, I do not like it.
Now, we're unable to force the user to use the AddOrderLine method. Since the OrderLines collection is now publicly exposed, it is now possible to just use the Add method of the List to add OrderLines to the Order.
The documentation of the classes could of course mention that you should always use the AddOrderLine method, but there's no real hard constraint here. (If the classes are used inappropriatly, the program could of course crash, so then there is a constraint after all. ;) However, then the programmer using those classes will maybe lose a lot of time to detect the error he made.

Another solution is to keep the OrderLines collection private, and to add some extra members to the Order class. In this way, uncontrolled access to the OrderLines is not possible.
However, there are offcourse disadvantages to this approach as well. First of all, you'll have to write some tedious code that just delegates the functionality to the Collection class, like this:

public class Order
{
private List<OrderLine> orderLines = ...

public void AddOrderLine( OrderLine ol )
{
ol.OwningOrder = this;
orderLines.Add (ol);
}

public int NumberOfOrderLines
{
get
{
return orderLines.Count;
}
}
}
Unnecessary to say that this is just a boring task.
Then, to be able to iterate through the OrderLines of an Order, you could write code like this:
public class Order
{
private List<OrderLine> orderLines = ...

...

public OrderLine[] GetOrderLines()
{
return orderLines.ToArray();
}
}
Actually, I think this is plain ugly.

I always have to make a choice between these 2 approaches, where each one has his disadvantages. After doing this too much, I wanted a better solution for this problem, and after some reading and experimenting, I finally found one. It is in fact such a simple solution that I can't imagine why I haven't been using this one much earlier...

It's just nothing more then this:
Keep the collection private, create the necessary methods to provide the necessary controlled access to the collection (for instance the AddOrderLine method, and create a public property which returns a read-only instance of the collection, so that you can iterate through the collection, change existing instances of objects within the collection (at least, this is only true if you have reference types in the collection; you will not be allowed to modify value types on a ReadOnlyCollection, get the number of objects that are in the collection, ...

In code, it looks like this:

class Order
{
private List<OrderLine> orderLines =
new List<OrderLine>();

public void AddOrderLine( OrderLine ol )
{
ol.Order = this;
orderLines.Add (ol);
}

public ReadOnlyCollection<OrderLine> OrderLines
{
get
{
return orderLines.AsReadOnly();
}
}

}
This is the C# 2.0 version.
Now, it is impossible to add OrderLines in an uncontrolled way, but it is possible to iterate the OrderLines that are in the collection, and modify existing OrderLine objects that are already in the collection (since it are instances of a reference type; if OrderLine was a struct, it would not be possible to modify them.

In C# 1.x, it looks like this:
class Order
{
private IList orderLines = new ArrayList();

public void AddOrderLine( OrderLine ol )
{
ol.Order = this;
orderLines.Add (ol);
}

public IList OrderLines
{
get
{
return ArrayList.ReadOnly (orderLines);
}
}
}
Here, I return a readonly copy of the ArrayList. It is still possible to iterate and change the items that are in the collection, but it is impossible to Add an OrderLine to the Order in an uncontrolled fashion like this:
Order o = new Order();
OrderLine ol = new OrderLine();
o.OrderLines.Add (ol);

In this case, a System.NotSupportedException will be thrown.
It would of course be nicer to not have an Add and Remove method on the read-only ArrayList property, like we've achieved in the C# 2.0 version (the ReadOnlyCollection class does not have Add and Remove methods).
In .NET 1.x we can achieve that by letting the property return an ICollection instead of an IList, however, then we're not able to use an indexer to retrieve an OrderLine like this:
OrderLine ol = theOrder.OrderLines[i] as OrderLine;
Therefore, I prefer to return an IList instead of an ICollection