If you are an experienced object-oriented programming (OOP) language developer (like this guy in the picture) then probably you are very familiar with design patterns. OOP is so popular that there are really many patterns and they are quite commonly used. But if you develop in another programming language, then design patterns concept might not sound very familiar to you.
Design pattern is a general reusable solution to a commonly occurring problem within a given context in software design [Wikipedia]. This is one of the best practice to use design patterns - instead of wasting time to reinvent the wheel, you just built the wheel in an already well-known way. Some design patterns are universal and some are more specific to the programming language. The famous Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) in their book (Design Patterns: Elements of Reusable Object-Oriented Software) have described 23 patterns and ilustrated it with Smalltalk and C++ examples.
If you are Microsoft Dynamics NAV developer and you think there are no design patterns you can use, you should better think it over!
I am pretty sure that even if you are not familiar with the design patterns, you already use some of them. For instance, Document pattern. Even a junior NAV developer knows that when you implement new type of document you create header and lines structure, add a list page, a page of Document type and subpage to show the lines. This is the pattern - the standard way how to solve commonly occured problem.
On the Microsoft Dynamics Blog, there is a Design Patterns wiki listing different patterns for NAV:
There are many patterns published already and you can browse them by different categories (for instance: User eXperience, Setup, Error Handling). This is open community project, meaning that not only can you use design patterns, but also you are welcome to comment and even suggest new patterns.
In this blog text I would like to present just one pattern in NAV, which is not so obvious as a Document pattern. I will describe it briefly and show how we implemented that pattern in one of our projects.
In th OOP world, Façade design pattern was introduced by already mentioned Gang of Four. It is presented in the UML diagram in the following way:
The main reason to use Façade pattern is to hide complex set of functionality. Client does not have to know all the subsystems – it just calls the Façade and Façade takes care of the client’s request by calling subsystems.
Façade design pattern is so straightforward and general that can be used in NAV as well.
In one of our projects, we were building interface to export data from NAV to external system. We used buffer table concept, meaning that before we generate the XML file with the data, first we copy the data from original tables to the buffer tables, e.g. Purchase Header table -> Purchase Header Buffer table -> file. The requirement was not only to export documents, but also master data, like Vendors (data flow was similar: Vendor table -> Vendor Buffer table -> file).
For purchase documents and vendors export we have separate codeunits with some helper functions (one codeunit per table). However, the flow of the export is the same, regardless of data type. Therefore, we have extracted one generic codeunit called
Outbound Interface Mgt.. This is our Façade codeunit. At some stage of the export process, all table-specific codeunits refer to that codeunit and call a function
ExportData. Neither of those two specific codeunits has to know precisely how export is done.
Now, as I am going to demonstrate this, I would like to ask you to use a little bit of imagination. For the sake of simplicity, I don’t want to present the whole solution and I will skip definitions of the variables, because it would be too long. Trust me, I am engineer :) Variables are self-explaining.
Code of the
ExportData function in those table-specific codeunits is following. For purchase documents:
RecordVariant := PurchaseHeaderBuffer; OutboundInterfaceMgt.ExportData(RecordVariant);
(RecordVaraint is of type Variant.) For Vedors:
RecordVariant := VendorBuffer; OutboundInterfaceMgt.ExportData(RecordVariant);
Only first line of code was changed. Both codeunits, although they are based on a different table type, call the same function in Façade codeunit -
ExportData. This is the power of variant variable type. You can cast any record to variant and then pass it as a parameter to the function. Variants are often used with this Façade design pattern in NAV and this is the reason why this pattern is called in NAV Variant Façade, not just Façade.
Without Variant Façade pattern in place, most likely you would just create a piece of code for exporting Vendors and then copy-paste that code to other codeunits. However, this is a bad smell. If we can extract some blocks of commonly used code, let us do so and keep it simple.
Going back to the example. In our Variant Façade codeunit
Outbound Interface Mgt. function
ExportData looks like this:
ExportData(VAR RecordVariant : Variant) : Boolean DataTypeManagement.GetRecordRefAndFieldRef(RecordVariant, MessageStatusFieldNo, RecordRef, FieldRef); FieldRef.TESTFIELD(MessageStatusOptions::Pending); CASE RecordRef.NUMBER OF DATABASE::”Purchase Header Buffer”: IntegrationSetup.GET(‘PURCHASE’); DATABASE::”Vendor Buffer”: IntegrationSetup.GET(‘VENDOR’); END; FileName := IntegrationSetup."File Path" + GenerateNewFileName; XmlFile.CREATE(FileName); XmlFile.CREATEOUTSTREAM(XmlStream); IF NOT XMLPORT.EXPORT(IntegrationSetup."XmlPort ID to Run", XmlStream, RecordVariant) THEN ERROR(FileNotExportedErr) CreateLogEntry(RecordVariant)
What happens here?
Variantis casted to
RecordReftype (functions from codeunit 701:
Data Type Managementare very helpful here).
RecordRefwe know exactly what is the record type and which record it is pointing to (filters are preserved). Based on the record type, we can now read specific export settings from additional setup table
Integration Setup. We have different setup per data type, so we use
CASEexpression to find relevant setup.
Integration Setuprecord stores information about export path, file name and also XML Port ID that should be used for export
XmlPort ID to Run.
XmlPortis run. You can pass
XmlPortand filters will be preserved.
What are the implications? To put it in a nutshell: maintaining, extending and upgrading is cheaper. Why?
Outbound Interface Mgt.(in the
Does it have some drawbacks or weak points? Yes, I it might be more difficult to read and debug the code.
The variant Façade has been described very well on the design pattern wiki It is based on the document printing functionality (the logic for printing purchase order and sales order is basically the same). Vjekoslav Babic (Microsoft Valuable Processional) is also describing another idea of the Façade pattern – TempBlob Façade pattern. I have never used that one, but it is also interesting. Vjeko is writing about Façade pattern in the context of polymorphism and you can read this on his blog.
See what we have to offer - Careers