60
June 1, 2009 [DOCUMENTING EP-SOLUTIONS PROPRIETARY SOURCE CODE] Documenting ep-Solution’s Proprietary Source Code Proposed standards, process, tools, and practices Weatherford ep-Solutions | Introduction 1

Documenting ep-solutions proprietary source Web view[Documenting ep-solutions proprietary source code] ... the proposal I am presenting here is based on the C# .Net comment ... first

Embed Size (px)

Citation preview

June 1, 2009 [Documenting ep-solutions proprietary source code]

Documenting ep-Solution’s Proprietary Source CodeProposed standards, process, tools, and practices

Weatherford ep-Solutions | Introduction 1

June 1, 2009 [Documenting ep-solutions proprietary source code]

Table of ContentsIntroduction.................................................................................................................................................3

Source code documentation standards.......................................................................................................5

Guidelines................................................................................................................................................6

Comment headers...............................................................................................................................6

Types...............................................................................................................................................6

Variables, consts and simple #defines.............................................................................................8

Functions, functional macros, and methods...................................................................................9

Documenting source code...........................................................................................................................9

Legacy code.............................................................................................................................................9

Tools....................................................................................................................................................9

Practices............................................................................................................................................11

Using Understand Analyst.............................................................................................................11

Using our automated comment insertion/replacement tool.........................................................30

New Code..............................................................................................................................................30

Tools..................................................................................................................................................30

Practices............................................................................................................................................31

Source code documentation database..................................................................................................31

Tools..................................................................................................................................................32

Practices............................................................................................................................................32

epsDocTemplater Tool..............................................................................................................................33

Installation.............................................................................................................................................33

Compiling documentation for unmanaged C++ code............................................................................45

Examples...............................................................................................................................................46

Limitations and assumptions.................................................................................................................50

Weatherford ep-Solutions | Introduction 2

June 1, 2009 [Documenting ep-solutions proprietary source code]

IntroductionThe decision to better document our in-house source code is a welcome one to those who must maintain and extend that code, and should pay significant dividends in reducing future employee training costs and improving the quality of our code generally (code that is understood by all who work on it is more likely to be re-used, is less likely to produce errors, and makes a more solid base on which to write new code).

There are two challenges before us:

1. Documenting new code going forward; and2. Documenting our existing code base

These may seem out of order – certainly you would want to have your old code well-documented before basing new code upon it. However, documenting new code is a matter of setting standards for the documentation and policies to enforce those standards – you also need those standards in place before you can document the old code.

This document will serve as the foundation and vehicle for a discussion among stakeholders to establish standards, practices, and policies for documenting code. We will start by proposing a basic standard which will probably prove to be inadequate and will need improvement from all parties. This will eventually lead us to a determination of what our source code documentation should look like.

Once we have a documentation standard in place, we will need to apply that standard to all of the legacy code we possibly can. Let’s be absolutely clear about two things: The effort is going to be labor-intensive and the rewards will not be immediately felt. Unless there is a total commitment to the effort required and a complete acceptance that the intended results are for the long-term benefit, there is no point to starting this project – “partially reliable” and “partially consistent” source code documentation may be worse than no documentation at all.

Assuming management has signed off on the tenet that major effort will required for substantial payback over the long haul, we can address how best to expend that effort. The most expensive, potentially mistake-prone, and least productive method is to manually insert documenting headers above all of our (public) functions, methods, variable, and declarations. It has the additional deficiency that when you get done, you haven’t made the task of documenting other source code any easier.

However, the effort required to implement a manual solution should be the bar against which all other solutions should be measured – in other words, while a savings of the total labor is always desirable, the same labor which would have been required anyway but which produces multiple times the results or quality should be more desirable. This is particularly true when you recognize that the problems of documenting source code (old and new) are never going away, and that as long as you are in the business of producing or using source code you are going to have to document it - not only to get full value out of the source code (re-use), but to prevent severe maintenance and training costs that are

Weatherford ep-Solutions | Introduction 3

June 1, 2009 [Documenting ep-solutions proprietary source code]

multiplied by every single person who has to work with the code, multiplied again by every instance in which they have to work with it (information doesn’t stick unless it can be referenced).

For all of these reasons, the proposal I am presenting here is based on the C# .Net comment prefix and XML tags along with tools – tools we convert from some other purpose, tools we purchase, or tools we build if there is no other way. Tools have the tremendous advantage that they can be re-used and automated so that their benefits can be replicated over and over with substantially reduced costs for every use after the first one. There is a precedent for the combination of standards and tools for documenting source code in the JavaDoc model, and there are a number of third-party tools available that we can use or modify for this purpose if we mimic the C# .Net comment styles in all of our code as described below (i.e. Winnersh Triangle’s .NET documentation tool -http://www.winnershtriangle.com/w/Products.DotNetDocumentationTool.asp). There are articles and examples for building tools available on the Internet (http://www.codeproject.com/KB/XML/csharpcodedocumentation.aspx and http://www.codeproject.com/KB/XML/XMLDocStylesheet.aspx). And, Microsoft’s Sandcastle documentation compiler can use C# .Net-style comments for extraction (and we may be able through a pre-parsing tool to get Sandcastle to accept unmanaged C, C++, or FORTRAN code as though it were .Net code).

In addition to mapping out useful tools, strategies, and standards for source code documentation, this proposal extends the range and visibility of the source code documentation itself. Rather than have the documentation as classic static comment text bound to the source code, I’ve suggested a means and method for storing to a database the comment, its location, search keywords, time and date last edited, comment type, a unique identifier, and context text before and after the comment. A centralized independent database of source code comments provides the opportunity for any coder anywhere in the organization to locate by keyword, partial description, time range produced, function name, or other criteria relevant source code no matter where it resides, complete with context and de facto examples of use. This will promote re-use of code and drive us to standardized coding behaviors, as well as helping produce both technical and non-technical external documentation. Instead of having to find and interrupt a programmer who you happened to know from chatter in the halls once worked on a task of a certain kind, you can find the work he/she did for yourself.

