Friday, 30 August 2013

G'day:
The code & testing for the article I'm writing is going to take a few hours, and Mon-Fri I only have a coupla hours available each day to write said code, so I'll not get to the actual article until the weekend. In the meantime... where are Adobe at with bug fixing?

G'day:
Last night was the first meeting of the London Railo Group. A bunch of people in the local London Railo community got together at the Pixl8 offices and had an informal catch-up and drank beer and ate pizza. There was only about a dozen people there, but I think it was a successful first meeting. Well done Alex Skinner for organising it, and Mark Drew for giving an impromptu presentation on some random Railo stuff he finds interesting.

Monday, 26 August 2013

G'day:
This is an adjunct to my preceding article, pretty much allowing me go say "One word: parameterExists()" without actually qualifying why I said that that without requiring more than one word.

Most CFMLers probably know there is a function parameterExists() in CFML. Most people will know it's poor form to use it in favour of isDefined(), and really it's poor form to use isDefined() rather than structKeyExists(). Some people will be surprised to hear parameterExists() is still in the language; others will be aware that it's deprecated (and, curse them, others still will think that because it's deprecated that it will no longer work, but I've already covered that).

Now I knew parameterExists() had been deprecated for ages, and I always cite it as having been deprecated for over a decade, and use it as an example of why people should not get all uppity and hand-wringy at the notion of things in CFML being deprecated. We could happily deprecate <cfset> and still expect it to work in ColdFusion 15, in ten years time (no, I neither expect there to be a CF15, nor for anyone to be discussing CFML in ten years time. It was an example).

Anyway, I decided to find out how long it's been deprecated. Up until now I thought it was since CF5, because I have a copy of the CF5 docs, and it's already deprecated there:

G'day:
One thing I hate (of a very long list, it seems...) is people simply not getting what the notion of "deprecation" means. In the context of software (~ features) I mean.

For goodness sake: if one has a software system and one declares an element of that system to be "deprecated", this does not mean it's been removed from the system, or will now break, or will work in any way different from how it did before it was marked deprecated.

If we're talking about ColdFusion, and we were to say that <cfform> (pseudo-random example, but a frickin' good candidate for deprecation!) was deprecated as of CF11... then it would still work exactly the same as it does in CF10 in CF11 and every subsequent release of ColdFusion until it was finally retired.

All deprecation means is to flag that a feature will no longer receive enhancement (or bug fixing, etc), and that it will possibly be removed from the product at some later date. I would go as far as to say that if one was being professional about things, then simply saying in the release notes of CF11 that <cfform> was deprecated (but no mention of when it would be removed) then that's almost a guarantee that it'll still be there in CF12 as well. Deprecation is one thing, but the decision to actually remove something from the language ought to be flagged 1-2 version out (something that Adobe has never done).

[...]there is not situation in which a string formatted as "xx/xx/xx" should be interpreted as a date "yy/mm/dd". No-one writes dates as "yy/mm/dd".

Well Duncan pointed me at this Wikipedia page: "Date format by country". Wikipedia seems to have pages for everything.

As it turns out there is a country in which the date format is "yy/mm/dd": Kenya. Who'd've known?

That said, I stand by my point. Not for the sake of pigheadedness (well not solely that ;-), but because "Kenyan" (or any approximation thereof) is not a locale that ColdFusion supports (according to the locales listed in server.coldfusion.supportedLocales, anyhow).

So in the context of CFML... there still really is no justification for ColdFusion to ever to consider the string "xx/xx/xx" as a date-parseable value representing the format "yy/mm/dd". For it to do so, IMO, is a bug: 3617365.

Wednesday, 21 August 2013

G'day:
This might be painfully obvious to everyone, but I had a "what the hell?" moment this morning when having a look at some of Aurel's code posted against one of my earlier articles. It turns out I have the wrong expectations as to what and when CFML considers values to be boolean.

I've gotta be quick as it's taken most of my lunch break to distill the code down to something simple, but here's the crux of the matter:

G'day:
OK, having got today's Stack Overflow rant out of the way, here's the article I meant to write this morning. Or actually last night. Well actually "here's the text that someone else wrote that I meant to copy and paste in lieu of actually writing something". Here it is. CTRL-C, CTRL-V...

G'day:
F*** me Stack Overflow is populated by cocks. I was amidst answering someone's CFML question when an insecurity of self-appointed moderators (I have decided "insecurity" is an apt collective noun for these people) closed the question underneath me, so I could not post the answer.

