Tuesday, May 27, 2008

Work Item Customization tidbits (part 1 of X)

One of the typical TFS administration task is Work Item Template customization. Chances are, even if you never did it sooner or later you will.

However, while work item customization is often represented as very simple activity there is a host of things not to do and also quite a few useful tidbits of information helping to make customizations easier. Over the (three) years that I am working with TFS I have my little arsenal of tricks and I was meaning to make it public for a while. It does not mean to replace the guidance on MSDN but rather to provide less formal description of the things that matter in my opinion. The intended audience is not a seasoned TFS administrator that knows intimately the syntax and what can/cannot be done with it but rather a person who starts designing templates from scratch or contemplating changes to existing ones.

If you want to use work items, there are a few choices

  • Postpone work items implementation until source control is stable
  • Use work item types distributed with TFS (MSF/CMMI templates) or partner templates (Conchango)
  • Use work item types distributed with TFS as a baseline with minor changes (additional data fields)
  • Create a new work item type or perform major customization on stock work item types

First case does not present any difficulties; the second case also does not present any customization challenges (and is probably atypical since most organizations will have differences with predefined work item definitions).

For the last two scenarios the work item type templates will have to be customized. And that's where questions start – what is the optimal customization strategy?

In order to customize work item types templates efficiently, first prerequisite is to understand their structure. Since TFS is installed with two predefined project templates, it is logical to select one of the work item type templates that are part of those project templates as an example. Let's use MSF Agile Bug WI type, which is pretty simple and yet contains most important concepts.

Some basics to start with – every work item type is defined as XML of special format. This XML is part of the project template (how to download project template). For convenience, the XML that defines Bug work item type can be downloaded here.

The exact schema may be viewed here; I will attempt to try and deal with definitions in less structured way while still supplying links to relevant MSDN contents.

Conceptually, from the term work item one may reach the conclusion that it must have at least two logical parts:

  • Data fields describing the work to be performed
  • Status fields describing current status of work being performed

And indeed, simplest work item type template contains three sections (three since we also need to define user interface for WI): FIELDS section that defines data fields relevant for specific type; WORKFLOW section defining states and available transitions between them and FORM section, defining the UI representation of data fields.

Let's look in depth on each of those sections.

First, let's have a look at simple excerpt from Bug WI template FIELDS section:

<FIELD name="Issue" refname="Microsoft.VSTS.Common.Issue"
type="String">

<HELPTEXT>Used to highlight the bug.</HELPTEXT>
<REQUIRED/>
<ALLOWEDVALUES>
<LISTITEM value="Yes" />
<LISTITEM value="No" /> 
</ALLOWEDVALUES> 
<DEFAULT from="value" value="No" />
</FIELD>

In FIELDS section, every FIELD element at the very least needs to specify human readable name and reference name refname together with element type. Both name and refname are unique across Team Foundation server, however, refname is used internally both in code and database and thus cannot be renamed once created. On the other hand, name is exposed to the user and may be renamed if needed.

Another useful bit of information on reference name – in Bug work item template definition one can see that some fields start with System
prefix while others start with Microsoft.VSTS. The naming convention is very useful – the System fields are core fields that represent functionality common to all work item (regardless of the type) and should be present in every work item whereas other fields may be specific to work item type.

In addition to providing name and type, FIELD element may be contain additional elements used to define

  • Field tooltip contents (HELPTEXT element)
  • Field rules that define runtime behavior and constraints
  • Field behavior in regards to data warehouse and reports

Most important of those additional elements are ones that define runtime behavior. Some of the rules available:

  • Mandatory field (REQUIRED element)
  • Read-only field (READONLY element)
  • Field that is "frozen" – that is cannot be modified once it is set to some value (FROZEN)
  • Field that cannot be cleared once set and saved (CANNOTLOSEVALUE)
  • Field that must have different value from other field (NOTSAMEAS)
  • Field value must match regular expression pattern(s) (MATCH)

In addition to the rules that specify certain constraint on the element, there are rules that define action to be executed on field

  • Set default value for the field – that is value that will be set when new WI is created (DEFAULT)
  • Set default value for the field on save on server (useful for such fields as date or originator of change) (SERVERDEFAULT)
  • Copy value from the other field (COPY)

And finally, there are rules that define how multiple values may be specified or stored for the field:

  • Allow the field to accept only valid user name (VALIDUSERS)
  • Allow the field take only values from the list (ALLOWEDVALUES)
  • Provide list of suggested values for the field [how it is provided is UI-specific] (SUGGESTEDVALUES)
  • Prohibit field from accepting values in the list (PROHIBITEDVALUES)

With that minimal knowledge, it will be easy to understand the example FIELD definition above – it defines mandatory field "Issue" that may accept only values "Yes" or "No"; by default "No" is set (from attribute in DEFAULT specifies whether to take default from scalar value [value] or from another field value [field]).

However, the basic syntax does not provide much flexibility. For example, with that syntax one cannot make field conditionally read-only (say, only for certain users). Also, it is not hard to imagine that certain fields will have to provide certain behavior based on the values of other fields.

And indeed, those scenarios (and many more) can be handled with the help of additional syntax elements. I shall cover those in the next installment.

No comments: