Microsoft Dynamics Ax developer's blog

Thursday, March 16, 2006

The magic semicolon

Example


This X++ code compiles well, but have Two potential errors:

static void test(Args _args)
{
int axcoder, axcoder1;
axcoder=1;
axcoder1=2;
}

This code is fragile. Try now to add the new type called 'axcoder'. Introduce a new class with the name 'axcoder', for example.

You will get a syntax error.

The problem is that designers of X++ decide to:

  • allow variables and type with similar name (so it is not possible treate a type as a variable of the special type, lead to tableNum, classNum and other ...Num literals in X++, blocks to declare variables in any place of code and so on)

  • do not lookahead deep enough to resolve this collision - so you and me we both able to decide that axcoder is not a class name here, but X++ parser does not (i am not sure its an easy task, but i think it is possible)


There is a common workaround for this situation: add an extra semicolon after the end of declarations like this:

static void test(Args _args)
{
int axcoder, axcoder1;
;
axcoder=1;
axcoder1=2;
}

Now the code compiles well. But this is not the end.

Try to introduce a new class with the name 'axcoder1'.

Oops! One more syntax error.

The cause is the same.

Now let's split multivariable declaration to two;

static void test(Args _args)
{
int axcoder;
int axcoder1;
;
axcoder=1;
axcoder1=2;
}


This compiles well.

Conclusion


X++ developers didn't copy java accurate enough. The decide to reinvent the wheel so X++ is sometimes ugly. It allows you to compile code which become brocen if anybody introduce the class with a special name. I have seen examples of such fragile code even in sys layer code (see \Classes\SysLookup\lookupTableFieldRelation for example).

There are simple rules to avoid such errors:

  • don't use multivariable declarations

  • insert extra semicolon after declarations end (but you can ommit it if the first non-declaration is a keyword for example return)

  • dont use simple name for classes ('i', for example) which can be name of the variable in existing code


Note on style


I prefer to keep extra semicolon as the first character of line so it help to delimit internal fuction from the main function body:

void test()
{
void subFunction1()
{
// body of subFunction1
}
void subFunction2()
{
// body of subFunction1
}
;
// body of the main function
}

Saturday, March 04, 2006

Sidax 0.3.4 - user mode sidax

Changes in this version:

  • Its now safe to run sidax by end users -- checks for access to menuitems added; check for development rights at start removed

  • now you can setup project window titles and timings by editing the 'class declaration' section of sidax

  • window tab reflect window title changes

  • sidax now uses default menu of the user instead the main menu

Ideas: AxPath protocol

Imagine that you have an ability to create links to everything in axapta: forms, records, classes, busines objects (for example orders). You can insert that link in the web page or e-mail and your correspondent can click on this link and open the item you linked to from browser or email client. For example you open Purchase order 'P0002', click the 'copy link' button and send a letter with words "look at order P0002" and sombody who have received this message can simply click on the link to open this order.

This document describe proposal to introduce that kind of links read more..

COM in Axapta

Just published article in the Axaptapedia in answer to post in microsoft.public.axapta.programming

Wednesday, March 01, 2006

How to make Sidax autostart.

If you do this, Sidax will start, when you login Axapta.

Open class Info and modify the startupPost method. Replace yourUserID with the name you log in to Axapta.

/*
No SYS code must exist in this method
*/
void startupPost()
{
;
// ======== Sidax start: =============
// check for user ID and ask for confirmation
if(curUserId()=='yourUserID' && Box::yesNo('Run sidax?', DialogButton::Yes)==DialogButton::Yes)
{
// actually run sidax
TreeNode::findNode('\\Forms\\Sidax').AOTrun();
}
// ========== end of Sidax start =============
}


Note: If you want to skip question, just remove:

Box::yesNo('Run sidax?', DialogButton::Yes)==DialogButton::Yes)