G'day:
A few days ago I had a look at this - apparent - myth that evaluate() is terribly terribly slow and one should not use it on that basis alone (not forgetting there's no real justification to use it these days anyhow). I tested on ColdFusion 9 and 10 to gather my results (the final results posted were from CF10, but the two were much of a muchness). I speculated that given there was not really good-enough evidence to support these performance issue claims in modern versions of ColdFusion that perhaps the problem existed "back in the day" and it's since been remedied. So over the weekend I blew the dust off my CFMX7 install, and ran the tests again on a like-for-like config, alongside re-running the tests on CF10. And for the sake of completeness, here are the results (they should be read in conjunction with the original article, as I do not go into great detail as to what was being tested).

This is clarification of something Dave did dwell on during that podcast, in reference to my article 'Really, Adobe: "NotWorthEffort"'. And to fulfill Scott's observation that I'd feed-back on what Dave said.

That article draws attention to what I perceive is slack-arse-ness on Adobe's part in how they dealt with a user-raised issue on the bugbase relating to the toScript() function (3041310).

The lads on CFHour made a few points / observations which are relevant, but at least partially tangential to the point I was trying to make.

Firstly: yeah, the code that toScript() generates works. It's slightly verbose, but it works. That's a very low bar to set though, isn't it? The approach taken here demonstrates a certain lack of finesse that one might expect from a function Adobe (OK: it was Macromedia) have provided to effect a better solution that just rolling one's own. And surely that's the intent here? It also kinda shows their hand in regards to their JavaScript capabilities, which seem to be "less than ideal" (I'd actually say: "not up to the job").

Saturday, 17 August 2013

G'day:
Sorry for the "slow-news week" this week (well: it's been a coupla weeks now). Everything I'm planning to write up will take a while to prep, which means I find excuses to do something else instead.

A while back I wrote about getFunctionCalledName(), mostly because I can never find it in the ColdFusion docs as I never remember enough of what it's called to google it properly. So that article was purely google-bait (it didn't work, just in case you're interested... I still cannot ever remember what getFunctionCalledName() is called, nor can I successfully google it up).

Here's a list of CFML- or dev-oriented pete peeves of mine. In no particular order. And why? Just for the hell of it, on a slow news day.

The idea that pointless closing CFML tags is "a thing"

'nuff said.

Comments that simply state what the next line of code is doing

eg:

// create the object
theObject = createObject("TheComponent");

Seriously? F*** off if you do that. If a person is looking at that file, they understand CFML (or at least they should, and comments are not the way to solve that if it's not the case!), and reading the code is a fine way of identifying what the code does.

This is made worse by poorly maintained code in which the comments reflect the state of the code as it was a year earlier, but not how it is now.

Use comments to explain what's not already on the screen, and not readily inferrable from what's on the screen: why you're doing something, how an algorithm works, or an explanation of why unlikely-looking code needs to be the way it is (eg: some third-party service wanting dates as strings, or something).

Copying and pasting of code instead of refactoring

If you want the same functionality somewhere else in your code base: refactor, don't copy and paste (or as I term it in this context: "cu*t and paste". Because if you do it: you are one). I don't know how many times I've needed to fix something only to find out that the same bit of logic exists in several places in the code base.

Using tags in logic-only files

Tags are for interacting with mark-up. They are clumsy and clunky-looking when used in logic-only files. The only time they should be used in these cases is when Adobe have dropped the ball and there is no script-compatible implementation of the given functionality.

Not RTFMing (or should that be "RingTFM"?)

Asking questions (especially in a written forum) before even bothering to just look up the answer in the docs. Or via Google. It's just laziness, and people like that do not deserve the help they are soliciting.

CFML's "Wizard" tags

Like anything to do with the UI (<cfform>, <cfpod> etc), and including <cfinsert> and <cfupdate>. Have some pride: do your work properly.

Adobe's attitude to their clients

Their support of and participation in their developer community is appalling.

Not understanding when to use #

Thanks to David Nash for this one. Its not complicated (like when to use an apostrophe), yet so many people simply do'nt bother to learn the languages' syntax properly. NB: sic.

Not having a basic understanding of computing

Not understanding why floating point numbers are inaccurate, why data types have size limitations; or how Javascript runs on a client machine and ColdFusion runs on a server and the two don't interact directly, etc. I don't expect people to be able to write a C compiler (cue Sean to say something along the lines that he has ;-), or know the intricacies of the architecture of a CPU, but an understanding of the basics of the tool set one uses daily for one's career.

Being partisan about technology

Because I use Railo doesn't mean ColdFusion is automatically the villain (it's not for those reasons), or if I like CFML then PHP automatically sux, etc. Or I like Apple products therefore Microsoft products are automatically bad, etc. I know we work in IT, but not everything is binary. And you sound stupid if you hold opinions like that.

That's a random ten. There'll be others, and things that annoy me more, but happen less frequently so have not sprung to mind in the last 15min since I decided to write this.

I'm sure you'll disagree with at least some of these, or have some other ones of your own. Go on then...

Tuesday, 13 August 2013

G'day:
Me mate Alex Skinner of Pixl8 is hosting the new London Railo Group. The first get together is on Weds Aug 28 - so two weeks' time - at their offices in Clapham.

I'm gonna pop along and take advantage of the beer and the wifi, and I think I saw mention of pizza somewhere (can't find the reference now). Oh, and having a yap about Railo and CFML and that sort of stuff.

