Saturday, July 05, 2008

Work Item Customization tidbits: global lists (part 6 of X)

In previous installments on work item customization, I talked more about general syntax of custom work item types and less about how this syntax is applied. Today I’d like to talk about WI syntax that can be used to minimize complexity in maintaining custom work item types.

One way to simplify the maintenance across different work item types is to have some definitions global to Team Foundation server. TFS WIT provides such mechanism aptly called global lists. Global list is exactly what its name says - list of values global to Team Foundation server; by global I mean that it can be used by any work item types on the server.

Let’s digress for a moment into details of list definitions in work item templates. To define the list box in work item (some call it combo box), one needs to do the following:

  • Define field with one ALLOWEDVALUES/SUGGESTEDVALUES multiple values specifier
  • Associate the field defined with FieldControl in UI

Now if we define list field, how it can be modified to use a global list? Let’s start with Priority field as defined in MSF bug work item template:

<FIELD name="Priority" 
      refname="Microsoft.VSTS.Common.Priority" 
      type="Integer" reportable="dimension">
  <ALLOWEDVALUES>
    <LISTITEM value="1"/>
    <LISTITEM value="2"/>
    <LISTITEM value="3"/>
  </ALLOWEDVALUES>
</FIELD>

Leaving aside specifics of global list definitions, assume for a moment that we have global list called “Priorities” containing values 1, 2, 3 defined; then Priority field can be defined as following:

<FIELD name="Priority" 
      refname="Microsoft.VSTS.Common.Priority" 
      type="Integer" reportable="dimension">
  <ALLOWEDVALUES>
    <GLOBALLIST name="Priorities"/>
  </ALLOWEDVALUES>
</FIELD>

Now if priorities list needs to be changed across all work item definitions, it is sufficient to change one global list. The scenario is also flexible enough to allow modifying single template without affecting the rest; the following definition uses combination of global list and values specific to current template:

<FIELD name="Priority" 
      refname="Microsoft.VSTS.Common.Priority" 
      type="Integer" reportable="dimension">
  <ALLOWEDVALUES>
    <GLOBALLIST name="Priorities"/>
    <LISTITEM value="Undefined"/>
  </ALLOWEDVALUES>
</FIELD>

The global list may be defined in two ways – either as part of work item template or separately using glexport/glimport command line utilities (in the latter case, global list is represented as xml file). Several caveats to be aware of when defining and using global lists:

  • Global list values cannot be modified (only replacement of the whole list is supported); when you include global list definition in WI template or use glimport, if the list exists the whole list will get replaced. For that reason, I do not recommend placing global list definitions into WI template but rather to create global list prior to using it in any templates (make sure you modify templates that you get through witexport; witexport will always include related global lists in work item definition)
  • Global list cannot be deleted (there exists a workaround - if you are using VS2008, Power Tool destroygl can be used for the purpose)

One additional important scenario that global lists help in solving is bringing external data over to TFS Work Item Tracking system. Suppose that you need to have list of project codes from external system (f.e. payroll) available in TFS work item; and the catch is that the list is updated in external system every now and then. The first step is obvious – define the project codes list as a global list, and make sure all work item templates use it. The second step is to make sure the global list gets updated when new projects are added in external system. Simplest solution to this would be to import list of project codes into XML file from external system and schedule glimport to run overnight. Or for more complex situations, one could use TFS extensibility API (most notably ImportGlobalLists method of WorkItemStore) to write custom updater.

To conclude, while using global list may require some extra thought in designing custom work item types, the benefits you’ll reap in maintenance are huge.

Related posts:
- Work Item Customization: system fields (part 5)
- Work Item Customization: user interface (part 4)
- Work Item Customization: state transitions (part 3)
- Work Item Customization: conditional field behavior (part 2)
- Work Item Customization: fields definition (part 1)

No comments: