Parameter Object in Dynamics NAV/365 Business

#dynamicsnav #businesscentral #msdyn365bc #designpatterns

In Dynamics NAV/BC development we often see a method with a lot of parameters.

Take as an example the method FormatAddr in codeunit Format Address.

procedure FormatAddr(var AddrArray: array[8] of Text[100]; Name: Text[100]; Name2: Text[100]; Contact: Text[100]; Addr: Text[100]; Addr2: Text[50]; City: Text[50]; PostCode: Code[20]; County: Text[50]; CountryCode: Code[10])

If we need to add a new parameter to this method and this method is used in a lot of places, well, I guess you know what’s going to happen, right?

Imagine that we need to add a parameter called Name3. We would need to change the procedure and add the Name3 parameter after the Name2, like this:

procedure FormatAddr(var AddrArray: array[8] of Text[100]; Name: Text[100]; Name2: Text[100]; Name3: Text[100]; Contact: Text[100]; Addr: Text[100]; Addr2: Text[50]; City: Text[50]; PostCode: Code[20]; County: Text[50]; CountryCode: Code[10])

Now we would have to go to every method that receives these parameters and add the Name3 parameter. That would happen, for example, in the following methods:

  • OnFormatAddrOnAfterGetCountry(AddrArray, Name, Name2, Contact, Addr, Addr2, City, PostCode, County, CountryCode, LanguageCode, Handled);
  • OnBeforeFormatAddress(Country, AddrArray, Name, Name2, Contact, Addr, Addr2, City, PostCode, County, CountryCode, NameLineNo, Name2LineNo, AddrLineNo, Addr2LineNo, ContLineNo, PostCodeCityLineNo, CountyLineNo, CountryLineNo, Handled);
  • OnAfterFormatAddress(AddrArray, Name, Name2, Contact, Addr, Addr2, City, PostCode, County, CountryCode, LanguageCode);

A way to avoid this is to group (and reduce) the number of parameters. This technique is called “Parameter Object”. Basically, instead of using all these parameters, we create an object that include all those variables and we pass an instance of this new object as a parameter.

If we ever need to extend it, we just need to add the new parameter to the object. No need to add the parameter on every place the method is being called.

I’m going to create a new object called RPM Address Information. This new object is a codeunit and will have the following variables:

  • Name
  • Name2
  • Contact
  • Addr
  • Addr2
  • City
  • PostCode
  • County
  • CountryCode

The new methods would look like this:

  • procedure FormatAddr(var AddrArray: array[8] of Text[100]; var AddressInfo: Codeunit “RPM Address Information”)
  • OnFormatAddrOnAfterGetCountry(AddrArray, AddressInfo, LanguageCode, Handled);
  • OnBeforeFormatAddress(Country, AddrArray, AddressInfo, NameLineNo, Name2LineNo, AddrLineNo, Addr2LineNo, ContLineNo, PostCodeCityLineNo, CountyLineNo, CountryLineNo, Handled);
  • OnAfterFormatAddress(AddrArray, AddressInfo, LanguageCode);

Nice, don’t you think?

At least from NAV 2016, we can pass codeunits as a parameter in a procedure so we can use a codeunit to create our parameter object. Don’t forget to set the parameter as var.

The global variables cannot be accessed from outside the codeunit so we need to have getter/setter methods for that.

Here’s an example of the codeunit:

codeunit 50000 “RPM Address Information”
{
var
Name: Text[100];
Name2: Text[100];
Contact: Text[100];
Addr: Text[100];
Addr2: Text[50];
City: Text[50];
PostCode: Code[20];
County: Text[50];
CountryCode: Code[10];

procedure SetName(NewName: Text[100])
begin
Name := NewName;
end;

procedure GetName(): Text[100]
begin
exit(Name);
end;

procedure SetName2(NewName2: Text[100])
begin
Name2 := NewName2;
end;

procedure GetName2(): Text[100]
begin
exit(Name2);
end;

procedure SetContact(NewContact: Text[100])
begin
Contact := NewContact;
end;

procedure GetContact(): Text[100]
begin
exit(Contact);
end;

procedure SetAddr(NewAddr: Text[100])
begin
Addr := NewAddr;
end;

procedure GetAddr(): Text[100]
begin
exit(Addr);
end;

procedure SetAddr2(NewAddr2: Text[50])
begin
Addr2 := NewAddr2;
end;

procedure GetAddr2(): Text[50]
begin
exit(Addr2);
end;

procedure SetCity(NewCity: Text[50])
begin
City := NewCity;
end;

procedure GetCity(): Text[50]
begin
exit(City);
end;

procedure SetPostCode(NewPostCode: Code[20])
begin
PostCode := NewPostCode;
end;

procedure GetPostCode(): Code[20]
begin
exit(PostCode);
end;

procedure SetCounty(NewCounty: Text[50])
begin
County := NewCounty;
end;

procedure GetCounty(): Text[50]
begin
exit(County);
end;

procedure SetCountryCode(NewCountryCode: Code[10])
begin
CountryCode := NewCountryCode;
end;

procedure GetCountryCode(): Code[10]
begin
exit(CountryCode);
end;
}

What if we need to add the Name3 parameter? We just need to change the new codeunit like this:

codeunit 50000 “RPM Address Information”
{
var
Name: Text[100];
Name2: Text[100];
Name3: Text[100];
Contact: Text[100];
Addr: Text[100];
Addr2: Text[50];
City: Text[50];
PostCode: Code[20];
County: Text[50];
CountryCode: Code[10];

(…)

procedure SetName3(NewName3: Text[100])
begin
Name3 := NewName3;
end;

procedure GetName3(): Text[100]
begin
exit(Name3);
end;

(…)

I hope you enjoyed this article and found it useful.

Please feel free to comment on this.

Share this

Leave a Reply

Your email address will not be published. Required fields are marked *

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