Thursday, November 27, 2008

Thankful not just today...

Today is Thanksgiving over here in the U.S. It's a day that spurs us to think back over the past year and remember all the things for which we're thankful. While Thanksgiving the "Day" is almost over, I think we all need to remember that today is not the only day in which we should remember to be "thankful."

This year has been very turbulent for a great many people... both in the U.S. as well as the rest of the world. The crumbling housing and financial markets have sent shockwaves through an already fragile economy, with ripples that can be felt worldwide. Violence such as the recent attacks in Mumbai has shattered lives. The passage of Proposition 8 in California and similar referendums in Arizona and Florida have torn apart the stability of many families. For these things, no one can be thankful.

But even amongst these tragedies, there is room for most of us to be thankful. Most of us have been spared being directly affected by the worst that 2008 has tossed at as, and for that we can be thankful, even while we think of those who have been less fortunate. Amongst the darkness there have been rays of light shining forth. While the elections on November 4th were marred by Proposition 8, a brighter light shone forth that day.

In each of our lives we can find something for which to be thankful, something to lift our spirits and encourage us to make the new year a better one than the last.

So, looking back on 2008 and forward to 2009, here are a few of the things for which I'm thankful:


  • A stable job in a time of uncertainty.

  • A job that I actually enjoy with people I enjoy working with.

  • The love of my partner, family, and friends.

  • A house when so many are finding theirs in danger.

  • The joy brought into my life by the adoption of my two newest cats.

  • The memory of many years of love given by my sweetheart kitty Ophelia who passed away last year.

  • The continuing joy and love given by my other surviving cat Edison (also a rescue).

  • My health.

  • The good health of those I love.

  • November 4th and the hope for a long overdue change in our country's direction.

  • That Vista on my new laptop doesn't suck as badly as I was afraid it would.

  • That I get to sleep in tomorrow!

  • The presence of Hope which for so long seemed absent.

OK, so they're not all profound, but being thankful for the little things in life is just as important as being thankful for the big things. They're also easier to find. So for all those little things in life and the ability to find them, I'm thankful.

Thursday, November 20, 2008

XML Documentation (continued)

Wow! I got sidetracked on getting out some other posts and, well... life, and I just realized I never continued the articles I started about XML documentation! For my earlier posts about code documentation, see Documentation is the Key and XML Documentation. So, as promised, here's how I use XML comments to document methods and events.

Methods
Documenting methods can get a little more complicated. Like all other comment blocks, I always include a <summary></summary> tag that gives a brief description of the method. If the method contains parameters, I'll follow the summary with a <param> tag for each parameter passed. If the method returns a value, I'll follow the parameter tags with a <returns></returns> tag that describes the return value. If the method throws any exceptions, those get documented within <exception></exception> tags. Finally, if the method needs further explanation, I'll include a <remarks></remarks> tag and possibly an example in an <example></example> tag.

