Posting routines - why not work directly on Rec?

jensthomsenjensthomsen Member Posts: 173
edited 2016-12-20 in NAV Three Tier
Hi
Can anyone explain the pattern used in say codeunit 80, 81 etc:

SalesHeader.COPY(Rec);
Code;
Rec := Salesheader,


Why not work directly with 'Rec'? Are there some technical reasoning for doing like this, or is it just a matter of pattern?? If it's a question of encapsulation of the Code-function, we could call the function with Rec as a VAR-parameter (the 'Salesheader' variable should not be Global in my opinion)...

Answers

  • vremeni4vremeni4 Member Posts: 323
    Hi,

    This is not just a pattern, this is done on purpose.
    The reason is to avoid to have two different versions of the same record with different changes.
    For example,
    there is a salesheader record
    SalesHeader.Name ''Name';
    SalesHeader.Address = ''Addres ';

    In the code you might want to change the name of this record
    SalesHeader.Name := 'Test1';
    SalesHeader.MODIFY;
    somewhere else in code in a different function
    you might have to change the address
    SH.Address := ''Address test';
    SH.MODIFY;

    Which of these two records is correct.
    You have now two versions,
    one with the name 'Test1' and address ''Addres '
    and the second one with the name 'Name'
    the address ''Addres test';

    Usually when this happen the system will report an error message similar to "The record was already changed ... "

    In order to prevent this error message and to synch two versions of the record we use the above structure.

    I hope this helps.
  • DenSterDenSter Member Posts: 8,307
    I always assumed that was because Rec is local to the OnRun trigger, so by copying it into a global variable you can access it everywhere in the codeunit. Never really tested that theory actually :)
  • KishormKishorm Member Posts: 921
    @jensthomsen I understand what you are saying and have thought about this before myself, for example why not just pass Rec as VAR parameter to the Code() function?

    The conclusion I came to is that this is done so that when the codeunit is called using an IF statement, e.g....
    IF SalesPost.RUN(SalesHeader) THEN
    
    ...if an error occurs and it returns FALSE then the SalesHeader record is returned in its original state. I know when such an error occurs that database changes would be rolled back but I don't think changes to the SalesHeader variable would be, so this method is to deal with that situation. I've not actually tested it, but this is what I settled with in my own mind :)
  • DenSterDenSter Member Posts: 8,307
    Haha, funny how we're all trying to come up with an explanation, and they all make sense :)
  • jensthomsenjensthomsen Member Posts: 173
    vremeni4 wrote: »
    Hi,

    This is not just a pattern, this is done on purpose.
    The reason is to avoid to have two different versions of the same record with different changes.
    For example,
    there is a salesheader record
    SalesHeader.Name ''Name';
    SalesHeader.Address = ''Addres ';

    In the code you might want to change the name of this record
    SalesHeader.Name := 'Test1';
    SalesHeader.MODIFY;
    somewhere else in code in a different function
    you might have to change the address
    SH.Address := ''Address test';
    SH.MODIFY;

    Which of these two records is correct.
    You have now two versions,
    one with the name 'Test1' and address ''Addres '
    and the second one with the name 'Name'
    the address ''Addres test';

    Usually when this happen the system will report an error message similar to "The record was already changed ... "

    In order to prevent this error message and to synch two versions of the record we use the above structure.

    I hope this helps.

    Hmmmm, I can't see that this really "solves" the problem...It's just a matter of choosing 'SH' or 'SalesHeader' to be the right one?
  • jensthomsenjensthomsen Member Posts: 173
    Kishorm wrote: »
    @jensthomsen I understand what you are saying and have thought about this before myself, for example why not just pass Rec as VAR parameter to the Code() function?

    The conclusion I came to is that this is done so that when the codeunit is called using an IF statement, e.g....
    IF SalesPost.RUN(SalesHeader) THEN
    
    ...if an error occurs and it returns FALSE then the SalesHeader record is returned in its original state. I know when such an error occurs that database changes would be rolled back but I don't think changes to the SalesHeader variable would be, so this method is to deal with that situation. I've not actually tested it, but this is what I settled with in my own mind :)

    Good theory, but I have done some testing in a 2015 version, and here the rollback is done (as expected) right on the SalesHeader variable. So in my mind its just some kind of "Boat-anchor"....

  • David_SingletonDavid_Singleton Member Posts: 5,479
    edited 2017-08-06
    Actually the reason is quite simple.

    When Navision Financials was released, it came with an code conversion tool kit that converted some of the old DOS (navi.exe) version objects to the new Financials (fin.exe) objects. In the old version you only had "Functions" which were mapped to CodeUnits. A function simply "ran" and was quite different to the OnRun we now know, which really was put there just for backwards compatibility. To convert caller code (eg the button F8 to post become F11 with code so the OnRun ran similar to the DOS version so that the tool could map one to one.

    Also as relating to what Denester says, there were no local variables in the old version, so converted code would often fail when converted to Financials where the variable scope didn't match. This also solved that.

    Actually there were a few more reasons, but all of them were to maintain compatibility with DOS.

    We were told that this was just a temporary construct and that as new versions were released it would be deprecated. But 20 years later we are still following the old way blindly with no idea why.
    David Singleton
Sign In or Register to comment.