mfp's two cents

...on Dynamics AX Development!

  • mfp's two cents

    Microsoft Dynamics AX 2009 is RTM!

    • 10 Comments

    Today Microsoft Dynamics AX 2009 is RTM. This means DVDs are now being mass produced, and the product is available for download at Partner Source.

     

    My favorite features in DAX2009:

    • Brand new UI: List pages, role centers, crumb-bar, activity centers and ribbons.
    • Improved performance. Especially I like the near-instantly startup of the clients.
    • Workflow support.
    • Improved reporting and BI facilties; powered by SSRS.
    • Enhanced developer experienced: TFS integration, XML documentation, ER diagrams, CLR interop and much more.
    • New suite of tools for code upgrade.

    I'm proud to have been a part of the extraordinary team building this extraordinary product, executing on a 2 year plan and delivering on time. Since you are reading my blog, I feel confident this product will have a postive impact on your professional life. Starting today!

  • mfp's two cents

    I am working on AX6.0 - what are you working on?

    • 10 Comments

    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

  • mfp's two cents

    X++ in AX7: The var keyword

    • 9 Comments

    This is the new language feature that is generating most discussions. Just like C# you can now use the var keyword when declaring variables. It has the exact same semantics, and any guideline you will find on how to use it in C# will also apply in X++.

       

    In C# the var keyword was introduced to enable scenarios where declaring the type was impossible, near-impossible or irrelevant, like with anonymous types and generics. Writing less was naturally well received by a lot of developers, and the use of var blossomed. It is also a great topic for steering up a debate. There are lots of guidelines and opinions. They cover the entire range from one extreme: "Always use it, it makes code easier to read" to the opposite extreme: "Never use it, it makes code harder to read".

       

    X++ does not support anonymous types or generics in AX7 - so the real need for the var keyword is not present - yet it is supported, and already heavily used. Like in C# the use of var is as strongly typed as when the type is explicitly provided.

       

    Personally, I'm recommending using var in only two cases:

    1. When the type is obvious.
      In X++ there is a lot of repetition. The var keyword can help avoid some of this clutter while making the code easier to read, without any information gets lost to the reader.

      For example:

      MyClass myClass = new MyClass();  

      In AX7 I would write:
      var myClass = new MyClass();   

    2. When the type is irrelevant.

      Sometimes you don't care about the type. If you don't care the reader most likely doesn't either. 

      For example:
      ListEnumerator enumerator = myCollection.getEnumerator();

      In AX7 I would write:
      var enumerator = myCollection.getEnumerator();   

     There are a number of X++ specific reasons to not use var (i.e. doesn't apply to C#)

    1. Limited support Visual Studio.
      In the X++ editor in Visual Studio, you can use F12 to go to the declaration of a type. However, the X++ editor is still not as smart as the X++ compiler. At the time of this writing you are losing this drill through capability when not explicitly specifying the type of the variable. The same applies for IntelliSense – when using the var keyword, IntelliSense is not available (yet).

       

    2. Higher risk of runtime errors.

      Just like the C# compiler, the X++ compiler will determine the type from the assignment to the variable and enforce all the same rules and restrictions. So you might think that the use of var doesn't lead to more runtime errors. There is a catch in X++ - you should be aware of. The X++ compiler doesn't enforce any validation of method invocations on object or common. So if the X++ compiler determines the type to be object or common, then you lost your safety net. It is not always obvious.

      Consider this code:
      CustTable custTable = Xml2Record(xml);
      custTable.someInvalidMethod(); // Compile error  

      Using var, the code becomes:
      var custTable = Xml2Record(xml);  
      custTable.someInvalidMethod(); // No compile error, as Xml2Record() returns a common  

     

    THIS POST APPLIES TO MICROSOFT DYNAMICS AX7 PREVIEW; IS PROVIDED AS-IS AND CONFERS NO RIGHTS.

  • mfp's two cents

    AX 2012 R2 CU7 has been released!

    • 8 Comments

    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:

    Area 

    What’s new

     

    Accounts payable

    • New options for configuring workflows for vendor invoices.
    more info

    Accounts receivable

    • External documents can now be sent as email to a customer or vendor by using the email address that is specified by the address purpose field. Any report can be sent as email to an internal employee by using the worker title.
    more info

    Budgeting

    • You can create a budget plan worksheet template for Excel by using a wizard in Microsoft Dynamics AX.
    • The budget allocation process is easier, because you can use ledger allocation rules for budgets.
    • Budget planning workflows can be set up so that they can’t be accidentally deleted or reset.
    • Budget planning workflows can be set up so that they require a parent budget plan.
    • You can specify whether budget planning user groups (XDS policies) are used for budget planning. You can also specify the number of associated budget plan lines to include when budget plans are exported to Excel.
    • You can view worksheet and justification documents from the Budget plan page in Enterprise Portal for Microsoft Dynamics AX.
    • The process of creating a budget plan from an existing budget plan is enhanced.        

    more info

    Fixed assets

    • You can now transfer more than one fixed asset at the same time.
    • The acquisition cost of fixed assets can include a miscellaneous charge amount.
    • The process for acquisition proposals or depreciation proposals for fixed assets can now be run in a batch process.

    more info

    General ledger

    • An Excel template for journal entries is included on the virtual machine for demo data.
    • More understandable posting messages for journal lines that have errors in the account combination.
    • Delete an unposted journal that contains lines.
    • View advanced rules for a main account.
    • Easier dimension setup for Excel integration.
    • Display dimensions in a specified order in Management Reporter.

    more info

    Human resources

    • New preparation reports available to help make it easier for employers to complete mandatory human resource reports.
    • Changes to the forecast positions area .
    • You can require additional details when worker information is entered or changed, and optionally enable workflow.         

    more info

    Inventory and warehouse management

    • New On-hand entries cleanup batch job can be used to delete unused entries for serialized on-hand inventory, helping to improve the performance of queries for on-hand inventory.
    • You can combine two or more inventory batches into a new or existing batch.
    • Added new Role Center for costing and inventory valuation.

    more info

    Payroll

    • You can mass update benefit rates for workers.
    • Tiered contribution calculation rates for retirement benefit plans.
    • Create and update payroll tax groups.
    • Preparation of regulatory compliance reports for payroll.
    • Separate positive pay statements for Payroll bank accounts.

    more info

    Procurement and sourcing

    • Financial dimensions can be specified on sales agreements or purchase agreements.
    • A Totals FactBox is added to the Purchase orders list page.

    more info

    Product information management

    • You can determine prices using a product configuration model.

    more info

    Production control

    • Case management functionality is enhanced for documenting and releasing product changes to production.

    more info

    Project management and accounting

    • Use Microsoft Project to create or update a Microsoft Dynamics AX project plan, and integrate with an Office 365 SharePoint project site.
    • Use Microsoft Project to create or update the work breakdown structure (WBS) for a Microsoft Dynamics AX project quotation.
    • Create a WBS template for Microsoft Dynamics AX by using Microsoft Project.
    • Expanded support for working with project teams, defining project role types, and managing projects.
    • Expanded support for managing worker assignments and capacity in projects.
    • Enable audit trails on timesheet entry and reporting.
    • Improved management of project tasks in a WBS.
    • Improvements for creating WBS templates for project tasks.
    • Intercompany pro forma invoices for project costs.

    more info

    Public sector

    • The configuration keys for public sector organizations in France are enabled by default, hence the primary address of the organization no longer has to be in France if you want to use the French public sector accounting rules.
    • You can now dispose of more than one fixed asset at the same time.

    more info

    Retail

    • Prompt for a reason code when the cashier opens the cash register drawer without performing a sale transaction.
    • You can post store transactions from statements based on the end of the business day instead of the calendar day.
    • You can use a new statement method to calculate statements by shift.
    • Passwords can now be changed and reset in Microsoft Dynamics AX for Retail POS.
    • Cashiers can view additional customer account information in Retail POS.

    more info

    Sales and marketing

    • You can calculate the sales price of an item by using an attribute-based pricing formula.

    more info

    Backup and recovery

    • We have added functionality for backup and recovery for cumulative update 7 for Microsoft Dynamics AX 2012 R2.

    more info

    Data import, export, migration

    • As of CU7, the Data Import/Export Framework is shipped as part of AX instead of as an add-on.

    more info

    Office Add-ins

    • Improved performance when you use the Office Add-ins. A new Validate dimensions button helps you locate and correct financial dimensions that were entered incorrectly or that are suspended.

    more info

    Reporting

    • PowerShell commandlet to install multiple instances of SSRS on the same SQL server
    • SSRS is primed after restart to speed up "first time" execution of reports
    • Can send reports to people using a token (@<Job Title>@) instead of being forced to name people explicitly
    • MorphX compare tool enhanced to support reports
    • Management Reporter can now be installed with primary AX setup

    more info

    Sales tax processing

    • Sales taxes and ledger accounts can be reconciled more easily.
    • Performance is improved for tax reporting.
    • You can post of sales tax amounts for intercompany transactions to either the source legal entity or the destination legal entity.

    more info

  • mfp's two cents

    Anyone interested in developer documentation of X++ code?

    • 8 Comments

    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.

    But who really cares about this? Great tools won't make my day - I want documentation!

    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:

    • 10% will be available in the X++ source code, in the product documentation and on MSDN. This content has been written by developers for developers. (and reviewed by Content Publishing).
    • 20% will only be available in the product documentation and on MSDN. This is pattern matched documentation for methods such as main(), construct(), pack(), unpack() and parm(). This documentation has been written once for each pattern, and then applied to all methods matching the pattern.
    • 70% will only be available in the product documentation and on MSDN. This is automatically generated minimal documentation for methods that we haven't manually documented. It contains syntax and other high level information.

    Or in other words:

    • You will never see the dreaded boilerplate "At the time of publication..." again.
    • About 40.000 methods contain human written developer documentation.
  • mfp's two cents

    X++ Pedal To The Metal

    • 7 Comments

    This is a post I’ve been waiting to write for quite a while – but it had to wait until R3 became available.

    T-Shirt-Fast Xpp The SysExtension framework offers some great capabilities, but unfortunately it also comes with a performance penalty (in R2). A while ago I set out to understand where the time was spent, and hoping to optimize it. As an engineer this is a typical task with an expected outcome: A few days spent, an optimization of 10-20 percent is found. This time the task turned out to completely consume me for the better part of a week, I learned some important lessons, and the outcome exceeded my wildest imagination. This blog shares my findings.

    Starting point

    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.

    First success

    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.

    First physical limit

    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.

    Ultimate physical limit

    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!” 

    Final success

    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.

    image

    Conclusion

    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

  • mfp's two cents

    X++ in AX7: Static members

    • 6 Comments

    You can now declare class member variables as static. The semantics are exactly the same as in C#; namely that all instances of the class will share the member, e.g. if one class sets the value, another class can get it.

    Naturally; this should be used with care, but there are some really cool use cases, for example, implementing a singleton pattern in now much cleaner.


    Example:

    class MyClass
    {    
        static MyClass singleton;

        public MyClass getInstance()
        {  
            if (!singleton)
            {
                singleton = new MyClass();
            }
            return singleton;
        }
    }     


    In previous versions of AX you could achieve similar behavior through the SysGlobalCache classes. The main functional difference between the two is that you can flush the SysGlobalCache classes. This is especially useful during test execution, where the test framework is automatically flushing the caches between each run to avoid state leaking from one test to another.

    Static members will not automatically be flushed – you can of course create a flush() method yourself and hook it up to the SysTest::postInvokeTearDown() event.

     

    THIS POST APPLIES TO MICROSOFT DYNAMICS AX7 PREVIEW; IS PROVIDED AS-IS AND CONFERS NO RIGHTS.

  • mfp's two cents

    Garbage Collection and RPC calls in X++

    • 6 Comments

    Dynamics AX is a 3-tier application that evolved from a 2-tier application.  Yes, this is right, the first versions of Axapta was solely a client side application communicating with the database. In version 2.0 the middle tier was introduced. The X++ language got a few new keywords, client and server, and the AX run-time provided the smartest marshaling of objects across the tiers on the planet. The marshaling is guaranteed to work in virtually any object graph you can instantiate. You can have client-side classes holding references to instances of server-side classes, which contains references back to other client-side objects, which references … you get the idea. All you have to do as a developer is to decorate your classes as client, server or called-from.

    You don’t have to worry about any low level details like how the instances are communicating across the wire. The key word in the previous sentence is “have” – stuff will just work, but unless you are very careful you may end up creating an extremely chatty (i.e. lot of RPC calls on the wire) implementation.  Recently I’ve seen two cases of well-intended changes that on the surface looked right, but both caused an explosion of RPC calls. Both were implemented by smart guys, and I wanted to point them to an article explaining the problem – and I realized that article didn’t exist. Until now.

    Garbage collection in AX

    The garbage collector (GC) AX is responsible for releasing memory consumed by object instances no longer in use. In .NET the GC is indeterministic, it runs when it “feels like” running, typically when the system has CPU capacity and is low on memory.   In contrast the GC in AX is deterministic – it runs every time an object goes out of scope.

    Consider this small example:

    static void GCJob1(Args _args)
    {
        MyServerClass myServerClass;
        //Create instance
        myServerClass = new MyServerClass();
        //Release instance
    }

    image

    Jobs run on the client tier, so this will create an instance of the MyServerClass and release it again. MyServerClass is a trivial class with RunOn=Server.

    If we enable Client/Server trace under Tools | Options | Development, and run the job, we get:

    Create instance
    Call Server: object: MyServerClass.new()
    Release instance
    Call Server: destruct class


    Notice this: The client-tier reference to the server instance, is keeping the instance alive. When the reference goes out-of-scope, then the GC takes over and calls the server to free the server memory.

    Island detection

    The GC is not just looking for instances without references – often object graphs are more complicated. To release memory that is no longer needed, the GC is looking for groups of objects without any external references – or in popular lingo: Islands. This search is potentially harmful to the performance of your application. The GC must traverse all members of any object that goes out of scope – regardless of their tier.

    Let’s build out the example by introducing a client side class that is referenced by the server instance.

    static void GCJob2(Args _args)
    {
        MyServerClass myServerClass;
        MyClientClass myClientClass;
        //Create client instance
        myClientClass = new MyClientClass();
        //Create server instance
        myServerClass = new MyServerClass();
        //Make server instance reference client instance
        myServerClass.parmMyClientClass(myClientClass);
        //Release instances
    }

    image
    Now; when myServerClass goes out-of-scope then the GC will start analyzing the object graph, and it will discover an island consisting of our two objects – despite they are on different tiers, and it will release the memory consumed.
    image

    Pretty smart – but not for free!

     

    This is the resulting RPC traffic from the above job:

    Create client instance
    Create server instance
    Call Server: object: MyServerClass.new()
    Make server instance reference client instance
    Call Server: object: MyServerClass.parmMyClientClass()
    Call Client: set class loop dependencies
    Call Client: test class loop dependencies
         
    Release instances
    Call Server: destruct class
    Call Client: destruct class

    Now suddenly we jumped from 2 RPC calls to 6! What happened? We met the GC! 

    • The first 2 calls are expected, they are a direct consequence of the methods invoked on the server tier.
    • The next 2 calls are set/test class loop dependencies. Both of these are consequences of the parm method. The set call is a result of the assignment inside the parm method. It tells the client that the server now holds a reference to the client side object. The test call is the GC looking for islands, but not finding any. When the parameter (containing the client-side object) goes out-of-scope at the end of the parm method, then GC looks for islands. As the server side class holds a client side member, then the traversal of the object graph requires a trip to the client.  
    • The last 2 calls are cleaning up. Notice that destruction is a chain reaction. First the server is called to destruct the server side object, then the server calls back to the client to destruct the client-side object.

     

    A real life example

    Consider a server side class that is looping over some data, and for each, say, row, it spins up another class instance on the server to do some calculations.  This is all server side, and perfect. So let’s add a client-side member to the mix.

    class MyServerClass
    {
          MyClientClass myClientClass;

          public void run()
          {
              int i;
              MyServerHelper myServerHelper;
              //Create client-side member
              myClientClass = new MyClientClass();

              //Loop over some data
              for (i=1; i<=10; i++)
              {
                  myServerHelper = new MyServerHelper();
                  myServerHelper.parmMyServerClass(this);
                  myServerHelper.calc();
              }
          }
      }

    image

    The alarming result is 10 client calls – or one per iteration in the loop – despite the loop only contains server side logic.

    Create client-side member
    Call Client: object: MyClientClass.new()
    Call Client: set class loop dependencies
    Loop over some data
    Call Client: set class loop dependencies
    Call Client: set class loop dependencies
    Call Client: set class loop dependencies
    Call Client: set class loop dependencies
    Call Client: set class loop dependencies
    Call Client: set class loop dependencies
    Call Client: set class loop dependencies
    Call Client: set class loop dependencies
    Call Client: set class loop dependencies
    Call Client: set class loop dependencies

    The assignment inside the parm method forces the AX runtime to traverse the object graph, and the object graph contains a client side instance.

    The alert reader would have recognized this as the Runbase pattern. The client side class is the operation progress bar. In Dynamics AX 2009 the operation progress bar framework regressed, as a client side reference was introduced - exposing all thousands of consumers to this specific problem. This got fixed in Dynamics AX 2012 R3.

    Symmetrical implementation

    The implementation of the GC and the supporting runtime is symmetrical on each tier – you can recognize them in action, when you come across these calls in the Trace Parser. Remember; they are always a consequence of the exercised X++ logic. I.e. something that can be addressed if required.

    Call Client: set class loop dependencies
    Call Client: test class loop dependencies
    Call Client: destruct class

    Call Server: set class loop dependencies
    Call Server: test class loop dependencies
    Call Server: destruct class

     

    Wrapping up

    There is only one way of understanding the impact the GC has on your implementation: Measure it!   The best tool for measurement is the Trace Parser. Alternatively, the Client/Server trace in Tools | Options | Development can be used – it will show all the RPC calls in the Message Window.

    The rule-of-thumb as a developer is to avoid class members that are living on the opposite tier. This will ensure your object graphs are single tiered, and it will make the life of the runtime and the GC much simpler, and your applications equally faster.

    There are situations where cross tier members seem unavoidable. However, there are techniques to avoid them, and achieve the same functional results. Take a look in the SysOperationProgress class in AX4 or AX 2012 R3 for an example.

     

    Code samples are attached. They are provided AS-IS and confers no rights.

  • mfp's two cents

    Microsoft Dynamics AX 2009 White Paper: Integrating a Third Party Version Control System into Microsoft Dynamics AX 2009

    • 6 Comments

    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

    CustomerSource:
    https://mbs.microsoft.com/customersource/documentation/whitepapers/ax2009_integratingthirdpartyvcs

    PartnerSource:
    https://mbs.microsoft.com/partnersource/deployment/documentation/whitepapers/ax2009_integratingthirdpartyvcs

  • mfp's two cents

    Seeing is believing - AX 2012 Developer Workspace

    • 6 Comments

    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.

Page 2 of 22 (216 items) 12345»