Friday 31 August 2012

Good things about Railo (#1) - CFLOOP

G'day, this is just a quick one.

In my last post I was discussing looping over arrays, and how Adobe messed-up their implementation of looping over an array with <cfloop> a bit (3321646).  Overnight, Gert from Railo added a comment, drawing my attention to Railo's handling of same.  And I gotta say I'm impressed.

Thursday 30 August 2012

Arrays in CFML (part 4)

G'day:
As the title suggests, this is part four of a series of articles I've written about arrays in CFML. So far I've covered what an array is and how to create them, plus two articles covering all the functions in CFML which specifically work with arrays.
As well as these functions that are specifically implemented to maintain & manipulate arrays, there are a bunch of other functions relating to other data types that use arrays. I'm going to cover those in this article. I'll break them down by the data-type they relate to.  I'm not going to do indepth coverage of how the functions work, because I'll eventually cover them when I give the various other data types the same treatment I'm giving arrays here.  EG: I'll discuss structFindKey() thoroughly when I do an exploration into "Structs in ColdFusion" (OK, so you've been fore-warned... there's more of this to come! ;-).  I'm just gonna dwell on the array`ed-ness of the relevant functionality.

Saturday 25 August 2012

ColdFusion Modularisation

G'day:
I was listening to the <CFHour> podcast this morning, and one of the things they touched on whilst discussing the new ColdFusion roadmap that Adobe have released was this thing it mentions about a "pluggable framework".  The roadmap gives no details, but Dave and Scott basically discussed the same conclusions I had drawn when thinking about it.

I'd really like to see the core of ColdFusion pared back to the essentials, and then everything else offered as a module.  I think CF is overpriced, but I see where the pricing comes from: there's a helluva lot of features in there.  Unfortunately I don't use most of them, so I'm paying for stuff I don't need.  I don't mind paying for stuff, but I do actually prefer to want the stuff I'm paying for.

(That said, I've never bought a licence of CF in my life.  That's what employers are for ;-)

So, anyway, I've got my own ideas about how important the various areas of ColdFusion are to me, but everyone's got different requirements of ColdFusion, and we all work our own way.


I'd like to get an idea of what bits 'n' pieces of ColdFusion are important to people, and to that end I've created a survey (the link's further down).

The gist of the survey is that I've broken ColdFusion down into a number of areas, and predetermined what I think is "core" and what I think is possibly a module.  My breakdown was as follows:

Thursday 23 August 2012

Arrays in CFML (part 3)

G'day:
This article finishes up the coverage of array functions in CFML (there's more to discuss than just the functions: I'll get to that stuff in yet another article). Most of the array functions were covered in an earlier article, and I'm just finishing of the rest of them here. The functions here haven't been put in a separate article for a good reason: it's just that I'm daft and forgot to put then in the earlier article that should have included them. I dunno how I missed them of the list initially, as I based my "todo list" on the list of functions on the "Array Functions" page from the CF docs. Like I said: I'm just daft. Anyway... here they are.

Tuesday 21 August 2012

The ColdFusion issue tracker

G'day:
This is just a filler post that I can write this morning on my way to work and finish of before 9am. I started doing part three of my series of articles on CF arrays, but realised I needed CF10 to do the code, and we've only got CF9 on our work PCs. So I'll have to do that one at home.

So, anyway, for most of the life of ColdFusion, neither Allaire nor Macromedia provided a public-facing issue tracker for ColdFusion. I had only just started with CF when it was an Allaire product, and never really had need to investigate bugs (it was safe to assume any bugs that cropped-up were in my own code, not theirs. This is actually generally still the case  ;-). By the time I actually knew what I was doing and knew a CF bug when I saw it all I had by way of communicating this to Macromedia was the "black hole". Or as they'd prefer to call it: the "wish list". This was a simple form that allowed one to enter in a bug or an enhancement request, submit it, and that's the last you'd hear of it. Not an encouraging user experience.

Friday 17 August 2012

Quality of CFML documentation

[This is a "toned-down" edit of the first draft I made of this doc.  The initial doc had a bit more vitriol in it than would be considered helpful.  Plus I was going to have to give it an NC-17 rating for its language.  It's a good thing to draft something then cool-off before pressing "send" sometimes]

G'day:

I've had a long day, some things that could gave gone smoothly didn't, and I'm in an intolerant mood. Some would say "sounds pretty much like your default setting, Cameron". Fair cop.

Anyway, I'm trying to write this second article about ColdFusion arrays (now complete... I started on this rant a few days ago), and I'm reading the official Adobe docs for inspiration (OK, not "inspiration", I guess. Anyway: I'm reading their docs).

Thursday 16 August 2012

Arrays in CFML (part 2)

G'day:
In this article, which is part two in an ongoing series, I'll discuss the various functions CFML ships with for working with arrays. The first part described what an array is, and how to create them.

The online docs cover each of these functions too, but the coverage is pretty superficial. They cover all the syntax options and give a code example, but they don't go beyond that. Having been around the block a few times (and thus... err... ending up back where I started.. hmmmmm...), I've picked up the odd but of insight, and have explored some of the idiosyncrasies of CFML that isn't covered in the docs. I shall try to discuss why one might want to use a given function, rather than just cataloguing that it exists (which is all the official docs seem to set out to do, at times).

The docs are good for something though: they do act as a good lookup of what's available, so go have a look at then after yer done here.

Anyway, enough waffle...

Just giving my surveys a nudge

G'day:
A few weeks back I launched a coupla surveys on Survey Monkey (what a cool service that is... I'd never used it before).

I've got a reasonable number of responses, but my blog was / is so low-traffic that I haven't accumulated a number of responses I think makes a legit case to pass on to Adobe.

Sorry to pester y'all, but if you haven't done the surveys, I'd deeply appreciate it if you could.

Here they are:

Much appreciated.

--
Adam

Wednesday 15 August 2012

CFML: More on Application.cfc... when things run

G'day
This one stemmed from me trying to come up with an accurate answer to someone's question on StackOverflow.  To summarise, the question was about what order things run in, what scopes come into play when, and all that sort of thing.  Stuff I imagine most of us pretty much know, but perhaps don't completely know the boundaries of the edgecases.  Certainly I sat down at the keyboard, drew myself up in an all-knowing sort of way ready to type the model answer, before thinking... "you know what?  I don't actually know for sure".  And when I answer stuff on forums, I like to be like 99% confident I'm right.  Not for my sake, but because I don't like wasting people's time by giving inaccurate answers.  And a bit for my own sake ;-)


Anyway, I voted-down the two answers that were there when I first read the question, because I thought they were - on balance - inaccurate.  Both had elements of correctness about them, but they both had blatant inaccuracies about them too (ie: they stated things that were outright wrong).  But I figured if I was voting stuff down, I had better come back with the goods.
Speaking of StackOverflow... here's an aside.  If you are reading this and you don't already help out on StackOverflow and - more importantly - the Adobe ColdFusion forums, please consider donating some of your time to helping the ColdFusion community.  There are a lot of people asking questions out there, and not enough people to answer them.  We could use your help.
But anyway... that's not the topic of my wittering for the day.
Application.cfc.

So, yeah, it occurred to me I didn't actually 100% know when various scopes became available, and what was available where, and that sort of thing.  I also saw it as low-hanging-fruit for a blog entry, so here I am now.

I knocked together a quick Application.cfc, which logged what it was up to and when:


The logic at play in this is repetitive: at each step of the Application.cfc I test various scopes that might exist, report if they do exist, and attempt to create a variable in them.  Then as processing continues through various event handlers, I keep track of what exists and where.

The log file created is as follows (this is a bit longwinded... scroll down rather than read it all. I've highlighted the important bits):

1 in pseudoconstructor before application name is set application scope not enabled
1 in pseudoconstructor before application name is set session scope not enabled
1 in pseudoconstructor before application name is set request.pseudoconstructor initialised
1 in pseudoconstructor before application name is set this.pseudoconstructor initialised
==================================================
1 in pseudoconstructor after application name is set application scope not enabled
1 in pseudoconstructor after application name is set session scope not enabled
1 in pseudoconstructor after application name is set request.pseudoconstructor existed
1 in pseudoconstructor after application name is set this.pseudoconstructor existed
==================================================
1 in onApplicationStart application.pseudoconstructor initialised
1 in onApplicationStart session scope not enabled
1 in onApplicationStart request.pseudoconstructor existed
1 in onApplicationStart this.pseudoconstructor existed
==================================================
1 in onApplicationStart application.onApplicationStart initialised
1 in onApplicationStart session scope not enabled
1 in onApplicationStart request.onApplicationStart initialised
1 in onApplicationStart this.onApplicationStart existed
==================================================
1 in onSessionStart application.pseudoconstructor existed
1 in onSessionStart session.pseudoconstructor initialised
1 in onSessionStart request.pseudoconstructor existed
1 in onSessionStart this.pseudoconstructor existed
==================================================
1 in onSessionStart application.onApplicationStart existed
1 in onSessionStart session.onApplicationStart initialised
1 in onSessionStart request.onApplicationStart existed
1 in onSessionStart this.onApplicationStart existed
==================================================
1 in onSessionStart application.onSessionStart initialised
1 in onSessionStart session.onSessionStart initialised
1 in onSessionStart request.onSessionStart initialised
1 in onSessionStart this.onSessionStart existed
==================================================
1 in onRequestStart application.pseudoconstructor existed
1 in onRequestStart session.pseudoconstructor existed
1 in onRequestStart request.pseudoconstructor existed
1 in onRequestStart this.pseudoconstructor existed
==================================================
1 in onRequestStart application.onApplicationStart existed
1 in onRequestStart session.onApplicationStart existed
1 in onRequestStart request.onApplicationStart existed
1 in onRequestStart this.onApplicationStart existed
==================================================
1 in onRequestStart application.onSessionStart existed
1 in onRequestStart session.onSessionStart existed
1 in onRequestStart request.onSessionStart existed
1 in onRequestStart this.onSessionStart existed
==================================================
1 in onRequestStart application.onRequestStart initialised
1 in onRequestStart session.onRequestStart initialised
1 in onRequestStart request.onRequestStart initialised
1 in onRequestStart this.onRequestStart existed
==================================================
1 in onRequest application.pseudoconstructor existed
1 in onRequest session.pseudoconstructor existed
1 in onRequest request.pseudoconstructor existed
1 in onRequest this.pseudoconstructor existed
==================================================
1 in onRequest application.onApplicationStart existed
1 in onRequest session.onApplicationStart existed
1 in onRequest request.onApplicationStart existed
1 in onRequest this.onApplicationStart existed
==================================================
1 in onRequest application.onSessionStart existed
1 in onRequest session.onSessionStart existed
1 in onRequest request.onSessionStart existed
1 in onRequest this.onSessionStart existed
==================================================
1 in onRequest application.onRequestStart existed
1 in onRequest session.onRequestStart existed
1 in onRequest request.onRequestStart existed
1 in onRequest this.onRequestStart existed
==================================================
1 in onRequest application.onRequest initialised
1 in onRequest session.onRequest initialised
1 in onRequest request.onRequest initialised
1 in onRequest this.onRequest existed
==================================================
1 in onRequestEnd application.pseudoconstructor existed
1 in onRequestEnd session.pseudoconstructor existed
1 in onRequestEnd request.pseudoconstructor existed
1 in onRequestEnd this.pseudoconstructor existed
==================================================
1 in onRequestEnd application.onApplicationStart existed
1 in onRequestEnd session.onApplicationStart existed
1 in onRequestEnd request.onApplicationStart existed
1 in onRequestEnd this.onApplicationStart existed
==================================================
1 in onRequestEnd application.onSessionStart existed
1 in onRequestEnd session.onSessionStart existed
1 in onRequestEnd request.onSessionStart existed
1 in onRequestEnd this.onSessionStart existed
==================================================
1 in onRequestEnd application.onRequestStart existed
1 in onRequestEnd session.onRequestStart existed
1 in onRequestEnd request.onRequestStart existed
1 in onRequestEnd this.onRequestStart existed
==================================================
1 in onRequestEnd application.onRequest existed
1 in onRequestEnd session.onRequest existed
1 in onRequestEnd request.onRequest existed
1 in onRequestEnd this.onRequest existed
==================================================
1 in onRequestEnd application.onRequestEnd initialised
1 in onRequestEnd session.onRequestEnd initialised
1 in onRequestEnd request.onRequestEnd initialised
1 in onRequestEnd this.onRequestEnd existed
==================================================
2 in pseudoconstructor before application name is set application scope not enabled
2 in pseudoconstructor before application name is set session scope not enabled
2 in pseudoconstructor before application name is set request.pseudoconstructor initialised
2 in pseudoconstructor before application name is set this.pseudoconstructor initialised
==================================================
2 in pseudoconstructor after application name is set application scope not enabled
2 in pseudoconstructor after application name is set session scope not enabled
2 in pseudoconstructor after application name is set request.pseudoconstructor existed
2 in pseudoconstructor after application name is set this.pseudoconstructor existed
==================================================
2 in onRequestStart application.pseudoconstructor existed
2 in onRequestStart session.pseudoconstructor existed
2 in onRequestStart request.pseudoconstructor existed
2 in onRequestStart this.pseudoconstructor existed
==================================================
2 in onRequestStart application.onApplicationStart existed
2 in onRequestStart session.onApplicationStart existed
2 in onRequestStart request.onApplicationStart initialised
2 in onRequestStart this.onApplicationStart existed
==================================================
2 in onRequestStart application.onSessionStart existed
2 in onRequestStart session.onSessionStart existed
2 in onRequestStart request.onSessionStart initialised
2 in onRequestStart this.onSessionStart existed
==================================================
2 in onRequestStart application.onRequestStart existed
2 in onRequestStart session.onRequestStart existed
2 in onRequestStart request.onRequestStart initialised
2 in onRequestStart this.onRequestStart existed
==================================================
2 in onRequest application.pseudoconstructor existed
2 in onRequest session.pseudoconstructor existed
2 in onRequest request.pseudoconstructor existed
2 in onRequest this.pseudoconstructor existed
==================================================
2 in onRequest application.onApplicationStart existed
2 in onRequest session.onApplicationStart existed
2 in onRequest request.onApplicationStart existed
2 in onRequest this.onApplicationStart existed
==================================================
2 in onRequest application.onSessionStart existed
2 in onRequest session.onSessionStart existed
2 in onRequest request.onSessionStart existed
2 in onRequest this.onSessionStart existed
==================================================
2 in onRequest application.onRequestStart existed
2 in onRequest session.onRequestStart existed
2 in onRequest request.onRequestStart existed
2 in onRequest this.onRequestStart existed
==================================================
2 in onRequest application.onRequest existed
2 in onRequest session.onRequest existed
2 in onRequest request.onRequest initialised
2 in onRequest this.onRequest existed
==================================================
2 in onRequestEnd application.pseudoconstructor existed
2 in onRequestEnd session.pseudoconstructor existed
2 in onRequestEnd request.pseudoconstructor existed
2 in onRequestEnd this.pseudoconstructor existed
==================================================
2 in onRequestEnd application.onApplicationStart existed
2 in onRequestEnd session.onApplicationStart existed
2 in onRequestEnd request.onApplicationStart existed
2 in onRequestEnd this.onApplicationStart existed
==================================================
2 in onRequestEnd application.onSessionStart existed
2 in onRequestEnd session.onSessionStart existed
2 in onRequestEnd request.onSessionStart existed
2 in onRequestEnd this.onSessionStart existed
==================================================
2 in onRequestEnd application.onRequestStart existed
2 in onRequestEnd session.onRequestStart existed
2 in onRequestEnd request.onRequestStart existed
2 in onRequestEnd this.onRequestStart existed
==================================================
2 in onRequestEnd application.onRequest existed
2 in onRequestEnd session.onRequest existed
2 in onRequestEnd request.onRequest existed
2 in onRequestEnd this.onRequest existed
==================================================
2 in onRequestEnd application.onRequestEnd existed
2 in onRequestEnd session.onRequestEnd existed
2 in onRequestEnd request.onRequestEnd initialised
2 in onRequestEnd this.onRequestEnd existed


The log here follows two consecutive requests (labelled "1" and "2" in the leftmost column).

There's a whole lot of bumpf there, but the stand-out things are highlighted.

First, let's look at what happens in the pseudo-constructor (the bit of code within the component tags, but outwith any method in the CFC).

This is not surprising:

1 in pseudoconstructor before application name is set application scope not enabled
1 in pseudoconstructor before application name is set session scope not enabled

There's no chance that there'd be any sense of application before the this.name line had been encountered.  CF doesn't know which application a given request is part of before it's been told.  Equally the session scope cannot exist prior to the application being identified, because sessions are bound to applications.

This is straight forward:
1 in pseudoconstructor before application name is set request.pseudoconstructor initialised
1 in pseudoconstructor before application name is set this.pseudoconstructor initialised

Obviously we know we can set this-scoped variables here... we'd not be able to set the application settings otherwise.  Being able to set request-scope variables is slightly surprising, given that this is before onRequestStart(), esp. given what I'm drawing your attention to next:

1 in pseudoconstructor after application name is set application scope not enabled
1 in pseudoconstructor after application name is set session scope not enabled

So this is after the application has been named.  But still the application and session scopes aren't available.  I expected they might have been as there's no reason for them not to.  I guess CF waits until the onApplicationStart() and onSessionStart() event handlers start before starting those two scopes.  Given my earlier diatribe on events vs event handlers, I half expected the scopes to be there, even if the event handlers had yet to be called.  So that is definitely something I have learned about all this.

Tuesday 14 August 2012

Obligatory ColdFusion Roadmap article

G'day
Like the vapid echo-chamber that it is, Twitter had been resounding with content-nil repetition of people restating what Adobe announced overnight: a public-facing roadmap for the direction of ColdFusion and ColdFusion Builder.

I struggle to communicate anything of merit in 140 characters (so... much the same as anyone else then  ;-), so I'll write about it here instead.

First up: heres a link to the official blog post, linked from which is the roadmap PDF.


Monday 13 August 2012

Communications policy

G'day
Just a quick note.

Please do email me about anything you read on the blog... the email address to use is cameron.adam+blog AT gmail.com (I dunno if I need to do that anti-spam thing?).

Bear in mind that I reserve the right to reproduce in part or in whole any emails you send me.  If I quote just a part of it, I will make sure not to alter the context of what you have said.

Unless you state otherwise, I will also cite your name (but, obviously, not your contact details!).  If you specifically ask not to be identified, I will respect that.

All in all though, please consider commenting on the blog rather than emailing direct, if whatever you want to say relates to something I've said on the blog.

Update:
I'm fed-up with inane "my favourite platform is better than your favourite platform" comments being posted against articles that have nothing to do with the comparison of various CFML platforms. In fact even when the article is actually about such comparisons, such comments are completely insightless, so just not worth making.  If you post stuff like that, you're a f*ckwit.  And I will delete the comment. So don't bother.

Cheers.

--
Adam

Olympic tables

G'day
Right, so that's the main Olympics over and done with, so I'll get rid of the medal tables from the right-hand-side of the blog page, and will just post them here for posterity.

Below are all the countries my readership comes from (with the top three placings for the given metric as well), with their total Olympic medal tally, adjusted for population:

Sunday 12 August 2012

Complex data-types in CF, and how they're not copied by reference

G'day
I've got part 2 of the array discussion underway, but I'm just going to digress slightly to write some notes up about how CFML deals with assigning and passing-around complex objects.

Again there's probably nothing new here for most bods out there, but hopefully it'll be useful to some people.

OK, so first up, there are a number of data types in CFML:
  • string (including lists)
  • date
  • boolean
  • numeric (including both integer and floating point)
  • array
  • struct
  • query
  • XML
  • objects (specifically native CFML ones, ie: component instances)
  • [others]
Included in "[others]" are stuff like file handles, images, spreadsheets, FTP connections, and stuff like that... there's a whole bunch of them, and I won't try to list all of them because I'll forget something, which'll mean someone will need to add a comment to point this out. So I'm just saving us all some time.

Saturday 11 August 2012

Arrays in CFML (part 1)

G'day:
I'm going to write up my understanding of how arrays work in CFML. This is a mundane topic in any programming language, but it's also absolutely critical, and having a good handle on how they work is very important. I will say up front that if you're a seasoned CFML developer that there probably won't be anything in here you don't already know.

Thursday 9 August 2012

Two timelines: Railo vs ColdFusion

G'day
This is just a quick bouquet (for Railo) and brickbat (for ColdFusion).

Here's the timeline of a bug that was found in Railo:

TimeElapsed TimeMilestone
8 Aug 2012 15:10-Potential bug in int() function reported on the mailing list
8 Aug 2012 15:5040minBug confirmed by community member
8 Aug 2012 21:236hrsProbable cause of bug suggested by community member
9 Aug 2012 08:0317hrsTicket raised
9 Aug 2012 09:1118hrsExplanation of issue offered by Railo dev team member
9 Aug 2012 10:3919hrsBug fixed ready for next release
9 Aug 2012 10:3919hrsWorkaround offered by Railo dev team member

Note that this is a fairly trivial issue, and the workaround is fine.  But it's now fixed, and will be released shortly.

Tuesday 7 August 2012

ClassViewer.cfc

G'day
This is just a quick follow-up to my previous entry about ClassViewer.java.

ClassViewer.java

G'day
I've had a busy weekend and a crazy time at work and have been tied-up in the evenings recently, hence the radio silence. But anyway I'm gonna squeeze a quick one out now (oh... please don't dwell too much on the potential double entendres there. You probably wouldn't've until I mentioned that, I guess... Oops).

Today I'm just publicising some code that I've found very handy in working out what ColdFusion is getting up to behind the scenes, as well as understanding how the "internal" methods of CF's class implementations of its various data types work.

Saturday 4 August 2012

Hungarian Notation

G'day:
Here's another old-skool and divisive topic: the usage of Hungarian notation in variable-naming.

As a brief overview for those not interested in following the link, Hungarian notation is a convention that suggests adding a prefix to a variable name to identify the variable's type, eg "qRecords" instead of just "records", or "sFirstName" instead of just "firstName".

Update:

This article addresses the usage of "Systems Hungarian Notation" not "Apps Hungarian Notation" (see the distinction in this Wikipedia article: "Systems vs. Apps Hungarian"). Systems Hungarian Notation was not Simonyi's original intent, however it seems to be the one that's been most adopted. That said, I don't think Apps Hungarian Notation has merit either in modern code. Its theory is reasonable, but its approach of using abbrevs. isn't great. If yer going for clean code, then clearly and fully articulate your variable names where you can.

I think this is what Adam Tuttle is alluding to in his comment below, but I don't think he quite nails it.

AC 2016-12-30

A quick aside: either "qRecords" or "records" is a really crap name for a recordset, unless the data describes your old vinyl collection. ALL compound data structures are "records" really. Your variable name should reflect the data, not its structure or where it came from (eg: the database).  I say this only because I see a lot of code with variables like that.


Anyhow, a quick summary of likely prefixes would be as follows:

Data Type Prefix Example
string s variables.sName = "Zachary"
list l variables.lColours = "red,green,blue"
integer i variables.iAge = 42
float f variables.fRatio = 3.1415
boolean b variables.bShowHeader = true
array a variables.aPeople = ["Adam", "Zachary"]
date d variables.dBirthday = 2011-03-24
query q variables.qPeople
struct st variables.stParams
xml x variables.xAddress
wddx w variables.wInvoiceLines
instance of an object o variables.oInvoice
(this is a bit plagiarised from my workplace, but... err... yeah well OK you caught me there [gallic shrug]).

I did my formal programming education back at the beginning of the 90s, with a lot of focus on C (and - chuckle - COBOL). One of the recommendations made in the C classes was to use Hungarian notation to make more clear what variables represented. The practice kinda stuck with me. I think this is at least partially due to my nature being slightly one of "a place for everything, and everything in its place", and I like rules, and I have had a tendency to place adherence to the rules above giving thought to whether the rule is valid ("at all ~", or just in the given context). I've recently found myself reflecting on this - I consider it a significant logic failing in the way my brain works, and is intellectual laziness - so I've been questioning some of my SOPs recently.

Anyway, I bought into the notion that carrying the data type around in the variable name was useful, so even in my home/scratch coding, I use H/N. Equally this wasn't entirely without assessing various nay-saying opinions, and basically disgarding them as facile or specious (which mean much the same thing, I guess) in the context of ColdFusion code - especially as CFML is "forgivingly" typed.

Recently we had a new starter at work: "new to us", not "a newbie", and as with any new starter moving into a senior position (or, hey, any position), he started questioning pretty much everything we do. I think we get some things right in his view, but he did raise a question mark over our usage of Hungarian notation. And for once he made a compelling case against it. When I say "for once", that's not a reflection on how compelling his cases usually are, I mean its compelling in the context of the other cases against Hungarian notation.

Basically it boils down to the notion that one doesn't actually need to know the type of the data until one comes to use it. And then the context of how it's being used will explain what the data type is. Or that - even then - one really didn't need to know that info all the time. For example, given a variable "invoiceLines", what data type is it? One can't say. But what can one say about it is:
  • they're invoice lines;
  • there's clearly more than one of them (the names is plural)...
  • ... so it's a collection of some sort.
That's without any indication of data type; is is - however - a fair appraisal of what's going on.

But let's pretend we're looking through some code, and we're still not savvy as to the data type of these invoice lines. And all we have to go on is:

invoiceLines = invoice.getInvoiceLines();


We need to do stuff with the variable, so need to know what data type it is. OK, if you just made that "get" call you must've had a reason to do so, and you looked up the API to see what method to call, and should have paid attention to the method's return type. So you should already know.

What if it was already being set, and you just need to do stuff with it? Well the variable must've been created for a reason. Look at the code nearby:

numberOfLines = arrayLen(invoiceLines);

...it's an array.

numberOfLines = invoiceLines.recordCount;

It's a query.

numberOfLines = invoiceLines.getLineCount();

It's an object.

Right, there you go: when the variable comes to being used, one can generally identify what type it is by how it's being used. If it's not being used adjacent (ie: within a few lines) to where it's being created, your code probably needs refactoring: why is it being created if it's not being used?

If you can't tell even after this point just dump the thing out and then you know. Write your code and then your code will be clear to the next person add to what the type is.



So far this was all just an intellectual exercise, and I have no control over the code I write in this regard during my day job but I'm gonna drop H/N from my own coding. I've not used it in my sample code on this blog, and I don't think it's suffered any readability issues at least in that regard.

What are your thoughts on this topic (and the readability of my code, too, for that matter)?

I've had commuting dramas this morning: the tube was down at my station, so instead of one 30 min tube journey on s single line all the way to the office; it's been bus, train, tube, and had taken an hour now. Still: enough time to write this blog entry I guess (on my phone... :-S), but now I need to crack on with some work.

[24 hours pass]

Bloody hell. Yesterday was a bit or a 'mare, and I didn't get a chance to proofread this and press "send".  Then I had to go to the pub with the lads because we all deserved a pint, then 4022 pints later I got home, and collapsed in a heap.  Now it's Saturday morning and I've just had a chance to proofread this, and am about right to press "send".  Am very pleased, btw, that I am off to watch some Olympic boxing (of all things... I actually have no interest in boxing.  Or any knowledge about it at all, other than it involving people bashing the sh!t out of each other.  Should be fun) today.

Righto.

--
Adam

Thursday 2 August 2012

Custom Tags: Looping

G'day
Here's an unpopular / unloved topic: custom tags. I dunno if you're like me (poor you if you are ;-), but I spend most if my time these days writing the business logic parts of our app, and I certainly enjoy that part of my work more than the "presentation layer" stuff. I just find doing all the front-end stuff like the mark-up and styling it according to sometime else's idea of what looks good to be the tedious part of my work. I much prefer working on files that have a CFC file extension than CFM.

That said, one of the good things about ColdFusion is this whole mashing-up CFML and markup thing that ColdFusion makes so easy. However I think "ease of doing something" often leads to rubbish code: just because one can do something doesn't mean one should do it. Because it might not be a very good approach to things when one takes a broader view of things. To this end, I'm very keen on separating concerns into model, view and controller logic, whether it's done via a framework, or just a mindset and following some convention.