The latter issue is not trivial. I’ve been looking at the LOWIS code for eight months at the time of this writing, and I am fully convinced at least eighty percent of the code I’ve seen is unnecessary. If you include not only the cut-and-pasted source code (bad enough for a myriad of reasons) but the hundreds of examples of solving the same problems in different (but duplicitous) ways as well as all of the projects that don’t commonly share code as modules, the percentage may well be higher. We may not be able to solve the problem in our legacy code, but we should certainly solve it going forward by making the existence of prior code and its capabilities known to all who need it. The point? Every reduction in the number of routines to be supported reduces support requirements by the multiple of the routines calling a single replacement function – it really is simple math, but the numbers are bigger than you think!

Weatherford ep-Solutions | Introduction 4

June 1, 2009 [Documenting ep-solutions proprietary source code]

The linkage between the database and the actual source code would be two-way. Once a comment in a line of code was anchored with the unique identifier, tools would be able to update comment changes made in the source code to the database, and update changes made in the database to the appropriate comments in the source code.

The tools required would fall into three categories:

1. Tools for creating new comment headers for (public) functions, variables, and declarations in legacy source code;

2. Tools to make it easier to automatically generate comment and header templates in the correct format for documenting new code; and

3. Tools to search and manage the database as well as the relationship between the comments in source code and the database.

In addition to easing the documentation challenges we face now and in future projects, the tools provide enforcement and assistance for the source code documentation standards we put in place.

The following sections provide more details in each of these subject areas.

Source code documentation standardsWe need to establish standards and requirements for the generation of comments in our source code for several reasons. First, we need to firmly establish in all coders’ minds exactly what is expected and to be able to police that expectation. Secondly, we need consistency in our comments so that coders can be reasonably sure that search criteria will find what they might be looking for. We also need to ensure that comments are written so they can be understood by our coders, and provide useful information without hindering or confusing source code production. Finally, standards will allow us to produce tools which can make it easier for coders to produce documentation by automatically inserting pre-templated comments into their code at the current cursor position when they press a certain key combination, as well as for batch-inserting relevant comment headers for public functions, variables, and declarations into uncommented legacy source code.

