Monday 13 January 2014

Using "undocumented" methods

G'day:
Today, my mate Duncan is my muse. That comment should make him feel pleasingly uncomfortable.

Dunc was revisiting some code, and he saw something along the lines of this (disclosure: it was my code):

numbers = queryNew("id,number", "integer,varchar", [[1,"tahi"],[2,"rua"],[3,"toru"],[4,"wha"]]);

while (numbers.next()){
    writeOutput("#numbers.id[numbers.currentRow]# #numbers.number[numbers.currentRow]# <br>");
}



This caused an eyebrow raise: next() is not a documented method of a query object in CFML. So his contention was - for good measure - we should not be using undocumented functionality of CFML, instead stick with the mechanism CFML provides for looping over a recordset:

for (i=1; i <= numbers.recordCount; i++){
    writeOutput("#numbers.id[i]# #numbers.number[i]# <br>");
}

TBH, in the given situation, I am ambivalent. I prefer the next() approach in general as it just seems to be more in-keeping with the intent of the loop, but I "get" the whole "don't use undocumented functionality" thing. And the indexed-for loop ain't so bad.

Being  mindful of that caveat, I am inclined to consider the reality of the situation as well as the theoretical rules in place. The next() method has been part of the public API of the ColdFusion query object since CFMX 6.0, and has functioned exactly the same all along. The code we were looking at runs on CF9, with no immediate plans to migrate it anywhere. But if we did, two candidates would be Railo or ColdFusion 10 (or perhaps 11 by the time we get around to it). I cannot speak to whether CF11 still has a next() method, but Railo 4.2 and CF10 certainly do. Also, it's a Java-standard way of going about things anyhow, so I can't see how it would change. And coupled with the fact it's a public method, that kinda makes it "documented" in my books. Well if not "documented" in the sense of being written down in the "help" somewhere, then it's been "advertised" by the API as being a method one can use. If it wasn't intended to be used, it shouldn't be public (surely?).

I do err more with caution here than I do with things like leveraging the fact that a CFML string is in fact just a java.lang.String, so I feel it's completely OK to use String's methods (eg: matches() or lastIndexOf()). That said, it would - I guess - be within Adobe / Railo's rights to switch to using the java.lang.StringBuilder class instead, and then I might be screwed.

I guess I weigh-up the merits of the code as it currently is, and nod to the future, but don't code for it. I also give consideration to whether the code is clear in its intent. I'd also be more inclined to use an underlying method if there was no inbuilt CFML way of arriving at the same results in the same quantity/quality of code.

Bottom line: I am completely happy with writing that code with the call to next().

What're your thoughts on this? Do you use the methods of the underlying Java classes that ColdFusion implements CFML with?

--
Adam