Refactoring the C/AL Code

When we discuss the methodology for refactoring, we need to focus on two areas. The first focus is on the data model—the way we store data in tables. The other is business logic—the code that is executed.

When we refactor the application, the restriction is that we do not introduce new functional features. We should focus on optimizing our application. This makes it easier to test the application, since the functional result of our transactions should match the old application.

Combining refactoring and implementing new features is very possible, but this introduces a substantial risk to our project that should be avoided if possible.

Refactoring tables

There is only a limited set of scenarios where refactoring tables is required to optimize the maintainability of the code without changing the functional application, since the Dynamics NAV user interface is typically bound to the database structure.

We will focus on the scenarios of renaming and normalization.

Renaming

Even though naming conventions in Dynamics NAV are strong and typically discussed when training new developers, this is considered an area where many mistakes are made. If, after reading this book, you would like to start implementing the naming conventions as discussed in Chapter 5, Coding Best Practices, we need to start renaming tables and fields.

The table and field names can be changed in Microsoft Dynamics NAV without breaking the code with a few exceptions.

Tip

When renaming fields and tables, a manual merge with traditional tools will detect a change. The automatic merge with the PowerShell tools, introduced in NAV2013R2, will accept this without a conflict.

When a WITH clause is used on a Table, Page, or OnRun trigger of a Codeunit, the scope of the clause is set to the Rec variable first, and the WITH variable second. When both the tables contain the same fields, this can lead to unexpected results. When renaming fields, there is a chance of breaking the code that used to work if these WITH clauses were implemented in the mentioned areas. This should and can be easily avoided by not using the WITH scope in these areas.

The following screenshot shows an ambiguous WITH statement where both the Customer and Contact table have a Name field:

Renaming

The FlowField definitions are not updated when the referenced fields are renamed in the Table. The FlowFields definitions should be updated manually. The compiler checks for these references.

Be careful with reserved words. A field in the table called Action can cause unexpected results, especially when renaming fields during refactoring. The compiler does not check for reserved words, but a list can be found on MSDN.

Note

Information on the MSDN article about reserved words is available at https://msdn.microsoft.com/en-us/library/ee414230(v=nav.80).aspx.

Normalization

Although Normalization is not typical for Dynamics NAV, there are some exceptions. When Microsoft shipped Dynamics NAV 2013, the Dimension feature was refactored to be normalized.

Introducing normalization in Dynamics NAV while maintaining the existing functionality requires the implementation of the Model-View-ViewModel Pattern, as introduced in Chapter 3, Design Patterns. We can find an implementation of this Pattern in the Dimension application area.

When changing the Data Model, we also need to provide an upgrade path for the existing users of the system. There are two ways of doing this upgrade.

Traditionally, we upgrade data by providing a temporary set of tables to which we first move the data, while making sure that the original tables are cleared. This is called step one of the upgrade. When the original tables are empty, we can make changes to the data model and after these are implemented, we can run a script that changes the data structure to the new model. This is called step two of the upgrade.

If the upgrade has time constraints, we can alternatively optimize the upgrade by providing a new set of tables instead of redesigning the existing tables. This makes step one obsolete.

Doing the data conversion directly in SQL can also make the upgrade run much faster.

Code refactoring

I hope that after reading this book, you want to implement concepts such as the Class-Method-Property model, Natural Language Programming, and Encapsulation.

When the existing code does not follow these structures, the code can be refactored by following a few easy steps.

Please note that we must be the original creator of the code in order to refactor. We should never refactor code that we do not own. If we want to refactor the code modifications that we have done in the objects we don't own, we should use the Hooks Pattern.

Finding the process owner

The first step for refactoring is to find the owner of the code. This is typically the record with which you start the transaction. If this is true, the code can be moved to a function of the table. If the code does not have a specific record, we can move it into an interface.

Moving to Codeunit

Depending on the owner, we now have either an interface or a method. Both should be in a Codeunit of their own. When the method is very small, we can consider keeping it in the table. This, typically, is the case when the function has 10 lines of code or fewer and does not have a strong probability of being changed.

Breaking down the code into functions

The next step is to see if we can further break down into functions. These functions should have logical names and when implemented, the main routine should contain readable code in function names, as discussed in Chapter 5, Coding Best Practices.

Encapsulating functions

The functions in the Codeunit should be encapsulated, meaning the Local property should be set to true. Typically, a method called Codeunit only has one global function, or you can use the OnRun trigger as the main application.

Normalizing the code

When we cannot encapsulate a function because it is called from multiple places, we should normalize the code, following the same steps. Find the owner, decide if it is an interface or a method, and repeat the steps.

If the function can be encapsulated, there is still a chance that the code can be normalized, or that the code is the result of a clone in the application. This should be evaluated by analyzing the application, and refactoring the clones in interfaces and methods of their own.

We will normalize the code and refactor the functions into members of the table in Chapter 7, Building Solutions using Patterns.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.172.195