Status/Resolution/Reason: Needs Review//
Reporter/Name(from Bugbase): Aaron Neff / ()
Created: 05/12/2018
Components: Language, Member Functions
Versions: 2018
Failure Type: Usability Issue
Found In Build/Fixed In Build: 2018.0.01.308605 (PreRelease) /
Priority/Frequency: Normal / All users will encounter
Locale/System: / Platforms All
Vote Count: 1
Issue: member function shameful workarounds
It's a shame that member functions and UDF arguments have such disconnect. Before CF added member functions, UDF libraries used BIFs:
//UDFLibrary Version 1 (uses BIFs)
component {
string function len(required string myString) {
return len(myString)
}
numeric function floor(required numeric myNumeric) {
return floor(myNumeric)
}
date function day(required date myDateTime) {
return day(myDateTime)
}
}
Then CF added member functions, and library authors updated libraries to use member functions:
//UDFLibrary Version 2 (uses member functions)
component {
string function len(required string myString) {
return myString.len()
}
numeric function floor(required numeric myNumeric) {
return myNumeric.floor()
}
date function day(required date myDateTime) {
return myDateTime.day()
}
}
Then end-users complained that the library update broke their code. Library authors contacted Adobe for help. Adobe said some member functions are sometimes missing from simple values for performance reasons, due to the way Adobe stores simple values under the hood. Library authors filed many tickets, but they were all rejected. Adobe maintained their stance that Adobe will decide how a simple value is stored under the hood, and based on that, it will be expected behavior that some simple values just won't have some member functions.
Annoyed, library authors added shameful workarounds to their libraries so that end-users code would stop breaking:
//UDFLibrary Version 3 (uses member functions and shameful workarounds)
component {
string function len(required string myString) {
myString = toString(myString)//chagrining workaround
return myString.len()
}
numeric function floor(required numeric myNumeric) {
myNumeric = myNumeric+0;//embarrassing workaround
return myNumeric.floor()
}
date function day(required date myDateTime) {
myDateTime = dateAdd("l", 0, myDateTime)//humiliating workaround
return myDateTime.day()
}
}
And that's how the story goes sometimes.
Here's a code snippet to show the sort of values the end-user was sending to the library. It's perfectly legit. Using len() to see if the simple value is empty or not. Using floor() to remove the time portion of a date. Using date math. None of this should break simply by upgrading from BIFs to member functions.
<cfscript>
userInput = createDateTime(2018,1,1,2,3,4)
libs = [new UDFLibraryV1(), new UDFLibraryV2(), new UDFLibraryV3()]
libs.each(function(lib) {
try {writeOutput(lib.len(userInput))}
catch(any e) {writeOutput(e.message)}
writeOutput("|")
try {writeOutput(lib.floor(userInput))}
catch(any e) {writeOutput(e.message)}
writeOutput("|")
try {writeOutput(lib.day(userInput+0))}
catch(any e) {writeOutput(e.message)}
writeOutput("<br>")
})
//UDFLibraryV1 result: 26|43101|1
//UDFLibraryV2 result: The len method was not found.The floor method was not found.The day method was not found
//UDFLibraryV3 result: 26|43101|1
</cfscript>
Attachments:
Comments: