The Dynamics AX design standards consist of the following considerations:
Code placement is important as it affects the following:
The general guidelines are that the code should be placed in such a way that various calls to other layers are minimized, the operation is performed at the layer where it is least expensive, and the same code need not be written at several places (e.g. if business logic is written on a form then it needs to be written in the enterprise portal for the web client also). So we should not only think about the tier of placement in the three-tier architecture, but also about the best AOT (Application Object Tree) element type for a piece of code. Once these have been designed we need to think about the type of method or objects in the classes, etc.
The three tiers in this architecture are dedicated for the following three types of jobs:
Dynamics AX has a property, RunOn, for every AOT element, which indicates the layer where it should be executed i.e. Client, AOS, or Database server. This RunOn property may have one of three values i.e. Client, Called from, and Server.
Client: The object will live on the client.
Called from: The object will live at the tier where the object is created using the ‘new’ constructor.
Server: The object will live on the server.
Now we will discuss how to decide the RunOn property value.
The value of the RunOn property for a class will decide the location of the object created from that class.
Now we will discuss the execution place for various types of methods.
The following table summarizes the execution place of various types of methods:
AOT elements | Default behavior | Can be changed |
Class static methods | Runs by default at the same place where the associated class runs i.e. if the associated class has the RunOn property value as server then the class static method will also be executed at the server. | Yes |
Class instance methods | Runs where the object of the class lives. The class objects live as described in the class RunOn property. | No |
Table static methods | Table static methods have the RunOn property as Called from and hence by default they run where they are called. | Yes |
Table instance methods | Table instance methods have the RunOn property as Called from and hence by default they run where they are called. The standard methods Insert/doInsert, Update/doUpdate, and Delete/doDelete run on the Server where the data source is located. | No |
GUI objects always live on Client. GUI objects include the FormRun, FormDataSource, all FormControls, DialogBox, and OperationProgress objects.
Reports always live on Called from, which means the object will live at the tier where the code creating it (by calling the new constructor) is running.
Temporary tables instantiate and live at the tier where data is first inserted and it does not matter where they are declared. Since the placement of temporary tables is very critical for performance, temporary tables should live at the tier where they are used. If a table is utilized in more than one tier then it should live on the tier where the greatest number of inserts and updates are performed.
QueryRun has Called from as the default value of the RunOn property. The QueryRun should always be supplied from the same tier from where it was originally run.
If you want to create a new QueryRun in place of an old one, it should be created on the same tier where the old QueryRun was executed.
The following guidelines must be followed to decide the type of code container:
AOT element | Considerations |
Class | Write code in class when either: Code is related to many tables. Code is not related to any table. Create class instance method when: Working on the instance variable of the class. Overriding is potentially useful. Create class static method when: Access to the class instance method is not required. Overriding is not needed. The functionality of the method is related to the class it is defined on. The method needs to be executed on a different tier than the method’s tier. |
Table | Write code in table method when: It is strictly related to a table. Create table instance method when: It is supposed to handle one record at a time. Create table static method when: It is supposed to handle none, some, or all the records at a time. |
Global class | Write code in global class when: Code cannot be placed more logically in another class (or table). Code is general purpose, tool extending, and application neutral. |
Forms and reports | Coding on forms or reports should be avoided as far as possible i.e. except for the calls to classes and table methods that handle complex layout and business logic. The edit and display methods must be avoided if they are placed in a table. If code cannot be placed anywhere else, i.e. the presentation tier is most suitable, then the following guidelines should be observed: Place the code at the data source or data source field level and not at the control level. Call classes from buttons on forms by using menu items. For example, rather than writing a code on the form or report, code could be written in a class and the class could be called from the menu item. |
Maps | Write code in maps when a limited number of connected fields needs to be grouped. |
Views | Do not place much code in views. |
The performance optimization guidelines can be categorized into the following three categories:
The database design principles are based on the following considerations:
Database access should be avoided whenever it is not absolutely necessary as retrieving database records from memory is far cheaper and faster. Recording database records in memory is known as caching. The following are the possible type of caching on the server:
Record caching is a type of performance enhancement technique in which one or a group of records is retrieved from the memory rather than the database. Retrieving a record from memory rather than database significantly improves the data access. Record caching can be enabled only when the following conditions are satisfied:
The retrieved records can be placed in cache if the following conditions are met:
A record is looked for when the following conditions are met:
The following table summarizes the different types of caching mechanism:
CacheLookup property | Explanation | |
None | No data will be cached or retrieved from the cache. This value of CacheLookup property is used when: Tables are frequently updated e.g. transaction tables. It is very critical to read fresh data. | |
NotITTS | All select queries that retrieved at least one result will be cached. | |
Found | All successful select queries based on caching key are cached for this type of caching. All select queries are returned from cache if the record exists there. A select forupdate in TTS will always read from the database and replace the record in cache. This value of the CacheLookup property is typically used for static tables like ZipCodes where the record usually exists. | |
FoundAndEmpty | All select queriesbased on caching keys are cached, even those select queries, which do not return data. All caching keys selects are returned from caching if the record exists or is marked as non-existing, and if it is neither marked as non-existing nor retrieving any result it will check the database and update the cache accordingly. A select forupdate in TTS will always read from the database and replace the record in cache. This value of the CacheLookup property is typically used for tables where registering non-existing keys is also important e.g. discount table. | |
EntireTable | A copy of table is created as temporary table. All selects against the table will be performed on the copy. Joins that include the table will only be performed against the copy when all tables participating in the join are EntireTable cached. Otherwise a database join is performed. Operations that change data (insert, update, and delete) are performed against the database as well as against the copy. The reread method will retrieve the data from database and update the copy data as well. The Microsoft Dynamics AX Object Server thin client will regard an EntireTable cached table as FoundAndEmpty cached as well, and will therefore build a recordCache locally when accessing the table. This value of the CacheLookup property is typically used for tables that are not supposed to be modified frequently. |
|
The RecordViewCache is useful for caching tables that are not of static nature, or contain so many records that the other caching methods would be impractical.
This type of caching can be available through the RecordViewCache class. The RecordViewCache is instantiated using X++ select with a where clause that defines the result set. Technically the RecordViewCache can be instantiated using X++ select but it will create a copy of table in memory, which may be an inefficient use of memory.
The following rules apply to the instantiating X++ select:
The limitations of the result-set caching are as follows:
In some cases result-set caching may be dangerous and hence only careful use is recommended. The following facts about result-set caching will be helpful in deciding the use of result-set caching.
As mentioned above the RecordViewCache can go out of synchronization and hence we may need to re-synchronize it again. X++ has a method reread, which retrieves the data from database and updates the cached copy.
I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…
Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…
Once we learn how to deploy an Ubuntu server, how to manage users, and how…
Key-takeaways: Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…
While developing a web application, or setting dynamic pages and meta tags we need to deal with…
Software architecture is one of the most discussed topics in the software industry today, and…