Beware ColdFusion Floating Point Integers

Adobe ColdFusion uses java.lang.Double to represent numbers in most cases, and it's a floating point representation.  That means it stores a finite amount of precision about the number in question, and discards any bits beyond that.  The stored precision is relative to the magnitude of the number.  So if you ask it to store a HUGE integer, you'll start losing the right-most (ones, tens, hundreds, etc. columns).  For example:

#11111111111111111 EQ 11111111111111111#
#11111111111111111 EQ 11111111111111113#
#111111111111111111 EQ 111111111111111113#
#44444444444444444 EQ 44444444444444444#
#44444444444444444 EQ 44444444444444443#
#444444444444444444 EQ 444444444444444443#

You'd probably expect to get "YES NO NO YES NO NO" output to the page, but you'd be wrong.  What you'll actually get is "YES YES NO YES NO YES".

What's the solution for comparing large integers like this?  To compare them as strings:

#compare(11111111111111111, 11111111111111111) EQ 0#
#compare(11111111111111111, 11111111111111113) EQ 0#
#compare(111111111111111111, 111111111111111113) EQ 0#
#compare(44444444444444444, 44444444444444444) EQ 0#
#compare(44444444444444444, 44444444444444443) EQ 0#
#compare(444444444444444444, 444444444444444443) EQ 0#

Running this code will give you "YES NO NO YES NO NO" – the desired result.

I believe Railo also uses java.lang.Double to represent numerics, so I'd expect it to have the same issue, though I didn't check.

CFGroovy 2 "Release"

CFGroovy 2 has been been released into the wild tonight as it's own project, separate from CFGroovy.  Read all about it on it's shiny new project page.  With the advent of CF9 and built-in ORM tooling, ongoing development with Hibernate integration seems wasteful.  Bugs will be fixed, since there are a fair number of sites using it, but ongoing development will basically cease.

CFGroovy 2 is crazy simple, and will probably remain that way.  The concept of a Groovy path would useful, but that's about it for a roadmap at this point.  It currently stands at 88 lines, much of which could be culled if I didn't want to have dynamic loading of the Groovy JAR if it's not already on the classpath.  However, from an ease-of-use perspective for people trying it out, I feel it's an essential feature and worth a bit of extra cruft.

Yay for single-file microframeworks!

CFGroovy 2 Has Moved

Until this evening, CFGroovy 2 has lived as a branch in the original CFGroovy project.  Now it has it's very own top-level directory.  So if you've any working copies and/or unpinned svn:externals pointed at

https://ssl.barneyb.com/svn/barneyb/cfgroovy/branches/cfgroovy2

you'll need to switch them to point at

https://ssl.barneyb.com/svn/barneyb/cfgroovy2/trunk

instead.

Apologies for any inconvenience this causes, but CFGroovy 2 really isn't a new version of the original CFGroovy.  It's a totally separate project that just happens to share a name.

TwitterFeed Test Post

I seems that TwitterFeed has lost all knowledge of my blog for some reason.  They recently redid their whole everything, so maybe I got lost in the shuffle.  I can still log into my account, but my feed is no longer listed anywhere and while Twitter didn't, TwitterFeed forgot about my OAuth config.  But before I bitch too loud I wanted to do an explicit test to ensure that the whole thing is broken, not just the on-site recall.  If anyone else is using TwitterFeed and has insight, I'd love to hear it.

CFML Request Parameters

If you've worked with ColdFusion (or CFML) for very long, you've probably noticed that CFML's treatment of request parameters is a little unorthodoxed.  Specifically, it doesn't differentiate between multiple instance of the same parameter being passed.  Consider this url:

page.cfm?a=1&a=2&a=3,4&b=5

As you can see, there are three instances of the 'a' parameter, one of which has a value that contains a comma.  In CFML-land, you're going to get a single value:

url.a == "1,2,3,4"

Uh oh.

Fortunately, the Servlet Specification comes to our rescue.  You can use getParameterValues on the ServletRequest object to get back an array of values:

getPageContext().getRequest().getParameterValues("a") == ["1", "2", "3,4"]

For a more complete series of examples, check out http://barneyb.com/r/params.cfm.  Note that the Servlet spec doesn't differentiate between query string and POST parameters, while CFML does (via the url and form scopes).  If you ask me, however, you shouldn't either.  They're all just parameters – treat them as such.

ColdFusion Struct Literals Are Not Thread Safe (CFML Ones Are)

