Readability, self-documenting code, and CFLib.org

November 21, 2012

I'm famous! Kind of! Not really! But I just got another function approved for CFLib.org. (This brings my total up to 3...I wonder how many I need before I win a prize, but I digress). This newest function is getMeridiem: As you can see this UDF is not super fancy; it returns the "am/pm" portion of a datetime, and it's literally just 1 line of code. You might ask why I'd write such a small UDF, since I can clearly do the exact same thing like this: timeFormat(dateTime, "tt"); My answer is simple: readability and self-documenting code. The first time I submitted this UDF to CFLib.org, it actually got rejected, because the person approving code that day felt "it's always gonna be better to use a built-in function than a UDF that - for all intents and purposes - does the same as the built-in function". That of course makes a lot of sense. But then I got to thinking about another UDF I use often, also found on CFLib.org: the CharAt() function. As you can see, this too is just 1 line of code: But the big difference is, CharAt() is more readable and self-documenting than the built-in CF code. Let's look at these 2 lines: Mid( "this is sample text", 6, 1 ); CharAt( "this is sample text", 6 ); They both do the exact same thing. If you know what Mid() and CharAt() do, I feel the CharAt() function is just a tad easier to read, making the project overall go that much quicker for me (and my team). The same thing is true here: timeFormat( Now(), "tt"); getMeridiem( Now() ); If I know what the "tt" mask does for the timeFormat() function, these might both be equally readable. I'll be honest with you: I don't remember all the masks, I look up at least half of them whenever I use date/time functions in CF. So in that case, getMeridiem() makes the code more readable and self documenting, again making my life a tad easier and the project that much more efficient. Of course, this is only true if I remember what "meridiem" means, and I've had to Google that before as well. :) After thinking about CharAt() and how it compared to getMeridiem(), I re-submitted my function to CFLib.org, along with a few more notes on how I felt it was the same as CharAt() in terms of what the benefits are to using such a small UDF. The same moderator that rejected my function before, now agreed with me and approved the UDF! Sometimes UDFs don't have to solve a huge complex problem. If all they do is make the code more self-documenting, that can be enough of a benefit to the project to use a UDF over built-in code. (I was on a C++ project once where the lead developer would wrap the assert() function in 3 or 4 different names -- he had one called "pre_condition(), another called "post_condition()" and a few others too. Each wrapper called assert() and nothing else -- but by using the different wrapper functions, when we'd go back to read the code we were able to determine a little more about when/where/why these asserts were supposed to be true, making the code that much more self-documenting which benefited all of our team.) -Nolan