Saturday, June 24, 2006

Can't Open Dump File in Visual Studio

I don't seem to have the option to open 'Dump Files (*.dmp; *.mdmp)' in Visual Studio

Debugging with WinDbg

WinDbg is shipped with the Debugging Tools for Windows, and it is considered the most powerful windows debugging tool. It is truly a tool for the expert. As a senior developer I am often called upon to 'fix the problem' which is usually a production problem that cannot be reproduced in test. Since this has become a frequent occurence, I have decided to take on learning how to use WinDbg. Some good resources I've found so far include the Microsoft Patterns and Practices document 'Production Debugging for .Net Framework Applications' and John Robbins' Debugging Applications for Microsoft .Net and Microsoft Windows.

Why Can't I Open Dump Files?

My current employer provides the development team with a 'corporate' install of Visual Studio .Net 2003, which includes only the features they think we need. Since most development is done in C# and some in VB.Net, C++ is not included in the install. I believe C++ is required to open dump files in Visual Studio .Net. You can see what languages and tools you have installed by going to Help -> About Microsoft Development Environment...

I wonder why I would have to have C++ installed to open dump files? Presumably it is expected that dumps are generated for native C++ code, and if you don't develop in that language you don't look at dump files. Maybe it is not useful to look at a dump of managed code in Visual Studio? I imagine you would have to load the SOS debugger extension to debug a dump in studio, I seem to be having more luck using WinDbg anyway. Stick with WinDbg, I sure it's worth the effort to learn.

Friday, June 09, 2006

.Net Assemblies and Layered Architecture

How should you physically implement a logically layered application?

My Story

In the book Domain Driven Design Eric Evans encourages the use of Repositories. A repository is an object that is responsible for persistence and retrieval of Model or Business Objects. The intent of the repository is to abstract the object storage mechanism. The interface to a repository should not be specific to a database technology, or any technology being used to permanently store or 'persist' objects. This abstraction allows you to easily change the underlying storage technology. Adding support for a new storage technology (I.e. another relational DBMS), means creating another matching set of repository objects.

Multiple Assemblies

With this in mind, I decided to create 2 assemblies to match the 2 layers. A Domain Model assembly and a Persistence assembly. The idea being that the persistence assembly could be dynamically loaded at runtime and thus chosen from a list of assemblies that support various DBMSes

After running FX Cop on my work, I tried adding the CLS Compliant flag to to satisfy the FX Cop audit.

using System;

The CLSCompliant attribute caused my Persistence assembly to fail on compilation, due to the fact that it referenced and returned types declared in another assembly. The other assembly was of course my Model assembly. This got me thinking...

Single Assembly

In other projects I have worked on, the persistence layer and model layer were combined in one assembly. The repository classes were included in a seperate namespace (and project sub-folder) and were therefore still distinct from the model objects. So logically the layers were seperate, but the physical implementation was a single assembly. The 2 layers worked very closely together and in many ways really acted like one layer. So this configuration also made sense.

The difficulty with the single assembly comes from the desire to 'swap' between persistence technologies. In the combined model, you can no longer load the repository objects you need at run-time. Supporting multiple database technologies requires the Domain assembly to contain multiple sets of repository objects collected in different namespaces, you would use the Strategy pattern to provide the runtime loading (abstraction from specific types), and some sort of controller to serve up the concrete repositories (based on a config setting perhaps). Each of the architectures has benefits and drawbacks. I like to reduce my assembly count though, and systems don't generally support a huge set of relational database technologies. So I think I will move my seperate assemblies into one. As the XP mantra goes, 'you aren't gonna need it' (Y.A.G.N.I.).

Friday, June 02, 2006

Application Specific Exception Classes

When should you create specialized exceptions in your C# application?

The .NET framework provides a few exceptions for use by applications, they are,

  • ApplicationException

  • ArgumentException

  • ArgumentNullException

  • ArgumentOutOfRangeException

and others...

These exception types are very useful and cover most cases. But they are usually not enough.
Let's say you have some special validation where arguments to a method have to 'jive'. Such as a ChangePassword method on a User object. The ChangePassword method takes maybe three arguments, oldPassword, newPassword and verifyNewPassword. The newPassword and verifyNewPassword arguments must match. You could just throw an ArgumentException and populate the message appropriately. This causes a potential issue since by raising a generic exception type you are forcing the caller to handle the exception in a generic way. If the caller wants to do something special for this error, it has to parse the error message. Not very nice.

Error Codes

The structured programming world employs error codes to relay the exception type. You could implement this in C# by defining a special exception type extended from Exception and include an integer ErrorCode property. Then assign every specific exception type a number using a series of enum types defined in the custom exception class. Use enumeration types to logically group exception types, and reduce the need to reserve blocks of numbers.

The error code solution works. However, imagine what the handler looks like from the caller's point of view. There is probably a switch statement of some kind. Not a very Object Oriented construct. In and Object Oriented design switch statements on enum codes do not belong. See Replace Type code with subclass. Enter Custom Exception Classes.

Custom Exception Classes

If you have error type codes, and you have switching logic on those codes, applying 'Replace Type Code with Subclass' will lead you down the path of custom exceptions. This essentially means creating a catalog of specialized exceptions derived from the Exception class in the System namespace.

Deciding what exception classes to create can be difficult. Over specialized classes could result in a huge and unwieldy group of exceptions. Under specialized classes are essentially meaningless. As in all object modelling, you identify classes to represent concepts in the domain. Exceptions are no exception(!) to this rule. Ask, what error condition concept you are trying to communicate. You might create an exception class to represent violation of an object relationship, or an exception to indicate an attempt to create a duplicate object. These classes would most likely include information regarding the objects involved, so as much information can be relayed to the user interface. Depending on the situation your exception classes may be more specific. For example, you may wish to express certain types of object relationship violation errors.

Be Agile

Attempt to model your exceptions based on the current need. Don't attempt to satisfy all possible scenarios. If you know how the caller will deal with the exception, model to that requirement. Extend later. If you find yourself tempted to add error numbers and switch on them - refactor to create exception classes.

It is somewhat painful to create exception classes properly. Run FxCop against your assembly and you'll see what I mean. If you are creating many exception classes it would be wise to create a codegen macro in VS, or at least have some code to copy/paste from to make it easier. You may also find yourself creating exception classes that add nothing. No additional data or methods, just a new type. I think this is OK, so long as you have catch statements for those exception types.