If you read my blog regularly or follow me on Twitter, you know how much I hate Adobe's quasi-implementation of struct (and array) literals.  I'm really hoping "third time's a charm" and CF9's implementation is sane.  The gripe is that this code:

<cfset s = {
  name = "barney",
  age = 29
} />

is executed as if it were written like this (on Adobe ColdFusion):

<cfset s = structNew() />
<cfset s.name = "barney" />
<cfset s.age = 29 />

The "correct" behaviour is to execute it as if it were written like this (which is how Railo does it):

<cfset temp = structNew() />
<cfset temp.name = "barney" />
<cfset temp.age = 29 />
<cfset s = temp />

This lets you write some really nasty code, causes some weird bugs, and today I realized (through some handy errors on our production cluster) that there are thread safety issues as well.   Consider this code (inside a getCacheForKey() method):

<cfif NOT structKeyExists(key_stats_cache, key)>
<cflock name="getCacheForKey.#key#" type="exclusive" timeout="1">
<cfif NOT structKeyExists(key_stats_cache, key)>
  <cfset key_stats_cache[key] = {
    getCount = 0,
    staleGetCount = 0,
    missCount = 0
  } />
</cfif>
</cflock>
</cfif>

If the struct literal were an expression, this code would be thread safe, because the assignment to 'key_stats_cache[key]' would be atomic.  However, because of the way ColdFusion implements it, it's not thread safe.  It's possible to have the existence checks trigger in a second request while the struct is building in the first request, and therefore some keys will not be present after the outer </cfif> tag of a second request.  Wrapping the outer <cfif> tag with a read-only CFLOCK will address the issue, of course, but if struct literals were implemented as expressions (the second behaviour above), the problem could never manifest itself.  So watch out!  Atomicity of assignment statements is not assured.

Riddle Me This, CFLOOP

Take this simple loop:


  #i#
  
    
  

What is the output?  My answer is the numbers 1-3 followed by 7-10.  But I was dismayed to learn this evening that it doesn't seem to be the case on my server.  There it outputs 1-10 with no breaks.  Can someone please confirm that this is NOT normal behaviour?  I'm running CF 8,0,1,195765 on x64 CentOS 5 (kernel 2.6.18-128.1.6.el5) with 64-bit Java 1.6.0_13.

Update: Clearly I'm just retarded.  It works this way on Windows, on Railo, and everyone else confirms this is known behaviour.  Somehow I've gone 10 years without running into this issue, probably because I always revert to CFSCRIPT when I do "weird" looping. Secure Tabs Online Legit

That syntax above is analogous to collection iteration (in Groovy):

(1..10).each { i ->
  println(i)
  if (i == 3) {
    i += 3
  }
}

It is NOT analogous to this for loop (also in Groovy):

for (i = 1; i <= 10; i += 1) {
  println(i)
  if (i == 3) {
    i += 3
  }
}

Weird.

An Ink Free Year

Yesterday I turned 29.  One year older on the clock, and about 20 years older in effect.  I'd planned on getting a leaf tattooed on my right calf as a birthday present, but like so much else, it didn't work out.  Since I turned 18, I've gone and had birthday tattoos more than half the years.  Never on my actual birthday, but as my present to myself when scheduling allowed.  I've been to a few shops here in Portland, but never felt right in one.  Last year I got my stars (my only tattoo since moving back from Bellingham) in Seaside where I got my first sword a day shy of 11 years ago.

That same day 11 years ago, Andrew Nygaard died at the Seaside pool.  He got hit in the chest by a medicine ball while doing dryland exercises after practice, died, crumpled to the deck, and never came back.  This year has the same week pattern as 1998: my birthday on Wednesday and the 12th on Friday.  I was just back to the pool in time to see the ball slip through his hands and watch him crumple to the deck through the office windows and down the length of the pool.  I still remember my first reaction: someone has to ensure the medics get from their ambulance to him as directly as possible, and no one is going to think about that.  So while everyone rushed about their business, I sat on the bench outside and waited to direct them through the correct door upon their arrival.  It's was fucking weird, but I was correct that no one else bothered to come outside.

The marks on my body are my own.  All put there by others, but they're there for me, even though I can't see most of them without a mirror.  Every time June rolls around, I think of my sword and Andrew.  And of Judy, his mom.  I skipped practice that day.  It was a chaotic time.  Just graduated from high school.  Off to Arizona on a swimming scholarship.  I barely swam that whole month.  I barely did anything that whole month.  It was a weird time.

