I was having an interesting discussion about Help Builder with Issam at DataDynamics about the Help creation process for large projects and components. He pointed me a feature in C# (and supposedly also in VB.NET for Whidbey) in the XMLDocumentation mechanism that I had never heard of.
In our discussion there a couple of interesting things came up to that I never thought about much. I figured Help Builder sort of as the documentation depository for documentation, so while code comments would be fine and Help Builder can import them either in batch (using an assembly import) or individually by using Help Builder’s add-in. So my thinking has been, that there's not much to worry about by not synching back religiously to the source code. However, the source based XML documentation is vitally important because VS.NET uses XML docs for Intellisense if it’s available.
If you didn’t know this make a note of it: Always copy both your assembly and the XML doc file if one is available into the main application that you’re running and debugging in order to get the fully doc'd XML comments with your Intellisense.
Anyway, the thing I missed previously to is that there’s an tag which allows storage of XMLComments in an external file, rather than in the source file itself. This works on per class basis and allows externalizing of comments which can be very useful if you plan on documenting extensively within your application. Externalizing the doc content also makes it easier to translate the documentation into other languages (gasp) which would be a bear to do in the source files.
The format for this looks like this (all on one line):
/// <include file='docs/CommandPrompt_docs.xml'
path='CommandPrompt_Project/CommandPrompt_Namespace/
CommandLoader[@name="CommandPromptLoader"]/*' />
For each member where you’d normally drop a comment you specify an XML file and an XPath string into the XML document to find the node. The syntax for each node should then look identical to the way it looks in comments except you can skip the slashes.
Let’s look at a quick example. I actually needed a quick utility today. As I was working with the MS 2.0 Help Compiler and some command line utilities I got sick of constantly popping up a DOS window and changing path. So I created a small Console application that takes a filename as a parameter and opens a console window in the directory of the file. I then stick this into the SendTo folder and whenever I need a command prompt I just right click SendTo command prompt and voila I’m there.
Here’s the code simple as it is:
using System;
using System.IO;
using System.Diagnostics;
namespace CommandPrompt.OS
{
/// <include file='docs/CommandPrompt_docs.xml'
path='CommandPrompt_Project/CommandPrompt_Namespace/CommandLoader[@name="CommandPromptLoader"]/*' />
class CommandPromptLoader
{
[STAThread]
static void Main(string[] args)
{
if (args.Length < 1)
Process.Start("cmd.exe");
else
{
// *** Change the path and open Command window
Environment.CurrentDirectory = GetPath( args[0] );
Process.Start("cmd.exe");
}
}
/// <include file='docs/CommandPrompt_docs.xml' path='CommandPrompt_Project/CommandPrompt_Namespace/CommandLoader[@name="TestMethod"]/*' />
public static string GetPath(string FileName)
{
FileInfo fi = new FileInfo(FileName);
return fi.DirectoryName;
}
}
}
With those comment pointers in place you now can create an XML file that looks like this:
<?xml version="1.0"?>
<CommandPrompt_Project>
<CommandPrompt_Namespace>
<!-- Command Loader Class and members -->
<CommandLoader name="CommandPromptLoader">
<summary>
This is the summary document for the CommandLoad class
</summary>
</CommandLoader>
<CommandLoader name="TestMethod">
<summary>
This is documentation for the TestMethod method.
</summary>
<param name="Test">String parameter for testing</param>
</CommandLoader>
</CommandPrompt_Namespace>
<SomeOther_Namespace>
</SomeOther_Namespace>
</CommandPrompt_Project>
I purposefully broke this XML out a bit to make it clear that you should very carefully think about how you lay out this XML file, so my preference here would be to use Project/Namespace/Class and member attribute as the way to lay this out. This is not really clear from the sparse documentation.
Now keep in mind that this is not really user friendly. First off you need to make sure that the names match which can be hard enough if you use a naming convention. You also need to make sure that the XML doc is valid or everything falls down. And managing text in this way can be tedious as hell. Remember there’s no Intellisense here either. Ultimately this would require a tool of some sort to be really useful.
However, because the XML is external to the code file you can create the entries first and then have the Doc team go in and manage updating the documentation without interfering with the source code. It’s also relatively easy to translate here this document since again it is external.
Anyway, so now I’m thinking about how I can take advantage of this functionality by providing the ability to backfit content from Help Builder into source code via possibly an external XML file. This would allow generating the content in Help Builder including the easy ability to edit the text in a rich environment that stays in sync.
My goal here is to treat Help Builder as the depository for the documentation, rather than the code or even this XML file. Although code and XML may have comments the ‘master’ copy would be in Help Builder. If this is the case Help Builder could then either manually or possibly (not sure yet how to do this) go back and update the documentation into the project.
Synching source code with something external is always a bitch. Help Builder links back to source code via member/class signatures based on namespace/class/member/parameters which uniquely identify members in source code. This is how the manual two way tools work when you right click on a member and Help Builder pops up in context. This works until a signature changes and then the link breaks. It can be overridden in Help Builder (the signature is editable) but it’s sort of a hassle, but doable on a single topic merge. However, in a batch situation this gets scary and would probably require explicit prompting whenever a signature cannot be found either prompting to leave it, find a match and resynch or throw it out.
I know that that many folks are seriously married to keeping comments all in code, but is this really where you want to do your documentation? Further if you use a tool like Help Builder you can take advantage of the rich interface and the ability to create content that is not directly tied to a say a class or method. For example a topic like a How To or Getting Started topic. But what am I talking about – good documentation is such a rarity these days that it can almost be discounted as non-existent.
Any comments on this?
Other Posts you might also like