This blogpost of Arend Jan Kauffman reminded me of a topic that I wanted to write a very long time now. Namely working with Variants. Sometimes I get the remark: “what the hell are they useful for? “. And to be honest: Variants could be bloody useful in some cases. Cases to make stuff even more generic then only working with RecordRef, FieldRef and such. The keyword is “Generic” here. Just trying not to create code that is copy-pasteable (if that is a word at all) .. but try that different parts of the application will run exactly the same code.
When you read the above .. you immediately think of RecordRef, RecordID, FieldRef, … all those kind of things. And indeed .. Variants can help you be even more generic .. in combination with RecordRef.
I’m going to try to explain this with a very simple use case which came to speak on a confcall yesterday: Opening a Card page from any record. You know, sometimes, opening a card for a record depends on the data on which card page you would like to open. If you look at the Sales list page, you see this:
What if I want to make this code a little bit (let’s say “much more”) generic/repeatable? First of all: I don’t want to code like that on a page .. and second: I can imagine that other tables/data/pages has the same kind of “Open-Card-For-Certain-Records”-issues.. .
What if …
What if I could write something like this?
On any of the pages, for any record, any place, any time, any … (one?). So, exacly the same code on the “Card” action of the “Sales List” as on the “Card” action of the “Purchase List”. You would expect you need two functions, because you’re passing either the Sales Header of Purchase Header record.
How can Variants help me in this?
Let’s use the “DrillDown” method to explain what I did.. .
This is what I the result is in my two pages:
You can see that I have exactly the same function of the same codeunit, and passing a record. A different type of record. One belongs to Sales Header, the other to Purchase Header.
When you drill down, you see that Variants is helping me on this:
As you can see: I’m handling the Variants .. and even went a small stem further. With the code above, you’re even able to not only pass different tables, but you’re also able to use that same function to pass RecordRef. How Generic does one want to be?
When you drill down to the “OpenCardPage”-function, you arrive in my codeunit where I manage all this, for all records:
This way, it’s centrally managed, one place, copy-able functions, .. and most important: re-usable functions (not like the default one on the page itself).
Is this all?
Not necessarily. There is a lot you can do with Variants. It’s not my intention to show you everything (that’s not possible), just a few thouchpoints.. .
So may be another touchpoint then?
Well .. one of the PRS “Design Patterns” is “Facade” (or at least, that’s what we call it now – might change ;-)). Typically in a Facade pattern, you define “codeunits” as pieces of “apps” you’re going to execute. Like a codeunit for a certain scale to get the weight of something during a business process. Another Scale – another codeunit.
In some cases, the setup is going to define which record you’re going to “send” with your codeunit. For example, I have some kind of “Validation Framework” where I set up which codeunits have to run on which triggers and so on.. . Set up could look like this:
Codeunits, that has to run on certain tables .. .
When you’re calling your generic codeunit (which we call the “Facade”-codeunit), it’s typical you’re getting a RecordRef again .. and passing RecordRef to a codeunit is not possible.. .
So this is what you could do:
First: create a variant of your recref
Second: Pass that variant to the codeunit.
This is somewhat similar to Arend Jan’s blog (he’s using it with pages).
At first .. it’s difficult to imagine what this can do for you. But in terms of “repeatability”, “upgradeability” and “maintainability” .. it is sooo powerful :-). Hopefully you agree.
If you have any other examples, please share! :-).