The coding standards will need to consider the main coding environments we use (C, C++, C#, and FORTRAN) as well as lesser environments like HTML, Java, VB, C/WScript, and where LOWIS is concerned, Case script. While the comment styles “/* comment */” and “// comment [EOL]“ will work for our implementations of the first four environments, the lesser languages and scripts use different syntax. Our tools will have to either sense the environment of the code being edited (may be difficult to do) or provide an easy means to persist the current code environment type (as a selection in a combo box in a non-modal comment-control dialog box, for example) in order to provide the correct comment syntax for generated comment templates or batch- inserted legacy documentation.

We are going to propose a set of guidelines (some of which will need to be defined as enforced “rules” by consensus of all interested parties) just to get the ball rolling on the standards discussion. We expect these to be greatly expanded, modified, and re-formatted as others input their ideas.

Weatherford ep-Solutions | Introduction 5

June 1, 2009 [Documenting ep-solutions proprietary source code]

Guidelines1. All public, exported and/or extern’ed functions, methods, variables, declarations, typedefs will

be documented with the appropriate comment header (from the descriptions below) describing their name, namespace, purpose, usage, restrictions, parameter types, limits, and ranges, return values, default initialization, and validation considerations, as well as any programmer notes;

2. All protected methods and variables declared in classes should be documented as though they were public if those classes are known to have derivations or would reasonably be expected to eventually have classes derived from them;

3. Private methods in classes should be documented as though they were public if they are referenced from source code files other than the one where the method body resides;

4. Where time and resources permit, all functions and methods (regardless of scope) should be documented at minimum with a comment header;

5. Comments other than headers, and the programmer notes fields of comment headers, should not be longer than three lines, and each line should not be more than 80 characters in width. Comments requiring more explanation should instead reference links to persistent centralizwed locations of external documentation;

6. For macros (#defines) that accept parameters, the expected parameterization types must be documented (because macros are inherently not type-safe and therefore potentially dangerous);

7. All comments will be assigned a unique identifier by the comment insertion tool(s) for tracking and synchronizing with an external source code comments database;

8. All references within comments (hyperlinks or file paths) to external documentation or other resources should be registered with the comment insertion tool(s); and

9. (Add more here)

Comment headers

TypesWhere the comment is standalone (that is, not embedded in a line of code) and when written for C, C++, C#, or FORTRAN code, each comment line should be prefixed by ‘///’ – three forward-slash characters. For other languages (HTML, VB, or script) you will need to use the prefix appropriate to the language in addition to and preceding the ‘///’ prefix. As an example, for HTML a comment line might look like this (don’t worry about the ID=”MYMJ123456789ABC” part just yet):

<!--///<remarks ID=”MYMJ123456789ABC”> This is a comment. </remarks>-->

A VB comment might look like this:

‘///<remarks ID=”POLT456843218FD3”> This is a comment. </remarks>

Each comment should be bracketed with XML-style tags describing the kind of item being commented. These tags will include the commonly-used C# tags, as well as tags we add. The following XML comment

Weatherford ep-Solutions | Introduction 6

June 1, 2009 [Documenting ep-solutions proprietary source code]

tags are officially supported in C#: c,code, example, exception, include, list, para, param, paramref, permission, remarks, returns, see, seealso, summary and typeparam.

c: This tag is used to denote code, so it can be used to identify sample code associated with a particular entity within the source code. Note that the tag can only be used to represent a single line of code or to denote that some of the text on a line should be marked up as code. Example: <c>double SalesTotal = 12</c>

code: This tag is used to denote more than one line of code, so it can be used to identify longer areas of sample code.

example: This tag may be used to describe an example of using a particular method or class. It is possible to include code samples within the example tag by making use of either the c or code tags.

exception: The exception tag allows a method's exception handling to be documented. The cref attribute allows the namespace of the exception handler to be included. Example: <exception cref="System.Exception" >Throws an exception if the customer is not found.</exception>

include: This tag allows documentation to be imported from an external XML file rather than being stored within the source code itself. As such it may be useful if the documentation is written by people other than the software developers (e.g. technical writers).

list: This tag allows bulleted or numbered lists or tables to be added to XML comments. para: This tag indicates that the text within the tags should be formatted within a paragraph. As

such it can be used to format text within other tags such as summary or returns. Example: <para>This is a paragraph</para>

param: The param tag is used to document a method's arguments. The tag's name attribute specifies the name of the argument to which the tag refers. The tag is also used by Visual Studio's Intellisense system to show a description of a method's arguments. It is also used by the Visual Studio Object Browser. Example: <param name="FileName" >The filename of the file to be loaded.</param>

paramref: This tag can be used to refer to a method's argument elsewhere within the method's XML comments. The tag's name attribute specifies the name of the argument to which the tag refers. Note that the param tag is actually used to describe the parameter. Example: Use the <paramref name="FileName"/> argument to specify which filename is loaded.

permission: The permission tag can be used to describe any special permissions a specific object needs. The object to which the permission refers is included as the cref attribute. Example: Class needs to write to the file system, ensure user has appropriate access.

summary: The summary tag describes a method or class, so it is the most important tag. As well as being used in a project's documentation, the tag is also used by Visual Studio's Intellisense system to show a description of the method or class being referenced. It is also used by the Visual Studio Object Browser.

remarks: The remarks tag can be used to supply additional information about a method or class, supplementing the details given in the summary tag. As with the summary tag, this tag is also used by Visual Studio's Intellisense system and the Visual Studio Object Browser.

returns: Describes the return value of a method. Example: <returns>True if user has permission to access the resource, otherwise False.</returns>

see: The see tag is used to reference other entities (such as classes) in the project. The see tag is intended for use within other tags such as the summary tag. Example: <seealso cref="System.Configuration"/>

Weatherford ep-Solutions | Introduction 7

June 1, 2009 [Documenting ep-solutions proprietary source code]

seealso: The seealso tag resembles the see tag and has identical syntax, except that the text is intended to be used to create a separate seealso section for the entity's documentation.

typeparam: Typeparam is used in an identical way to param, except that it is used to document a type associated with a generic class or function.

value: Value is only used when documenting a property, and is used to describe the value assigned to that. The comment is not required for properties that are marked as read only. Example: <value>Sets the employee's salary</value>

To these standard types, I would add the following comment types (primarily to support unmanaged C and C++ code documentation):

function: This tag identifies a header for a ‘C’-style function (as opposed to a class method). method: A header for a class method should be marked with the method tag. macro: This tag marks a #define that is inserted by the preprocessor and performs logical

operations. define: A #define that doesn’t fit the definition of a macro should be tagged with define. typedef: This marks is a type declaration, or assignment of a label to an intrinsic type. union: A declaration of a union should have a header tagged with union. enum: This header comment identifies a declaration of an enumeration. struct: This tag marks comment a declaration of an struct. class: A header for a class declaration should be marked with the class tag. extern: This tag marks an extern declaration of a variable declared or defined elsewhere

Every comment will include the language-specific prefix if needed (only when the source code is not C, C++ FORTRAN, or JAVA), the ‘///’ prefix, the XML prefix tag with an ID attribute, the comment text, the XML suffix tag, and the language-specific suffix if needed.

The ID attribute of the comment is supplied by one of the tools we will provide. The ID itself consists of a four-letter code identifying the computer along with a 12-character base-36 text representation of a high-granularity timestamp. The ID can be used by the external database to identify the computer that produced the comment, the time it was produced, the order in which comments were produced on that machine (for context), to identify the comment as one of our comment headers, and to tie an external database entry to a specific line in a source code file. The database record (produced by tools we will provide) allows enterprise-wide searches for sample source code, source code already written to satisfy a new task, and to inventory resources for library and assembly containers. It will also allow editing of comments from either the database or from the source code.

The tools that will supply comment header ID’s include a modeless utility to inject pre-formatted headers into the current cursor location when writing new code as well as tools that will automatically process and document legacy source code, as described in following sections.

Variables, consts and simple #defines Each declaration of a public, extern’ed, or exported variables, consts, and simple #defines and typedef’s should be documented with at least one, but no more than three, line(s) of explanatory comments, bracketed with the comment prefix and type as described above. Other than the use of the appropriate prefix and type, the comment contents are at the discretion of the programmer.

Weatherford ep-Solutions | Introduction 8

June 1, 2009 [Documenting ep-solutions proprietary source code]

Functions, functional macros, and methodsFor public functions and class methods, or macros that exhibit functional behavior, a more formal comment header is required. This header will look like this:

///<summary ID=”HR2G8D9S63OH677F”>/// Name: MyFooFunction()/// Purpose: Log message to status file/// Use conditions: File must not be read-only!/// Caller1: FirstMostPopularMyFooCallerFunction/// Caller1: SecondMostPopularMyFooCallerFunction/// Caller1: ThirdMostPopularMyFooCallerFunction/// (list no more than first three)/// Keywords: message status log/// Last author: Auto-commenter /// </summary> ///<param name=” pchFilePath” type=”char*”>Full path to status log file</param>///<param name=” bAllowRepeatMsgs” type=”bool”>Whether sequential message can repeat // /// the previous message</param>/// <returns>void<\returns> void MyFooFunction(char * pchFilePath,bool bAllowRepeatMsgs){...)

Documenting source codeThis section describes the tools we will acquire/build/use, and the techniques we will employ to accomplish each task.

Legacy codeThe challenge with legacy code is the sheer size and variety of the code we need to process, and the only reasonable means we have to ensure quality and consistent results is through the use of tools. We will use available third-party tools to process our source code and filter and identify the locations and types of functions, variables, and other declarations which need to be documented.

ToolsThere are two tools we will need to employ to process existing legacy code. The first will parse our existing code to locate, filter, and identify public declarations of functions, methods, variables, and definitions, and report those locations in some forma we can process in the second tool. The second tool will parse the output of the first tool, and for each location (in reverse order, that is from the bottom of the file up in order not to invalidate the location information previously collected) in source code it will go to that location and:

Identify and extract any comments already in the code immediately before that location;

Weatherford ep-Solutions | Introduction 9

June 1, 2009 [Documenting ep-solutions proprietary source code]

Identity and extract 256 characters of source code prior to that location (or prior to any existing comments immediately preceding that location);

Identity and extract 256 characters of source code after that location; Retrieve the function/method name and parameters (if relevant) from that location; Obtain a comment header ID from the high-granularity timestamp and machine name; Format an appropriate header style for the comment based on whether it is a variable, function,

method, or definition, and insert:o The appropriate comment header XML tag;o Any previously-written comments extracted from the source code;o The variable name and type, or function name and parameters;o The three most popular callers or referrers to the function or variable as identified by

the first tool; ando The appropriate comment header XML suffix.

Write the assembled header to the source code file; and Write the comment data collected to our central comment database.

The second tool will have to be custom-written – we should be able to create something relatively quickly in C# or script.

For the first tool, there are a number of third-party resources available (some of which would require modification and/or additional coding). I’ve identified the best of these as a product offered by SciTools as “Understand Analyst”. It has impressive analysis tools (for identifying what is public and what is not, for identifying callers of a function, as well as many others), can filter on a variety of criteria, and most importantly generates reports in text output that identifies all the elements we want, with their source code module and line number (which we can then use as input for the second, custom-coded tool).

Weatherford ep-Solutions | Introduction 10

June 1, 2009 [Documenting ep-solutions proprietary source code]

Practices

Using Understand Analyst

Understand Analyst opening screen

Weatherford ep-Solutions | Introduction 11

June 1, 2009 [Documenting ep-solutions proprietary source code]

The first step in using Understand Analyst is to create a new project (here we are going to analyze and document the LOWIS Tulz subdirectory):

Creating a new project

Weatherford ep-Solutions | Introduction 12

June 1, 2009 [Documenting ep-solutions proprietary source code]

For this demonstration, we are going to analyze (and ultimately document) for C/C++, C#, and FORTRAN languages:

Setting the languages we wish to analyze/document

Weatherford ep-Solutions | Introduction 13

June 1, 2009 [Documenting ep-solutions proprietary source code]

Now we must point the tool at the source code directory we want to analyze:

Choose the source code directory we want to analyze

Weatherford ep-Solutions | Introduction 14

June 1, 2009 [Documenting ep-solutions proprietary source code]

Set our directory choice options

Weatherford ep-Solutions | Introduction 15

June 1, 2009 [Documenting ep-solutions proprietary source code]

Accept the directory listing

Now we will start the analysis of our selected source code directory:

Start the source code analysis

You will see warnings about missing include files – for this demonstration we are going to ignore this warning (in actual use, you will have to assert your a priori knowledge of the directory and its

Weatherford ep-Solutions | Introduction 16

June 1, 2009 [Documenting ep-solutions proprietary source code]

relationship to other source code in order to resolve missing include files):

Ignore missing includes for this demonstration

Weatherford ep-Solutions | Introduction 17

June 1, 2009 [Documenting ep-solutions proprietary source code]

After several progress messages, our analysis is complete:

Analysis is finished

Weatherford ep-Solutions | Introduction 18

June 1, 2009 [Documenting ep-solutions proprietary source code]

Here we will filter for public function and variable declarations (this step is not necessary, but illustrates some of the capabilities of the tool for other uses):

Go to the entity filter explorer

Weatherford ep-Solutions | Introduction 19

June 1, 2009 [Documenting ep-solutions proprietary source code]

First we’ll filter for functions:

Set entity filter for functions

Weatherford ep-Solutions | Introduction 20

June 1, 2009 [Documenting ep-solutions proprietary source code]

From that result set, we’ll filter for just C++ global functions:

Filter just for C++ global functions

Weatherford ep-Solutions | Introduction 21

June 1, 2009 [Documenting ep-solutions proprietary source code]

This produces the following list:

The filtered C++ global function list

Here is just a small example of what the tool can produce as shown on the screen (here we’ve selected one of the filtered global C++ functions, run the update dependency menu command from the dependency tools and displayed a dependency graph, and displayed the “called by” property in the

Weatherford ep-Solutions | Introduction 22

June 1, 2009 [Documenting ep-solutions proprietary source code]

lower left tree):

Some information about our selected global C++ function

Of course, displaying this information on the screen does not help us isolate the information we want in a form suitable to our second tool, which needs to see the information in a form it can parse. To solve that problem, we need to export the information in a plain text format, and we can do that using the reporting tools provide by Understand Analysis. Fortunately it can output the information used to create

Weatherford ep-Solutions | Introduction 23

June 1, 2009 [Documenting ep-solutions proprietary source code]

screen elements as either HTML or plain text – to create a text report start here:

Start text report generation

Weatherford ep-Solutions | Introduction 24

June 1, 2009 [Documenting ep-solutions proprietary source code]

Now we need to configure the report we want:

Click configure reports button

Weatherford ep-Solutions | Introduction 25

June 1, 2009 [Documenting ep-solutions proprietary source code]

We want to set up a single text file report (just to understand what this tool can do, you may also want to produce an HTML report for your own viewing):

Set up a single text report

Weatherford ep-Solutions | Introduction 26

June 1, 2009 [Documenting ep-solutions proprietary source code]

Now generate the report:

Generate the text report

Weatherford ep-Solutions | Introduction 27

June 1, 2009 [Documenting ep-solutions proprietary source code]

After the text report has been completed, close the dialog:

Close the dialog after the text report is finished

The text file produced is quite large for this project – I will show you a tiny piece of it to illustrate the kind and quality of information that will be made available to our second tool for creating and inserting

Weatherford ep-Solutions | Introduction 28

June 1, 2009 [Documenting ep-solutions proprietary source code]

comment headers:

Text report sample data

In the report, the data is organized into several sections with readily identifiable separation text and unique element formats. This makes the report perfect for parsing by our automated comment header insertion tool. In the example above, we can discover the function name, return type, whether it is

Weatherford ep-Solutions | Introduction 29

June 1, 2009 [Documenting ep-solutions proprietary source code]

public, the class it belongs to, what functions it calls, the header and source code file locations where it is found, and the line numbers in those files. Other sections in the text report can tell us which functions call this one, and how often. The information is ideal for creating and inserting comments where we don’t have human input.

Using our automated comment insertion/replacement toolFor automatically documenting legacy code, we will need to develop a custom application capable of reading the text report output of Understand Analyst to get a source file name and line number as well as other information such as the most frequent callers of a function, formatting that with information from the source code file itself into the appropriate comment header format, and then injecting that comment header into the source code, replacing any existing comment header. The replace functions will have to happen from the bottom of a file up, so as not to render invalid the line numbers reported by Understand Analyst as functions and variables are processed. The application must also send information gathered while processing to a comment header database.

The automatic comment insertion/replacement application should be written in such a way that it’s comment insertion/replacement methods could also be used in a version of the application that synchronized source code comment headers with existing entries in the database (for sessions subsequent to the initial processing done the first version of the application).

The application should be written as single loop, processing the contents of a Understand Analysis report from beginning to end. The usage of the application should be as simple as:

Generate an Understand Analysis report; Pass the file path to the report and a base directory path for the source code to the application;

and Start comment header insertion/replacement processing.

New Code

ToolsFor new code, we will need to write a tool which can hover above the IDE or other development editor and accept mouse-clicks or combination keystrokes, which cause it to insert templated comment headers into source code at the current cursor position in the editor.

To do this, the tool must capture the previous window having focus anytime focus goes to the tool. It must also allow the programmer to persist and change comment header styles, and it must be able to generate comment header ID’s from the current computer name and the high-granularity system clock. It must generate the appropriate comment header text, set focus back to the original application that had focus, and then inject the comment header into the original application as individual keystrokes using the runtime kbhit() or similar API function calls. It must also be able to interact with the comment header database (by requesting synchronization of the database with the source code file). Finally, the tool must be able to register links to outside document references. The GUI for the tool might look something like this:

Weatherford ep-Solutions | Introduction 30

June 1, 2009 [Documenting ep-solutions proprietary source code]

Source code comment header assistant

We will also need a tool which can synchronize new or freshly-edited comments in source code with the source code comment database, replicating changes made in the source code to the database and vice-versa. This tool can be a variant of the automated comment insertion/replacement tool described for processing legacy code.

PracticesWhenever he/she is actively coding (whether new or old code) the source code comment header assistant application should be active – for this reason, all of these tools should be added to the Visual Studio external tools menu(s). Whenever the code needs to insert a comment header, they need only strike the appropriate keystroke combination, or change the comment type or style with the mouse and then click the insertion button or hit the magic keystroke combination.

When the coder is done for the day or with a specific task or project or ready to compile, they should use the database synchronization tool to pick up any new comment headers in the source code and register them to the database (or pick up changes rendered in the database for insertion into the source code).

Source code documentation databaseThe source code database could be any SQL database, or could be a database component of a document management system (DMS). The database will need to support two tables. The data recorded in each database entry of the first table should be pretty straightforward, and will consist of eleven columns:

1. A unique identifier that corresponds to the ID attribute of the comment header XML tag, and contains the encoded computer identifier and high-granularity timestamp;

2. The header comment type;3. The header comment style;

Weatherford ep-Solutions | Introduction 31

June 1, 2009 [Documenting ep-solutions proprietary source code]

4. The comment header text contents;5. The full path of the source code module file containing the comment;6. The relativity code for the full source code module path (Perforce repository, Mutt, etc.);7. The line number within the source code where the comment starts;8. 256 characters of source code found immediately before the comment (for context);9. 256 characters of source code found immediately after the comment (for context); 10. A flag indicating whether the sourced of the last update was from the database or from the

source code; and 11. A semi-colon-separated list of keywords extracted from the comment text suitable for matching

in searches.

The second table will be used to capture external links for source code comments – these links reference comments or data too large to be kept in the source code file, as well as additional text and non-text resources referenced in comments. This table will have the following columns:

1. Unique identifier, as a GUID.2. The full path of the file or Web address containing the linked information (can be empty if all of

the referenced information is text ans is in the free text field as item 4);3. The relativity code for the full source code module path (Perforce repository, Mutt, IP address,

contained-in-free-text, etc.);4. Free text describing the referenced object, or location of specific information within the

referenced object (i.e, page number, keyword, search text, etc.)5. Semi-colon-separated list of comment header unique IDs referencing this link (for determining

use counts on deletion, etc.).

ToolsAs described previously in the section on new code tools, we will need a tool which can synchronize new or freshly-edited comments in source code with the source code comment database, replicating changes made in the source code to the database and vice-versa. This tool can be a variant of the automated comment insertion/replacement tool described for processing legacy code.

PracticesThe database and source code synchronization tool should be automatically run against repository code on a regularly-scheduled basis (in addition to manual synchronization performed by the programmers).

Whenever a programmer has been assigned a new task or needs to search for existing or sample source code to use in his/her project, s/he should first search the comment header database before going externally to sites such as The Code Project or CodeGuru.com.

Weatherford ep-Solutions | Introduction 32

June 1, 2009 [Documenting ep-solutions proprietary source code]

epsDocTemplater Tool

The epsDocTemplater Tool is an add-on to the Visual Studio 2008 IDE, and includes a number of helper macros to document unmanaged C++ code in exactly the same way the IDE natively supports C# and managed C++ code – that is, with Intellisense support in the editor and standardized XML comment syntax.

The epsDocTemplater Tool also adds extension to the standard comment syntax, and provides a means to tie comments (and therefore the items the comments document) to a database visible outside the source code editor. The database will allow sophisticated search and analysis, and will allow editing comments independent of the source code (a synchronization tool will ensure both the database and the source code have the latest comments).

For every comment type supported in normal C#/managed C++ code in addition to the extension comment types supported only in unmanaged C++, a macro is provided by epsDocTemplater to automatically inject a pre-configured macro of that type into the source code editor at the current cursor position. Each of these macros comes in two forms – in one form, an empty macro is inserted into the code at the current cursor position. In the second form, epsDocTemplater attempts to analyzeany text it finds in the line at the current cursor position, and fills in the template with any appropriate information it can extract from the line, before injection.

In either form, the macro will inject the comment header just before the line where the cursor was located at the time the macro was activated. It will attempt to intelligently place the comment header based on either the text starting column (if text was present) or the cursor column position (if text was not present). For multiple line comment headers (as for functions) each line’s starting position will be blocked to match the starting position of the preceding line.

InstallationTo install the epsDocTemplater Tool, first download the solution to a local directory from the repository at ..\VS2005/IDE Tools/epsDocTemplater/. Change the properties for your local directory to make it and all subdirectory and subordinate items writable (the VS 2008 add-in tool requires writable configuration files).

Rebuild the solution in its entirety (there are two project within the solution, as well as a macros file in a separate folder).

Weatherford ep-Solutions | Introduction 33

June 1, 2009 [Documenting ep-solutions proprietary source code]

Now double-click [Your_Local_Directory]\epsDocTemplater\epsDocTemplaterSetup\Release\epsDocTemplaterSetup.msi :

Click “Next”:

Weatherford ep-Solutions | Introduction 34

June 1, 2009 [Documenting ep-solutions proprietary source code]

Enter “C:\Program Files\epsDocTemplaterSetup\” as your installation path (or other path of your choosing – this documentation will assume you entered “C:\Program Files\epsDocTemplaterSetup”\) and click “Next”:

Weatherford ep-Solutions | Introduction 35

June 1, 2009 [Documenting ep-solutions proprietary source code]

Click “Next”:

Weatherford ep-Solutions | Introduction 36

June 1, 2009 [Documenting ep-solutions proprietary source code]

Weatherford ep-Solutions | Introduction 37

June 1, 2009 [Documenting ep-solutions proprietary source code]

Click “Close”.

Create this complete directory path on your C: drive if it does not already exist: C:\Documents and Settings\All Users\Application Data\Microsoft\MSEnvShared\Addins\ .

Copy the file at [Your_Local_Directory\epsDocTemplater\InstallFiles\epsDocTemplater.Addin to the directory C:\Documents and Settings\All Users\Application Data\Microsoft\MSEnvShared\Addins\ .

Also copy the file at C:\Program Files\epsDocTemplaterSetup\ epsDocTemplater.dll to to the directory C:\Documents and Settings\All Users\Application Data\Microsoft\MSEnvShared\Addins\ .

Completely close Visual Studio 2008 if it is open. Now re-launch Visual Studio 2008.

Click the “Tools | Add-in Manager…” menu item:

Weatherford ep-Solutions | Introduction 38

June 1, 2009 [Documenting ep-solutions proprietary source code]

Make sure the two check-boxes for epsDocTemplater are checked ON. Click “OK”.

Create the directory C:\Documents and Settings\[Your_User_Name]\ My Documents\Visual Studio 2008\Projects\VSMacros80\MyMacros\epsDocTemplater\ .

Copy the file at [Your_Local_Directory\epsDocTemplater\InstallFiles\ epsDocTemplater.vsmacros to the directory C:\Documents and Settings\[Your_User_Name]\ My Documents\Visual Studio 2008\Projects\VSMacros80\MyMacros\epsDocTemplater\ .

Weatherford ep-Solutions | Introduction 39

June 1, 2009 [Documenting ep-solutions proprietary source code]

Click on “Tools | Macros | Load Macro Project…” in VS 2008:

Select the epsDocTemplater macro set, click “Add”, and then click “OK”:

Weatherford ep-Solutions | Introduction 40

June 1, 2009 [Documenting ep-solutions proprietary source code]

Now click the “Tools | Options…” menu item in VS 2008:

Weatherford ep-Solutions | Introduction 41

June 1, 2009 [Documenting ep-solutions proprietary source code]

From the tree on the left, select “Keyboard”. In the edit box entitled “Show commands containing:” type “epsDocTemplater”.

Weatherford ep-Solutions | Introduction 42

June 1, 2009 [Documenting ep-solutions proprietary source code]

Now a long list of available macros will appear, one for each type of comment epsDocTemplater supports. The name at the far right of the macro name string helps determine which comment type the macro represents. You will want to use the “Press shortcut keys:” edit box to assign keystrokes to the comment styles you want to use in the VS 2008 editor. Here is a list of the comment styles by macro name:

1. CSC_CodeSLCopyPrefix ///<c> Code (single-line sample), copies info already there, including comments </c>

2. CSN_CodeSLNoCopyPrefix ///<c> Code (single-line sample), no copying </c>3. CMC_CodeMLCopyPrefix ///<code> Code (multi-line sample), copies info

already there, including comments </code>4. CMN_CodeMLNoCopyPrefix ///<code> Code (multi-line sample), no copying

</code>5. EEC_ExampleCopyPrefix ///<example> Example, copies info already there,

including comments </example>6. EEN_ExampleNoCopyPrefix ///<example> Example, no copying </example>7. EXC_ExceptionCopyPrefix ///<exception> Exception, copies info already

there, including comments </exception>8. EXN_ExceptionNoCopyPrefix ///<exception> Exception, no copying

</exception>9. INC_IncludeCopyPrefix ///<include> Include, copies info already there,

including comments </include>10. INN_IncludeNoCopyPrefix ///<include> Include, no copying

</include>11. LSC_ListCopyPrefix ///<list> List, copies info already there,

including comments </list>12. LSN_ListNoCopyPrefix ///<list> List, no copying </list>13. PAC_ParaCopyPrefix ///<para> Paragraph, copies info already there,

including comments </para>14. PAN_ParaNoCopyPrefix ///<para> Paragraph, no copying </para>15. PMC_ParamCopyPrefix ///<param> Parameter, copies info already

there, including comments </param>16. PMN_ParamNoCopyPrefix ///<param> Parameter, no copying </param>17. PRC_ParamRefCopyPrefix ///<paramref> Parameter reference, copies

info already there, including comments </paramref>18. PRN_ParamRefNoCopyPrefix ///<paramref> Parameter reference, no

copying </paramref>19. PNC_PermissionCopyPrefix ///<permission> Permission, copies info

already there, including comments </permission>20. PNN_PermissionNoCopyPrefix ///<permission> Permission, no copying

</permission>21. RMC_RemarksCopyPrefix ///<remarks> Remarks, copies info already

there, including comments </remarks>22. RMN_RemarksNoCopyPrefix ///<remarks> Remarks, no copying

</remarks>23. RTC_ReturnsCopyPrefix ///<returns> Returns, copies info already

there, including comments </returns>24. RTN_ReturnsNoCopyPrefix ///<returns> Returns, no copying

</returns>25. SEC_SeeCopyPrefix ///<see> See, copies info already there,

including comments </see>26. SEN_SeeNoCopyPrefix ///<see> See, no copying </see>27. SAC_SeeAlsoCopyPrefix ///<seealso> See, copies info already there,

including comments </seealso>28. SAN_SeeAlsoNoCopyPrefix ///<seealso> See, no copying </seealso>

Weatherford ep-Solutions | Introduction 43

June 1, 2009 [Documenting ep-solutions proprietary source code]

29. SUC_SummaryCopyPrefix ///<summary> Summary, copies info already there, including comments </summary>

30. SUN_SummaryNoCopyPrefix ///<summary> Summary, no copying </summary>

31. TPC_TypeParamCopyPrefix ///<typeparam> Typeparam, copies info already there, including comments </typeparam>

32. TPN_TypeParamNoCopyPrefix ///<typeparam> Typeparam, no copying </typeparam>

33. VLC_ValueCopyPrefix ///<value> Value, copies info already there, including comments </value>

34. VLN_ValueNoCopyPrefix ///<value> Value, no copying </value>35. CLC_ClassCopyPrefix ///<class> Class, copies info already there,

including comments </class>36. CLN_ClassNoCopyPrefix ///<class> Class, no copying </method>37. CDC_CommentDBCopyPrefix ///<commentdb> Large text or binary object

stored in the comments database, copies info already there, including comments </commentdb>

38. CDN_CommentDBNoCopyPrefix ///<commentdb> Large text or binary object stored in the comments database, no copying </commentdb>

39. DNC_DefineCopyPrefix ///<define> #define, copies info already there, including comments </define>

40. DNN_DefineNoCopyPrefix ///<define> #define, no copying </define>41. EMC_EnumCopyPrefix ///<enum> Enumeration, copies info already

there, including comments </enum>42. EMN_EnumNoCopyPrefix ///<enum> Enumeration, no copying </enum>43. FNC_FuncCopyPrefix ///<function> Function, copies info already

there, including comments </function>44. FNN_FuncNoCopyPrefix ///<function> Function, no copying

</function>45. MAC_MacroCopyPrefix ///<macro> Macro (#define), copies info

already there, including comments </macro>46. MAN_MacroNoCopyPrefix ///<macro> Macro (#define), no copying

</macro>47. MDC_MethodCopyPrefix ///<method> Method, copies info already

there, including comments </method>48. MDN_MethodNoCopyPrefix ///<method> Method, no copying </method>49. STC_StructCopyPrefix ///<struct> Structure, copies info already

there, including comments </struct>50. STN_StructNoCopyPrefix ///<struct> Structure, no copying </struct>51. TFC_TypedefCopyPrefix ///<typedef> typedef, copies info already

there, including comments </typedef>52. TFN_TypedefNoCopyPrefix ///<typedef> typedef, no copying

</typedef>53. UNC_UnionCopyPrefix ///<union> Union, copies info already there,

including comments </union>54. UNN_UnionNoCopyPrefix ///<union> Union, no copying </union>

After you have installed the add-in and macros, you should be able to add comments to your source code easily using the assigned keystroke combinations.

Weatherford ep-Solutions | Introduction 44

June 1, 2009 [Documenting ep-solutions proprietary source code]

Compiling documentation for unmanaged C++ codeAll unmanaged C++ projects must have their /doc compiler flag set and have been compilied once to see the proper Intellisense behavior. To set the /doc compiler flag, go the unmanaged C++ project’s properties:

Click on the “Configuration | C/C++ | Output Files” item in the left-hand tree. In the “Generate XML Documentation Files” item on the right pane, set the combo box to “Yes (/doc)”, click “Apply” and click “OK” (do this for both debug and release build options, as well as any other build options you have set up).

Weatherford ep-Solutions | Introduction 45

June 1, 2009 [Documenting ep-solutions proprietary source code]

ExamplesHere is the editor just before we pressed the “summary” macro keystrokes set:

Weatherford ep-Solutions | Introduction 46

June 1, 2009 [Documenting ep-solutions proprietary source code]

And this is the inserted comment header:

Weatherford ep-Solutions | Introduction 47

June 1, 2009 [Documenting ep-solutions proprietary source code]

A depiction of the changes that were made by the macro:

Weatherford ep-Solutions | Introduction 48

June 1, 2009 [Documenting ep-solutions proprietary source code]

Here we’ve placed the cursor several columns to the right on an empty line:

And here is the result:

Weatherford ep-Solutions | Introduction 49

June 1, 2009 [Documenting ep-solutions proprietary source code]

Limitations and assumptionsThis solution works well, but is not perfect. Limitations of time and resources, as well as the law of diminishing returns, have resulted in an implementation that will cover most situations but may not produce expected results in certain specific situations. These are the assumptions and rules of engagement built into the current code:

1. When commenting existing code functions or methods, the expectation is that the cursor will be on the same line as the function name and return parts of the function declaration, and that the function name and the return will both be on the same line. However, the cursor can be positioned anywhere within that line, and parameter declarations for the function can either be on that line or on subsequent lines;

2. It is presumed that the first word to the left of the first opening parenthesis found is the function name;

3. It is presumed that all words to the left of the function name represent the return type (which may include import/export declarations and other qualifiers) – the return type is reported in a “<returns>” tag – the “type=” attribute for the “<returns>” tag is created from all of the words found in the function declaration line that were to the left of the function name;

4. It is assumed that parameter declarations will be comma-separated from one another, and each have the form:

[Optional volatility or other modifier]<Required variable type> (whitespace – required if variable name provided) [Optional variable name][Optional default value]<Required comma or closing parenthesis>

a. The parameter variable type is required;b. When optional volatility or other modifiers are declared to the left of the required

variable type, the modifiers will be included in the “type=” attribute of the “<param>” tag;

c. The optional variable name, if provided, will be reported in the “name=” attribute of the “<param>” tag;

d. If provided, the optional default value must be provided in the form “/* = SomeVal */”, where whitespace between the equal sign and the text is optional – the entire contents (less beginning and trailing whitespace) of the text between the “=” and the end of the comment will be reported in the “defval=” attribute of the “<param>” tag;

e. Parameter components are evaluated from right to left, which can cause occasional misreads :

i. If, for example, the legacy code declares a volatility modifier (i.e., “const”) and a parameter type (i.e., “int”) but does not declare a parameter name, the “int” will be misreported as the parameter name and the “const” will be misreported as the parameter type;

ii. Whenever a single word appears alone as a parameter declaration, that word will be presumed to be the parameter type;

Weatherford ep-Solutions | Introduction 50

June 1, 2009 [Documenting ep-solutions proprietary source code]

iii. Once the variable name (if provided) is determined (which is always the rightmost word of the parameter declaration unless an equal sign representing a default value is present), everything to the left of that variable name is presumed to be the parameter type;

iv. Other than the default value, any comments within the parameter declaration are ignored in the “<param>” tag; and

v. A maximum of 24 parameters will be documented.5. Existing comments in the line(s) immediately above the current cursor position within the

function declaration line when the macro is activated will be copied into “<remarks>” tags in the generated function header if they meet the following conditions (note that whitespace at the beginning and end of each line is discarded before the rule is enforced):

1. They must contain a “//” at the beginning of the line or a “*/” at the end of the first line immediately above the function declaration;

2. Each line above that line will also be copied, so long as the first two characters of the line are “//”, or a “*/” characters set was found in the first line and a “/* set has not yet been found;

3. No part of the comment can start anywhere other than at the beginning of the line, and when “*/” comment end sequence is found, it must appear at the very end of the line;

4. If a “^~^” character sequence is found anywhere in a comment, the comment is not copied (the “^~^” character sequence is an indicator for one of the comments already processed by this utility); and

5. When a comment is copied into a “<remarks>” tag, the comment is deleted from the source code, but the lines below it are NOT moved up to replace them – this is because the original cursor position when the macro was fired must be preserved to avoid asserts in the text editor.

Please report any bugs or desired behavior changes to me or to Kris.

Weatherford ep-Solutions | Introduction 51