The ready-set-go call has just resonated through the hallways at Microsoft, and we are now officially working on the next release of AX. What will the next release of AX look like? What features will it contain? What architectural changes will we make? What tools should we support? These are some of the many questions we will be working on during the upcoming months while we are defining the scope for the next release. I work in the Developer and Partner Tools team. This means I get to influence decisions like: "Should MorphX move into Visual Studio?", "How many layers should AX 6.0 have?", "Should X++ support eventing?", "Do we need an Entity concept in the AOT?", "How do we make our unit test cases available to partners?" - just to name a few. These are the questions that can get me out of bed in the morning - for a lot of good reasons, but primarily because I know my job makes a big difference to a lot of people.
If you want to join me shaping the future of AX at Microsoft Development Center Copenhagen, please visit:http://www.microsoft.com/danmark/om/mdcc/default.mspx
The most visual idiosyncrasy in X++ is the dangling semicolon separating the variable declarations from the actual code. But why is it there and why is it needed?
Best practices in X++ (as in most other modern languages) suggest using TitleCase when declaring (and referring to) types, and using camelCase when declaring variable types. Here is an example of what an X++ developer could write:
As X++ (unlike most other modern languages) is case insensitive, this is what the compiler will see:
Suppose the dangling semicolon wasn't there. Then the "accountnum" statement in the second line is ambigious. It could either refer to the type or to the variable. The X++ compiler assumes it is the type, and thus generates a compilation error when encountering the equal (=) sign; as you cannot assign into a type. By inserting the dangling semicolon you instruct the compiler that there will be no more variable declarations; and thus "accoutnum" is a reference to the variable and not the type.
If it was made a priority to get rid of dangling semicolons, what could be done?
The above is a draft of a blog post I wrote last week. I wrote it for two reasons: Mainly to explain the dangling semicolon issue, and secondarily to lay out bait for a developer on the X++ team. As it turned out more progress was made this weekend than the past eleven years in this corner of AX . After writing the draft above I decided to take a look under the covers in the compiler; to gauge the challenge, I guess. So I installed the latest version of VS and downloaded the latest source code for the kernel. (These are some of the freedoms you enjoy when working for Microsoft). After playing around with the grammar for a while, I came to the conclusion that the grammar is crisp and clear; the scanner is just feeding the wrong tokens to the parser. I found the spot where non-keyword tokens are evaluated. I discovered that if a token shares name with an X++ type (Class, Table, EDT, etc.) the parser assumes it is a type-token. After finding this spot it took me less than two hours to write some code that reads one token ahead and only assumes the current token is a type-token when it is followed by another non-keyword token. Sunday afternoon I had build 585 (the Release Candidate (RC0) of AX 2009) with a twist on my box: The dangling semicolon is no longer a requirement. I enjoyed the rest of the day in the sun with my family.
This morning I have created a package with my findings and sent it to the X++ team for evaluation. This change will not make it into AX 2009; but I'm confident those of us writing X++ code at Microsoft will enjoy this very soon. The rest of you will have to wait for AX6.0.
A new feature in Dynamics AX 2009 enables developers to write developer documentation directly in the X++ Editor while writing the production code. The feature is very similar to the XML documentation feature in C#.
Basically any method can contain /// (triple-slash) comments followed by structured documentation in XML format. Here is an example:
The developer is assisted by a dynamic documentation template, which is inserted through an editor script. The template automatically builds a skeleton including all the required tags for the current method. On top of this the written documentation is validated by best practice rules; which effectively prevent the documentation from growing stale. Finally a tool enables extraction of the documentation, so it can be processed outside AX, e.g. for publishing on MSDN.
Dynamics AX 2009 contains about 125.000 table and class methods in the SYS layer. To give a perspective on this number, it will take you over 15 years to document them all, if you can document 5 methods an hour.
All the methods shipping with Dynamics AX 2009 will have some documentation:
Or in other words:
Cumulative Update 7 for Dynamics AX R2 has been released today! Download it from Partner Source or Customer Source.
Besides 60 country specific regulatory updates and many quality improvements, these areas have been enhanced:
Inventory and warehouse management
Procurement and sourcing
Product information management
Project management and accounting
Sales and marketing
Backup and recovery
Data import, export, migration
Sales tax processing
This is a post I’ve been waiting to write for quite a while – but it had to wait until R3 became available.
To be able to measure the impact of any changes I build a very simple test harness to exercise the SysExtension framework. A two level deep class hierarchy and one attribute that decorated the sub-class. I then compiled everything to IL, and wrote a small job to measure how many class instances I could spin up per second. This velocity measurement was around 3,400 classes/second.
Debugging through the code I quickly learned that a lot of things were going on. This included creating a key for the attribute for various caches. This key was constructed via reflection on the attribute class. I avoided using reflection by introducing a new interface (SysExtensionIAttribute) and I fixed a number of other minor issues. Now the velocity jumped to 40,000 classes/second.
Is this an acceptable velocity? Well, how fast can it possibly be? The logic is in essence just creating a class via reflection, so I did a measurement of DictClass.MakeObject(). This could give me 84,000 classes/second. Slightly about double of the my current implementation. After some investigation I discovered two expensive calls: “new DictClass()” and “dictClass.makeObject()”. Can you spot what they have in common? They both requires a call into the native AOS libraries. In other words an interop call. I tried various other calls into the AOS, such as “TTSBegin” (only the first is hitting the DB), and “CustParameters::Find()” (again, only the first one is hitting the DB). To my surprise the velocity of these calls where comparative to DictClass.MakeObject(). The interop overhead outweighs what the method is actually doing. In other words, there is a limit to how many native AOS methods you can call per second. Let us call this velocity: Speed-of-sound.
Being a bit intrigued I measured the fastest and rawest possible implementation: “new MyClass()”. This would run strictly in IL, no overhead of any kind, the result was a whooping 23,800,000 classes/second. Let us call this velocity: Speed-of-light. In the words of Barney Stinton: “Challenge accepted!”
To achieve this kind of velocity the code must run 100% as IL. No calls into native AOS code. Period. Naturally there are APIs in .NET allowing for dynamically creation of class instances – they are slower than a direct instantiation, but still much faster than calling native AOS code. One other challenge was that SysExtension also can execute as pCode, and then a call into IL would cause a similar slow interop – just in the opposite direction. After a few iterations I had an implementation that would not cause an interop calls, regardless of if the code runs as IL or pCode. Take a look at SysExtensionAppClassFactory.getClassFromSysExtAttribute in R3 for details. I was pleased with the velocity: 661,000 classes/second. Or about 200 times faster than R2. Or about 15 times faster than a call to CustParameters::Find(). Problem solved: The SysExtension framework no longer has performance issues.
For a long time we have been hunting for SQL and RPC calls when looking for performance. RPC calls are expensive, as communication between two components (Client and Server) occurs. Just like SQL calls are expensive as the Server communicates with SQL (and waits for the reply). We still need to hunt for unnecessary RPC and SQL calls! Nothing changed; except that a third culprit has been identified: Native AOS calls. Relatively speaking the cost of calls into native AOS code is insignificant when compared to RPC or SQL calls – in the absence of these, the impact is measurable and significant.
This is an ERP system, so there will always be SQL calls. So why be concerned with the performance of X++ code? Well, if you can minimize the time between SQL calls, then you will also limit the time SQL holds locks, and you will experience better overall performance and scalability. After all, do you want you code to run with the speed-of-sound or speed-of-light?
Update 11-05-2014: Here is the test harness I used: PrivateProject_SysExpProject.xpo
A new white paper has been published on how to intergrate a third party version control system with AX2009. The white paper is a case study of the steps the MorphX team had to go through in order to integrate Team Foundation Server (TFS) into AX2009.
The white paper is available for download at these locations:
Microsoft Download Center:http://www.microsoft.com/downloads/details.aspx?FamilyID=48f803fc-5ded-44a8-a442-e499f2db6382
Here is a sneak preview of the new MorphX developer workspace in Microsoft Dynamics AX 2012.
Notice the clear distinction between developer and application workspaces, and how the layout of the drop down menus makes it possbile to access tools with fewer clicks. You can launch the AX client directly in development mode using: AX32.exe -development.
This post is also available on Channel 9.
THIS POST IS PROVIDED AS-IS AND CONFERS NO RIGHTS.
Here is a sneak preview of the new X++ Editor in Microsoft Dynamics AX 2012.
Notice that the editor now features word-completion, automatic indenting, scripting, zoom, multiline editing, and much much more.
These days the first milestone of AX6 is being completed. It means the first wave of new functionality has been implemented, tested and documented. As always; it is an exciting time to be working on AX...
One of the features coming in MorphX in AX6 is set of improvements in the X++ Unit Test framework.
First of all the unit test framework in AX6 is leveraging the new attribute feature in the X++ langauge. For example; you can use an attribute to declaratively specify the target class for your test (i.e. the class that is being tested by this unit test). Here is how:
Starting in AX6; you can also use attributes to mark which methods on the unit test class are test methods:
If you are using both unit testing and a version control system, you can benefit from marking your most critical test methods as check-in-tests. When setting up the version control system, you can specify which test project to run during check-in, and whether to run all unit test methods, or only the unit test methods that are marked as check-in-tests. During a check-in process the specified unit tests will be executed, and only if they all succeed the check-in will be submitted. This gives you the flexibility to run the most critical unit tests during the check-in process, while still having a full suite of unit tests that can be run on-demand. Here is how to mark a method as a check-in-test:
This posting is provided "AS IS" with no warranties, and confers no rights.
On behalf of the Dynamics AX 2009 development team I'm proud to announce that as of build 5.0.529.0 we have reached zero X++ best practice errors in the SYS layer.
Version 4.0 was the first release of Dynamics AX without any best practice errors. Reaching this level of code quality was a mammoth effort; due to the huge backlog and many new TwC related BP rules.
In Dynamics AX 2009 the goal was significantly easier to reach, as we didn't have any backlog. However; we have introduced more than 60 new BP rules, including validation of XML documentation, inventory dimensions, upgrade scripts, workflow, list pages, AIF and performance. On top of this the SYS layer now contains much more functionality than ever before - the AOD file alone has grown with more than 50%. All of this now conform to the Best Practice rules implemented.
What does this mean for you as an X++ partner developer?
For more information on MorphX Best Practices see: Channel 9 Screencast, or MSDN.
For more information on the importance of static code analysis see: Compiler warnings - and so what?