If yer around, head over. Alex and the crew are cool bods (I've been working for / with them on and off for years, so know them well), and it'd be good to get the Railo community in London in touch with each other.

Monday, 12 August 2013

G'day:
I'm always the first person to screw up my nose when I see someone using evaluate() in any CFML written for versions of CF after CF5. But generally because it's an unnecessary function call as there's almost always native syntactical constructs which will do the job without dynamically evaluating a string. And also in the back of my mind there's that perennial notion that it's really slow. I'd not investigated this since I was using CFMX7, and never very rigorously. So I decided to have a look at it.

Firstly, there's a few common areas I see evaluate() being used. I think these were recommended approaches back in the pre-CFMX days, but they've been unnecessary since CF was revamped to run on Java.

Dynamic variable names

This is the most common one. It often stems from a form that has an iteration of form fields with numeric suffixes on the name attribute value, to kinda emulate an array. EG:

This is shonky from the outset and the person has done themselves no favours by not scoping their variables. And had they scoped their variables, it might have occurred to them that evaluate() is simply not necessary here, and one can write much nicer code, thus:

form["teamMember#i#"]

Associative array notation will allow any variable to be accessed via a string containing its name, and obviously a string can be composed at runtime to contain dynamic values.

Working around the shortcomings of valueList()

valueList() is a bit of a rubbish function in its implementation as it is required to take a column reference, in the form query.columnName. This is the only place in CFML that this is the case, so - from the outset - alarm bells should have gone off with the implementors that this isn't a great approach. Furthermore, that is the only way of referencing a column that is permissible in valueList(). One cannot use query["columnName"] (which is also a reference to the entire column), nor any other sort of runtime expression. This causes problems if one is not in a position to hard-code the column name like that, for example if the column names are unknown at code-time, or indeed if even the query name is unknown at runtime. The latter is less often the case, granted. I have come across it though.

Firstly, the dynamic column name:

evaluate("valueList(query.#columnName#)");

That's what one has to do if one is using valueList(). But one does not need to use valueList() to effect this:

arrayToList(query[columnName]);

If one wants to emulate quotedValueList(); use listQualify() after arrayToList().

Secondly... what if the query name is a dynamic concern. One might think one can employ the previous tactic, of referencing the dynamically-named query thus:

valueList(variables[dynamicName].column);

This fails with:

Complex constructs are not supported with function valueList.

Use simple variable instead.

Which is a bit crap: it simply shouldn't matter how an expression is implemented, provided it is syntactically correct and returns the correct data type for the function taking it as an argument, it should work. What's particularly crap here is that this is a parser error (so done at compile time), not a runtime one, so CF has a built-in specific rule for valueList() to fail with expressions of this syntax. How about the compiler just lets the completely valid code through, and see if the value actually represents the desired data? Anyway, I have digressed a bit.

Traditionally the fallback here is to do this:

evaluate("valueList(#dynamicName#.column)");

This is not necessary, because one can avoid using evaluate() by simply using a known variable:

Dynamically referencing scopes

This is a less common one, but I have seen this in the past. Sometimes the runtime part of a variable reference might be the scope, rather than the variable within the scope. I've seen this being done in the past (ages ago), but can't recall the situation. However here's a quick contrived example... a lightweight scope cache:

Here we set up some variables-scoped references to actual scopes (yeah, it breaks encapsulation... this is just example code), which means we can then use associative-array notation to reference the scopes dynamically at runtime.

Dynamically referencing object methods

Another situation in which one might think to use evaluate() in the past was to call a dynamically-named method on a CFC object, eg:

One can still get away without using evaluate() here, with a bit of messing around:

theObject.___someStaticMethodName = theObject[theMethodName]; // the ___ is just cos we want something unlikely to overwrite another method already in the object
theAnswer = theObject.___someStaticMethodName(someArg="someValue");

That's a bit more code that with evaluate(), but I still think it's a bit more aesthetically pleasing that parsing & executing CFML at runtime... because bear in mind that at runtime, the natural order of things is that we're running Java bytecode, not CFML. So it goes a bit against the grain to be running CFML as well. Still: that's mostly just aesthetics.

Performance

I think the reason most people acting avoid using evaluate() is because it runs so damned slowly. But... um... here's the thing. It doesn't. It runs marginally slower than most of the non-evaluate() approaches (but not all of them!), but we're talking on a scale of 10ths / 100ths of milliseconds difference per operation. IE: on my machine 10000 iterations of my test rig for comparing dynamic variable evaluation compared to using associative array syntax, the difference was about 100ms. so 0.01ms (10 microseconds) per iteration difference. Another way of looking at it - if you really like wringing your hands over performance - is the evaluate() version is twice as slow the associative array notation, but at the scale we're talking about it simply doesn't matter.

Most of the operations I tested were about the same sort of comparison, except surprisingly the approach of injecting a statically-named reference to a method representing a dynamically named one was actually "significantly" slower than using evaluate(). I have no idea why, but there you go.

Testing Performance

My test rig for this was to do the usual approach of "loop over things a lot to 'amplify' the time an operation takes" whilst performing the test operation. I used 10000 iterations.

As well as that looping, I also used JMeter to run that code using five test threads each running five separate users to run the test code. So each test round was 25 sets of 10000 iterations, running as simultaneously as JMeter, my computer, and my CF install would allow. I was not timing the requests themselves, I was only timing the code within the requests, so there was no warm-up or tear-down overhead in my measurements.

I did two comparison tests: one round using one of the evaluate() techniques listed above, and the other using the non-evaluate() technique.

I can't stress enough that if - to test the performance of some code - you need to do this "loop over it heaps to see how long a lot of iterations take" approach, because the performance differences between the control and the test code is neglible when only doing a single operation, then just stop testing. Save yerself some time, cos the answer is: "it doesn't matter". Don't contrive an artificial situation in which you can see a difference. If you can't see the difference in a normal situation, then there is no difference worth worrying about. Doing an actual load test is different, because code can behave differently when it's run more than once at a time. Load testing for performance is essential.

NB: makeQuery() is just a UDF which makes a query with cols ID and [as specified in the function call], with a row for each element in the array.

Dynamicially referencing scopes

This lot is a bit more complicated. We've got an Application.cfc which sets some things into the application scope (so as to not need to do so each test), a coupla implementations of that scope cache thing I mentioned above, and the two test scripts.

I should do another test using invoke(), I guess, just to see how that fares.

That's it for the code. That's really just there in case anyone spots where my tests are unbalanced. I've tried to make each test analogous to the other test(s) it's being measured against.

Summary of results

Here's a sample test run's logged output:

"Severity","ThreadID","Date","Time","Application","Message"
"Information","catalina-exec-8","08/08/13","20:26:45",,"C:\apps\adobe\ColdFusion\10\cfusion\logs\evaluatePerformance010_array.log initialized"
"Information","catalina-exec-8","08/08/13","20:26:45","EVALUATEPERFORMANCE010","Elapsed: 98ms"
"Information","catalina-exec-13","08/08/13","20:26:45","EVALUATEPERFORMANCE010","Elapsed: 41ms"
[and continued in the same vein for 75 records]

And a summary of each of the tests...

Dynamic variable names

Stat\Test

evaluate()

Array

Min

32

21

25%

34

22

Mean

36

22

75%

39

23

Max

199

98

Here the Max values are definite outliers, as everything else is grouped around 30-odd or 20-odd milliseconds. On the face of it that's a dramatic "improvement" using associative array notation, but bear in mind that's over 10000 iterations. So an insignificant "real world" difference. If one is processing 10000 iterations of something on a regular basis, there are going to be more relevant things to be investigating than this difference.

valueList()

This test both dynamic query names and dynamic columns name.

Stat\Test

evaluate()

Array

Min

65

45

25%

68

47

Mean

70

48

75%

72.5

50

Max

109

58

This is about the same difference. The values are higher across the board, I guess, because there were two tests being performed in this test rig, rather than the single one previously.

Dynamic scope referencing

These are the tests using those pared down "scope cached". We're using CFC method calls here, so that seems to blow out performance in general.

Stat\Test

evaluate()

Reference

Min

120

77

25%

139

88

Mean

176

107

75%

280

175.5

Max

536

438

But it's still a similar sort of performance comparison. Still bear in mind that whilst 176ms vs 107ms sounds like a lot compared to the other results so far, bear in mind that that equates to 0.0069ms per iteration difference. So: nothing.

Dynamic object methods

This time around we have three columns: evaluate(), inserting object references, and using <cfinvoke>.

Update:

I've redone the test and the results table to include invoke().

Stat\Test

evaluate()

Reference

<cfinvoke>

invoke()

Min

121

171

93

83

25%

141

181.25

102

90

Mean

160

242

108

98

75%

232.5

334.25

126.25

132

Max

475

731

245

216

This is the interesting result: using method-reference injection is slower than using evaluate(). I was surprised by this, so ran the tests repeatedly to see if there was a difference, but the results were generally the same. I'm not on the same machine currently as I did those tests, so I cannot add another column for invoke() as well, but I'll do that this evening (update: done... invoke is fractionally faster than <cfinvoke>, it seems. But inconsequentially so). Still: I don't think the difference is worth worrying about, but it's interesting that creating a function reference and inserting it into an object has any sort of overhead at all. And <cfinvoke> is most performant, but not really so much ahead of evaluate() in this case. I guess the overhead of calling methods on objects overwhelms the difference between doing if with/without evaluate().

Conclusion

I think using evaluate() is always a poor choice syntactically, because there's almost always an approach that uses more elegant code that has the benefit of being compiled before it's run. And I think even the more verbose "work-arounds" like with the scope cache or injecting methods into an object are tidier code.

But one consideration I will not be dwelling on from now on is that I will not give any thought to performance considerations. Because they just aren't there. The performance consideration did used to be there on older versions of ColdFusion. I wonder how long it's not been the case though? Certainly by ColdFusion 9, which I used to test at work yesterday, before gathering my more comprehensive results on CF10 last night. I've yet to try Railo.

You?

Have you got any other use cases in which you're using evaluate(), or have seen it in use? Or do you have your own opinions on this? Sing out!

Tuesday, 6 August 2013

G'day:
This might actually be a manifestation of the same issue I wrote about a while back: "Right... so JSON is being a pain in the arse again". And I didn't spot this one myself - I've given up on using JSON in ColdFusion as it's just too unstable - but read about it on a thread on CF-TALK (it's not in the archive yet, so I cannae link to it).

