Microsoft Dynamics NAV Source Code Analysis – Triggers & Procedures

On my last blogpost on Source Code Analysis (which focused on the LineCount), I got the remark whether it would be interesting to drill into “statements”. I didn’t really know what he meant with it – but it made me think and drill down into the usage of the procedures.

You might remember we talked about the “places” in NAV where we were writing code, like: OnValidate trigger, custom functions, OnInsert, .. but also OnDrillDown on a control of a page .. these things. And the more you drill into it, the more things you wann find out ;-). So, the below on what came to my mind during this quest.

What are the places we write code?

In order to get some stats on that, we need to first define what we mean. Well, I’m interested in the procedure types, like “OnInsert”, “OnValidate”, but also the created functions. Well, here is the entire table – and you see, most code is on manually created functions, but still, there is a significant amount is on triggers:

Count Name
24676 Procedure
5948 OnValidate
4465 OnAction
2218 OnDrillDown
1907 OnAfterGetRecord
1281 OnPreDataItem
1063 OnLookup
982 OnOpenPage
476 ExportOnBeforePassVariable
442 OnPreReport
440 OnRun
398 OnDelete
375 OnAssistEdit
371 OnInit
311 OnPostDataItem
308 OnAfterGetCurrRecord
303 OnInsert
244 OnNewRecord
169 OnModify
162 OnRename
146 OnFindRecord
130 OnQueryClosePage
122 Event
114 OnDeleteRecord
111 OnInitReport
94 OnNextRecord
74 OnPostReport
65 ExportOnBeforePassField
63 OnInsertRecord
49 Documentation
48 ExportOnAfterGetRecord
44 OnModifyRecord
24 ExportOnPreXmlItem
23 OnClosePage
18 ImportOnBeforeInsertRecord
16 ImportOnAfterAssignVariable
13 OnPreXmlPort
9 ImportOnAfterAssignField
8 OnPostXmlPort
7 OnBeforeOpen
6 ImportOnAfterInsertRecord
4 OnInitXmlPort
2 ImportOnAfterInitRecord

The most used functions

Well, to be honest, this isn’t going to be very “true” stats, because I was not able to measure the amount of “OnModifies” or “OnInserts” or any of these trigger-calls for that matter. So I’m just focusing on all created functions/procedures – you know, the ones you can create yourself. Here is the Top 10 functions mostly used “somewhere” in C/AL:

FullNameWithID UsedByCount
Table<Currency Exchange Rate>.PROCEDURE<ExchangeAmtFCYToLCY>

156

Report<General Journal – Test>.PROCEDURE<AddError>

155

Codeunit<Reservation Engine Mgt.>.PROCEDURE<InitFilterAndSortingFor>

150

Table<Currency>.PROCEDURE<InitRoundingPrecision>

148

Codeunit<Calc. G/L Acc. Where-Used>.PROCEDURE<InsertGroup>

126

Codeunit<CalendarManagement>.PROCEDURE<TimeFactor>

124

Codeunit<AccSchedManagement>.PROCEDURE<GetDimTotalingFilter>

120

Codeunit<XML DOM Management>.PROCEDURE<AddElement>

113

Report<Vendor Pre-Payment Journal>.PROCEDURE<AddError>

111

Codeunit<Job Calculate Statistics>.PROCEDURE<ShowLedgEntry>

108

Note: It does NOT count the OnRun-trigger of a codeunit – so the Sales-Post.OnRun is not taken into account, or any “CODEUNIT.RUN” for that matter. But let’s be honest – we shouldn’t be calling code like that anyway! (no, we shouldn’t!)

Most used function names

So, let’s drill into naming conventions. First, just as a teaser, I like to know what the most used function name is – no – let’s show the Top 10 of most used names:

Count Name
238 InitializeRequest
104 Code
93 ShowDimensions
77 GetLocation
75 Initialize
69 Caption
57 ValidateShortcutDimCode
50 Load
50 SetUpNewLine
48 GetItem

Surprised? I asked this question on Twitter, you here you see the results – most of them were completely wrong :-).

To try to not confuse you (too much), there is a difference between the amount of times someone used a certain name to create a function (the above table), and the amount of times a certain function was used in some code.. . Let’s see about the latter one. Here are the function names, that are most used in C/AL code:

Name UsedByCount
AddError

869

MATRIX_OnDrillDown

596

ValidateShortcutDimCode

454

MatrixOnDrillDown

440

ShowDimensions

310

GetLocation

267

FilterReservFor

264

AddElement

264

MATRIX_GenerateColumnCaptions

212

UpdateSubform

192

GetItem

185

Initialize

176

Most Used Function prefixes