In addition to the above tags, method documentation might also include <see></see> tags to refer to related properties, methods, or classes. If I need to refer to a parameter by name within the documentation (outside of that parameter's <param> tag), I'll surround it with a <paramref></paramref> tag. If any parameter type is an enumeration, I may also include a <list></list> with enumeration values and their meaning within the context of the method.

Method comments can get rather complex, so here's an example:

''' <summary>
''' Saves the document to a file.
''' </summary>
''' <param cref="filename">
''' The name of the file to which the document will be saved.
''' <param>
''' <param cref="format">
''' The format in which to save the document. Can be any of
''' the following values:
''' <list>
''' <li>
''' XML
''' <description>
''' Document text and formatting saved using XML schema.
''' </description>
''' </li>
''' <li>
''' Binary
''' <description>
''' Document saved as binary data.
''' </description>
''' </li>
''' <li>
''' RTF
''' <description>
''' Document saved in rich-text format.
''' </description>
''' </li>
''' </list>
''' <param cref="overwrite">
''' If <b>True</b> and this file already exists, it will be overwritten
''' without warning. If <b>False</b> and this file already exists, this
''' function will not save the file and will exit with a return value of
''' <b>False</b>.
''' <returns>
''' <b>True</b> if the document was saved with no errors; otherwise,
''' <b>False</b>.
''' </returns>
''' <exceptions cref="ArgumentNullException">
''' Occurs if the filename is null (<b>Nothing</b> in Visual Basic).
''' </exception>
''' <exception cref="IOException">
''' Occurs if an error occurred attempting to write the file.
''' </exception>
''' <remarks>
''' <seealso cref="Load"></seealso>
''' </remarks>
Public Function Save(ByRef filename As String, ByRef format As FileFormatEnum, _
ByRef overwrite As Boolean) As Boolean
...
End Function


Events
Events are pretty straightforward. I usually don't do more than include a <summary> tag and possibly a <remarks> tag.

Example:

''' <summary>
''' Occurs when the document is being the completion status of the
''' progress has changed.
''' </summary>
''' <remarks>
''' The <see cref="ProgressUpdatedEventArgs></see> event argument
''' passed with the event contains an integer property,
''' <see cref="Progress"></see>, that contains the current completion
''' status, represented as a percentage.
''' </remarks>
Public Event ProgressUpdated as EventHandler(Of ProgressUpdatedEventArgs)


More Info
For a complete list of XML tags suggested by Microsoft, see Recommended Tags for Documentation Comments (C#).

Tuesday, November 11, 2008

Signed Assemblies and COM References

Something weird happened recently. A co-worker needed to use an assembly I had written, but he was going to be referencing it from a project that would be called from a classic ASP application so the assembly needed to be strongly-signed. "No problem," I thought. I strongly-signed my assembly and recompiled. A few minutes later another application I was working on -- which also used my newly-signed assembly -- started getting the following error:

"The located assembly's manifest definition with name [AssemblyName] does not match the assembly reference"

So what happened? I wouldn't think that just strongly-signing an assembly would cause problems, but apparently it did. After a bit of digging, I discovered the problem: my assembly had references to COM DLLs. When you add a reference to a COM DLL, Visual Studio creates an interop wrapper around the COM DLL... but you already knew that. What you might not have realized (I certainly didn't!) is that in order to use a COM DLL in a signed assembly, the interop file also has to be strongly signed. When I signed my assembly I inadvertently broke it because the interop files were still unsigned.

Once I knew that the solution was pretty simple: remove the references to the COM interops and add them back again after the project is strongly-signed. With the project strongly-signed, Visual Studio creates strongly-signed versions of the Interop files.

Not so fast...
Actually, the solution wasn't quite that easy. In addition to a reference to the strongly-signed assembly, my application also had references to the same COM DLLs used by that assembly. That meant I had a conflict because my application had unsigned interops for those DLLs but the signed assembly expected those interops to be signed.

Since I no longer actually needed those references in my project (I did at one point, but they were no longer necessary), I deleted them. After deleting those references from my application, I was started getting "File Not Found" messages. I didn't need references to the COM DLL in my application, but my referenced signed assembly did. The problem in this case was that I had copied my strongly-signed assembly to a shared folder and referenced it from there. What I didn't do was copy the strongly-signed interop files and my application could no longer find any interop files for those COM DLLs.

Once I copied those interop files to my network share, everything was fine. I also modified my post-build event to make sure those interop files got copied whenever a release build the project was run. My assembly worked, my coworker's project worked, and my application worked. Above all, I learned something interesting about the inner workings of .NET.

Conclusion
The whole experience was both frustrating and facinating. The error was very confusing and there didn't seem to be much useful information online. Apparently using a COM DLL in a .NET assembly that's then used in a COM environment doesn't come up all that often! Once I started getting a handle on the problem it seemed more logical, but then the next error in the stack reared up. Working through the chain of problems to get everything resolved was an exercise in persistance more than ingenuity, but in the end everything came together.

I never paid much attention to strongly-signing assemblies before this because I'd frankly never had a need to do it. The software I write is deployed internally, so I don't need to worry about third parties using my assemblies and I haven't had to write anything in .NET that needed to be used in a COM environment. However, since strongly signing a project takes all of two seconds once you've created a key I'm going to start strongly-signing all of my reusable code libraries and controls. It doesn't make any difference when the assembly is used in a non-signed project, but is essential in order to be used by a signed project so it just makes sense to me to be consistent and do it on every project.