Hi folks!
Sometimes, when designing a class method and feeding it with more and more useful features, very soon the number of parameters can reach 10 and even more.
It becomes pretty difficult for users of useful methods to remember the position of the important parameter, and it is very easy to misuse the position and transfer the wrong value to the wrong parameter.
Here is an example of such a method (I asked GPT to create a method with 20 params):
ClassMethod GenerateReportWith20Params(
pTitle As %String = "",
pAuthor As %String = "",
pDate As %String = "",
pCompany As %String = "",
pDepartment As %String = "",
pVersion As %String = "1.0",
pFormat As %String = "pdf",
pIncludeCharts As %Boolean = 1,
pIncludeSummary As %Boolean = 1,
pIncludeAppendix As %Boolean = 0,
pConfidentiality As %String = "Public",
pLanguage As %String = "en",
pReviewers As %String = "",
pApprover As %String = "",
pLogoPath As %String = "",
pWatermarkText As %String = "",
pColorScheme As %String = "default",
pPageSize As %String = "A4",
pOrientation As %String = "Portrait",
pOutputPath As %String = "report.pdf"
) As %Status
{
}
Beautiful, isn't it?)
And here is an example of using it, providing only 1,2,5,13,19 params:
Do ##class(Report.Generator).GenerateReport(
"Annual Financial Report",
"Jane Doe",
,,
"Finance",
,,,,,,,
"Alice,Bob",
,,,,,
"Landscape"
)
A soup of commas.
There are, of course, many ways to mitigate the problem. E.g., this is where JSON approach can help. I found its usage in the very useful @Benjamin De Boe's bdb-sql-utils lib e.g. here, where qualifiers are being provided as JSON and then parsed inside a method:
do ##class(bdb.sql.InferSchema).BuildAll("/tmp/data-dump/*.csv", { "verbose": 1, "targetSchema": "MySchema" })
I like it and leveraged the same approach in csvgen lib, and introduced the Gen() method, which is an alias to Generate(), but which accepts reasonable 6 parameters instead of 11. Indeed:
Generate signature:
ClassMethod Generate(fncsv As %String, dlm As %String = ",", ByRef pclass As %String, ByRef prowtype As %String, pguessTypes As %Boolean = 1, Output recordsCount As %Integer, pverbose As %Boolean = 1, pappend As %Boolean = 0, ploaddata As %Boolean = 1, pheader As %Boolean = 1, pkey As %String = "") As %Status
Gen signature:
ClassMethod Gen(fncsv As %String, dlm As %String = ",", ByRef pclass As %String, ByRef prowtype As %String, qualifiers As %String = "", Output recordsCount As %Integer)
Inside the method, JSON is being parsed to a key-value variable, which provides a convenient way to proceed with qualifiers:
ClassMethod FlattenQualifiers(ByRef qf, obj As %DynamicObject, prefix As %String = "") [ Internal, Private ]
{
set iterator = obj.%GetIterator()
while iterator.%GetNext(.key, .value) {
set sub = $s(prefix="":$$$LOWER(key), 1:prefix_"."_$$$LOWER(key))
if $isobject(value) {
do ..FlattenQualifiers(.qf, value, sub)
} else {
set qf(sub) = value
}
}
}
And this is an example of how it can be used, e.g., when Primary needs to be introduced:
Generate call:
set status=##class(community.csvgen).Generate(fn,",",.pclass,.prowtype,1,.tResults,,,,,"name")
I need to type 5 commas before a necessary parameter can be placed.
Gen call:
set status=##class(community.csvgen).Gen(fn,",",.pclass,.prowtype,{"verbose":1,"primarykey":"name"},.tResults)
Here, I provide only the qualifiers I need, and it is clear which are provided. That's why I want to share the experience with you, amazing InterSystems Developer Community!
Thanks again to both @Benjamin De Boe and JSON for making life simpler for developers with ObjectScript!
Happy coding!