That made me think – what about prefixes. Well, that’s somewhat more difficult, because function prefixes can consist of a variaty of number of chars. So I decided to:

  • Only focus on prefixes with 2,3,4,5 and 6 characters
  • Don’t include the events (which basically start with “On”)
  • And only take the ones that make sense to me, like exclude “Ge”, because it most likely “Get” is the intended prefix.
3207 Get
2373 Set
1233 Update
1093 Calc
1079 Check
869 Show
845 Insert
842 Init
822 Create
700 Export
507 Is

This is the top – and I like all of them ;-).

Unused functions

Vjeko came to me, and said – hey – you should try to list the functions that are NOT used anymore. Well, yeah, he kind of has a point – but I didn’t really think it was useful to do that, as Microsoft probably does their own analysis .. but still, it triggered me, so I did some queries. And I was amazed by the outcome. Really .. the amount of unused functions is a dazzling 1543, spread over 413 Pages, 416 Codeunits, 356 Tables and 358 Reports. And this is what i have taken into account:

  • Only self created functions/procedures
  • Left out the event subscribers
  • Left out all functions from Codeunit 1 (as these are called from the runtime)
  • Left out all the functions from “library-Random”, as there are functions for the testability framework

And still that many. Probably all of them having their own story, I’m sure, but I’m also sure that a lot of them are quite frankly “boat anchors“. I can’t just print them all here on the blog, but let’s just shed a light on two random cases:

Codeunit<Sales-Post>.PROCEDURE<CheckWarehouse>

As said, this function is never used .. although it has quite a lot of code! For me, this is a real boat anchor. Because we can find a “CheckWarehouse” at many locations – also on SalesLine – so my assumption is that it was redesigned, but left in CU80 .. . We can find more in CU80, by the way.. .

Codeunit<G/L Account Category Mgt.>.PROCEDURE<GetIncomeSalesReturns>

This is a type of function that I come across quite frequently. This function only returns the value of a text constant, by:

EXIT(myTextConstant);

Thing is, the function is never used, but the text constant is used all over that codeunit. So – what is the point of the function?

Local or global functions

We always advocate “be as local as possible”. Only methods should be global, all the rest should be local. Well, at least that’s the guideline .. so I though – let’s see how many are local and how many are global. These are the results:

  • Local Functions: 13481
  • Global Functions: 11195

Download

I exported the object-collection that I created to create this blog. You can find all results in that. So if you’re interested in all unused functions, you can figure that out from this download: NAV_10_15140_BE_ProcsFunctions

Disclaimer

As I put in my previous blogpost, all this data was crunched by an internal tool that I can’t share, and is still in BETA. Although I have no reasons to doubt the outcome (and believe me, when I saw the unused functions, I sure doubted our tool 😉 but after quite a lot of checks, conclusion was that it has to be right), I just can’t officially guarantee the 100% correctness of the results. If you have any reason to doubt, please contact me :-).

5.00 avg. rating (97% score) - 1 vote

Permanent link to this article: https://www.waldo.be/2017/03/09/microsoft-dynamics-nav-source-code-analysis-triggers-procedures/

4 comments

Skip to comment form

    • Andri Wianto on March 9, 2017 at 3:15 am
    • Reply

    Hi Waldo,

    Why we should not call “CODEUNIT.RUN” ?

    Thank you.

    Andri

      • waldo on March 9, 2017 at 2:40 pm
        Author

      Well, I see NAV as a container. Like a class. You don’t “RUN” a class .. you run a method.
      On top of that, you break ‘where used’, go to defenition, .. and such.
      I can only see a use for CODEUNIT.RUN in a generic situation: when you don’t know in code which codeunit is going to run, like in a (what we call) a Facade-pattern.

      I could go on like this .. many reasons not do do so .. .

  1. Eric, being a stats guy I am loving this. You might recall that I’ve been doing this kind of things in the past using the old cmd tool findfunc (https://dynamicsuser.net/nav/b/vanvugt/posts/quot-where-used-quot-as-simple-as-you-can-get-it), now totally outdated, but giving goods result, like https://dynamicsuser.net/nav/b/vanvugt/posts/nav2013-beta-to-rtm-some-striking-code-changes-2-find.
    So looking forward to your tool getting out here. 😉

      • waldo on March 9, 2017 at 2:47 pm
        Author

      Cool :-). I was not aware of that post. Thanks!
      Our tool has another approach – it makes an object model of the source code. Kind of like Roslyn. When loaded, I can query the code, properties, variables .. quite quickly. Very interesting.
      I did not create this myself – I merely was part of the brainstorming sessions (which enabled the PowerShell-ability) ;-). So making this available to the community – well – no guarantee. And since there will be a whole new DEV tool, it’s not really something we focus on…

Leave a Reply to Andri Wianto Cancel reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.