Getting Started with DXL

The DOORS eXtension Language

by Ian Alexander

www.scenarioplus.org.uk

In earlier articles (Get More from DOORS with DXL Graphics, Get More from DOORS with DXL Links), I introduced some of the special features of The DOORS eXtension Language (DXL), and illustrated how to create custom graphics and links from a module in the database. But these were quite advanced features, and several DOORS users have asked me if I could help them to get started with the language.

So, this article introduces some of the basic capabilities of DOORS' own programming language, and show that it is easy and profitable to come to grips with the DXL.

Introducing DXL

The DOORS user interface makes it possible for you to carry out most day-to-day requirements operations without any extra tools. You can, for example, filter on a user-defined Attribute named 'Object Type' to view only those Objects that are marked as requirements, and look at the Results display to see how many requirements you have.

However, you'd need to open the filter tool each time to do this, and either respecify the filter or reload a view that contains that filter. If counting the requirements is something you want to do often, then it might be worth writing a small DXL program to do the job. It can be accessed directly from the main menu bar – you can put it in the User menu or create your own (without further programming).

The program's specification is simply to go through all the Objects in the current Module and count them if they are requirements. Let us assume that an Object Attribute called 'Object Type' is declared in the Module, and that this is based on an Enumeration Type which provides allowed values {Heading, Requirement, Comment}.

Just about the simplest program we can write to do this is the following – I shall explain what it does in a moment:

Module m = current

Object o = null

string oot = ""

int reqtCount = 0

for o in m do {

oot = o."Object Type"

if oot == "Requirement" then reqtCount ++

}

infoBox "There are " reqtCount " requirements in this Module"

This tiny program first declares a variable m to be of type Module, which as you have guessed means a DOORS Module, and sets it to be the current one. DXL contains several such access types specially for DOORS – type names like Object, Link, Filter, Column, and Attribute should sound very familiar. Apart from that, most of the syntax of DXL is just like C's, but with some friendly simplifications. For instance, there are no semicolons (;) in the program – DXL doesn't need them if you put each command on a line by itself.

There are three more declarations: of a variable o of type Object, a string oot which will hold the value of the Object Type so we can check what it is, and an integer reqtCount which will record how many requirements we have found.

The core of the program is the for..in..do {..} construct. This is a special kind of loop in DXL, with the meaning 'for all the whatever-they-are's in this-data-structure, do the following'. This meaning is nice, as it corresponds closely to how you might specify a search or other logical operation on your requirements. DXL's for..in..do.. is a clean and elegant construct.

What the loop does is to take the first Object it comes to, and retrieve the value of its 'Object Type' Attribute. The retrieval is specified by the '.' operator after the Object variable o. Read it out aloud as 'oh-dot-Object Type'. You can perhaps hear that this is a compact way of indicating an Attribute of an Object.

The next command in the loop tests to see if the retrieved value, a string, is exactly equal to the string 'Requirement'. If it is, the integer counter reqtCount is incremented (i.e. one is added to its current value).

The next line contains just a closing curly bracket, indicating the end of the for loop. It tells the DXL run-time system to go back and process all the rest of the Objects in the Module, or rather, all of those that are on display. The loop actually ignores Objects that are concealed by filtering, outlining, or by being at a level below the limit set by the user in the box that normally displays 'All levels'. This is very useful as it allows you to combine filtering with searching, but it can also lead to wrong programs if you don't think out what you want.

Finally, the last line of the program displays an information box, like this:

As you can see, it is quite normal for a few lines of DXL to require a page of explanation. This is because programs are made up only of instructions (and comments to help people understand and maintain the code) – there should be nothing in a program that is not needed for some purpose.

Some Refinements …

Error Handling

The little program above works – but only if it is used from a Formal Module that happens to contain the 'Object Type' Attribute, and only if the user has not turned on filtering, outlining, or levels. In other words, it is more like a sketch of the functional requirement than a complete implementation. So, we need a few pre-flight checks to make sure the program won't immediately crash when used out of context.

///////////////////////////// pre-flight checks /////////////////////////

if type m != "Formal" then

error "Module is not Formal"

if !exists attribute AobjectType then

error "Attribute '" AobjectType "' not found"

filtering off

level 0

The command 'error' is the name of a built-in DXL function. It does pretty much what you might expect – it displays the message that you provide to it, and it stops the program right there. This is still a little unfriendly, but at least you get to choose the message. If you prefer, you can use an ack box and then give the halt command yourself:

ack "...error message here..."

halt

Sometimes you may be able to avoid halting, but you have to be careful if you mean to proceed in the presence of a known error.

Maintainable Constants

Another thing that is untidy in the little program is the way that string constants (in double quotation marks) are sprinkled everywhere, including in the main body of the program. In a small example like this, it hardly matters, but in a larger program it becomes difficult to find all the places where a constant is referred to. If the design of the database changes, for instance if the name of the 'Object Type' Attribute had to be updated, maintenance would be trickier than it ought to be.

The cure is to collect up all the 'fixed' parts of the program at the beginning – in a large program, this may be a separate file to be included by the run-time system – and to refer to them as named constants (or variables) rather than as actual values:

/////////////////////////// constant declarations ///////////////////////

const string AobjectType = "Object Type" // enumeration attribute ...

const string Chead = "Heading" // ... and its values ...

const string Creqt = "Requirement"

const string Ccomm = "Comment"  

More Detailed Results

As a finishing touch, let us display a little more detail about the module, like this:

The last line of the program needs to be modified to include the extra information:

infoBox "There are " reqtCount " " Creqt "s\n" //-

"out of " oCount " Objects in Module '" mName "'\n"

This makes use of two new variables, oCount which counts the total number of Objects (whatever their Object Type), and mName which records the name of the Module:

int oCount = 0

string mName = m."Name"

for o in m do {

   oCount ++ // unconditionally

   oot = o.AobjectType

   if oot == Creqt then reqtCount ++

}  

Comments

It is important to comment your programs so that other programmers (and probably you yourself, a few months down the line) can understand your intentions. DXL encourages you to put in comments with the incentive that if you provide a

// one-line comment like this at the top of your program, saying what it is,

/* followed by a multi-line comment like this,

which you can use to explain what the program does,

and include your copyright notice and the program's history

*/

then DOORS will automatically build your DXL program into the program library and make it appear on the menu bar, as long as it is in a properly-constructed DXL directory such as 'User'. You'll find it in DOORSHOME/lib/dxl/addins/ where DOORSHOME is wherever your system administrator has placed DOORS on your system.

The Complete Program

Here's how the whole program looks, now that we have polished it up and protected it a little. The process of sketching out a program and then making it meet all its requirements – not just for the main task it has to perform (that's usually easy) but for reliability and readability and perhaps other qualities – is important. Even small systems do not instantly work perfectly in all circumstances. This article has tried to illustrate the sketching and polishing process. The program below is more complex – perhaps in some ways better than the initial sketch – but I think you'll probably do best by starting off thinking of the sketch.

For a small program, it is efficient just to write and test the code to get it working in normal situations, and then to add features like pre-flight checks to help it behave properly if the context is wrong. For larger programs, the job of sketching out and subsequent refinement is best done by writing a specification as well as designing the code – but since you are a DOORS user, you know that already.

// reqtCount.dxl --- counts number of objects of Object Type "Requirement"

/*

Example for 'Getting Started with DXL'

DXL for DOORS 5

Ian Alexander

3 Sept 2001

*/

/////////////////////////// constant declarations ///////////////////////

const string AobjectType = "Object Type" // enumeration attribute ...

const string Chead = "Heading" // ... and its values ...

const string Creqt = "Requirement"

const string Ccomm = "Comment"

////////////////////////// variable declarations /////////////////////////

Module m = current

Object o = null

string mName = m."Name"

string oot = ""

int reqtCount = 0

int oCount = 0

///////////////////////////// pre-flight checks /////////////////////////

if type m != "Formal" then

error "Module is not Formal"

if !exists attribute AobjectType then

error "Attribute '" AobjectType "' not found"

filtering off

level 0

/////////////////////////////// main program ////////////////////////////

for o in m do {

   oCount ++

   oot = o.AobjectType

   if oot == Creqt then reqtCount ++

}

infoBox "There are " reqtCount " " Creqt "s\n" //-

"out of " oCount " Objects in Module '" mName "'\n"

/////////////////////////// end of reqtCount.dxl ///////////////////////

Summary

DXL provides powerful and effective ways of extending the built-in behaviours of DOORS. It does this by combining a general-purpose programming language with direct access to the data structures of DOORS itself. Many of the features are simple to use and do not demand advanced programming skills. You can often enhance DOORS projects with useful tools, just by writing a few lines of DXL.

© Ian Alexander, September 2001

Ian Alexander's Home Page