Anyway, this time the issue is with ColdFusion and "strings that look like numbers" again, but a different slant on it. Consider this code:

On ColdFusion (9, and apparently 10 too, going from the thread I can't link you to...), the output is this:

array

1

struct

NUMBER

.0006

2

struct

struct.number

.0006

3

struct

STRUCT

struct

NUMBER

.0006

4

struct

JSON

{"NUMBER":6.0E-4}

Nice. Thanks for that, ColdFusion. Just in case yer really going "wah??" there, that's scientific notation for 0.0006. So, ColdFusion... which part of "turn this into JSON" did you interpret as "turn this into JSON and any numbers with more then three decimal place? Scientific notation please". Just to demonstrate that this is not "just one of those things", here's the output in Railo:

Yeah, I can't vouch for Railo, but on ColdFusion saving class files rapidly becomes a performance hit on the system (Windows) if your app is such that you generate more than a thousand or so classes. The reason being - it seems - that Windows really struggles to file-scan a directory to find the pre-compiled class if it's needed... say the one in memory has been garbage collected... once there are more than a few hundred files in that directory. On big apps it's more expedient to let the class recompile from source code than rely on Windows finding and loading a saved one.

I doubt this is a problem on *nix-based file systems.

The issue with CF is that all the classes are stored in one flat directory. If they were stored hierarchically (which shouldn't be too much of an issue?), then there'd be no problem. I did mention this to the Adobe bods, but they looked at me like I was speaking [some language they didn't understand... CF perhaps], and that was that.

Anyway... I dunno if the same consideration exists on Railo, but this would be one reason why one might not want those class files saving. Something to test, perhaps.

Mark Drew subsequently suggested it might be a topic for a blog article, so here one is.

Search This Blog

About

I've been a web developer since 2001. I have spent 13yrs as a CFML developer, and until Sept 2014, that was the main subject matter here. I've now been re-tasked as a PHP developer, so learning PHP will become the focus of this blog. But I also mess around with other languages too.

I tend to be a bit "forthright" in my opinions, I am indelicate, and I tend to swear too much. This will come out occasionally here: I make no apology for it.

Everything said here is my own opinion. Feel free to disagree with me :-)