It was a time of floating, like that split second when the clutch is all the way in as you slide from one gear to the next.  Everything was in flux.  Probably the case for most high school graduates who know they're shipping off to some remote college.  I feel like that again.  There is nothing here for me except responsibilities I have to fulfill until life slides into gear again.  I just hope it's not shifting from 5th -> reverse.

jQuery TableSorter Comma Parser

Last night I needed a simple HTML table with sortable columns, and after a quick Googling, found the TableSorter jQuery plugin.  I'd come across it before, but never actually used it.  Added a class to my table (for targeting and to leverage the CSS that it comes with), added the required line of JavaScript to initialize it, and I was up and running.

As I tuned the presentation, however, I ran into a couple issues.  First, the included styling sets the table width to 100%, but that was easily fixed with a .css("width", "auto") call.  I also wanted alternating row backgrounds, and a quick look showed that there is a 'zebra' widget built in that does exactly that, it just has to be enabled.

The biggest problem was with number formatting.  Some of the sortable columns contained large numbers, and when I wrapped the output with numberFormat() to add commas, the sorting reverted to textual instead of numeric.  A quick look through the source showed why: the 'digit' parser respects only numbers, the decimal point, and an optional leading +/-.  So the commas made it skip any numeric sorting and fall back to textual sorting.  Fortunately, the fix was simple.  Before initializing the table, I just added a new parser that piggybacks on the 'digit' parser's implementation:

jQuery.tablesorter.addParser({
  id: "commaDigit",
  is: function(s, table) {
    var c = table.config;
    return jQuery.tablesorter.isDigit(s.replace(/,/g, ""), c);
  },
  format: function(s) {
    return jQuery.tablesorter.formatFloat(s.replace(/,/g, ""));
  },
  type: "numeric"
});

The only difference between it and the 'digit' parser is that it strips all commas from the string before handing off to the backing methods (the blue stuff).  Works like a champ.  The separator should probably be parameterized like the decimal stuff is, but I only deal with comma separators in this app, so I didn't bother.

The only thing I wasn't able to figure out (though I'll admit I didn't try very hard) was setting the initial sort to be descending, so when you click a column header for the first time it does a descending sort rather than ascending (with subsequent clicks reversing the sort as normal).  Setting up the on-initialization sort to be descending is simple, but I didn't see a way to parameterize user-triggered sorts.

First Person Documentation

I'm not sure when I started, but I've documented things in the first person for quite a while.  Fusedocs promoted this format, and was probably a significant influence, though I recall doing it back in college as well.  It's clearly not new or uncommon, but I just had a gentleman email me about it (based on finding my old ComboBox script embedded in an app he inherited), and his comments really brought to light why I like the format so much.  Here's an example (from the ComboBox code):

/**
 * I am called to repopulate the dropdown.  There should never be a
 * need to invoke me externally.
 */
ComboBox.prototype.populateDropdown = function() {
  // ...
}

Now you might say that there is no substantial difference between that and the more typical third-persion documentation.  However, I think there's a huge difference.

First, in order to anthropomorphize the method enough to write in first person, you have to get inside what it's doing.  That provides useful insight, and can highlight behaviour that really doesn't make that much sense, even though it doesn't jump out and say "I'm wrong!".  It also makes the comments easier to write, I think, because it's more personal.

Second, writing in the first person lets you make certain statements in a far nicer way.  For example, there's no way to say "Barney implemented this method poorly", despite the fact that it might be true for whatever reason (misunderstandings, time constraints, etc.).  However, saying "I am implemented poorly " doesn't assign blame.  Even better is "I was poorly implemented by Barney", which would never be written by anyone except Barney, and therefore also prevents assignment of blame, but does let Barney take it upon himself.  Hopefully any of the three are immediately followed by how it was implemented poorly, why it was done that way, and even suggestions for improvement.

The inverse of this is it lends a bit of personality to the code.  Seemingly arbitrary business requirements tend to end up with comments that have a bit of "attitude" to them, for example.  This personality is absolutely instilled by the developer(s) themselves, but it becomes an element of the code itself which makes it far easier to deal with.  It supplies a sort of contextual memory for the code when it's cracked open again in a different time.

Finally, the mindset of the reader (even if it's the same person who wrote it) is different when interfacing with something first hand.  The first person gives you the impression that the code is alive and talking to you, and as we all know, code is a living thing.  The third persion is like what you'd see in a museum; information about a static snapshot of something dead.

I'd be quite interested to hear about other's experiences with this style of commenting, good or bad.