Friday 29 November 2013

Unit Testing / TDD - continuing the tests for on() and trigger()

G'day:
I was getting into a rhythm with my TDD cycle this afternoon... test... refine... test... refine... here's what I was doing. Well: after the obligatory recap links (/SEO bait):

Do you know what? I am actually enjoying writing this code. And I'm now past the bits I already knew I had to write (and had the code pretty much already written in my head), so I'm doing really really TDD now. On with the show...

Unit Testing / TDD - getting stuck on how / what to test (part 2/2)

G'day:
Today I'm resuming where I left off yesterday, but first the obligatory links to the rest of the series so far:
Yesterday I questioned how thoroughly I should test return values from functions. Today I am completely flummoxed as to how I test something at all. Spoiler warning: I never worked it out.

CFML: <cfexit> doesn't quite behave how it's been documented to

G'day:
<cfexit> isn't a tag I have call to use very often. Its primary use is in custom tags, and our coding standard at work prohibits the use of custom tags (I did not write the coding standard, and I do not agree with this position, but hey). I looked at the <cfexit> tag's use within custom tags ages ago, when I first started this blog (Custom Tags: Looping).
As far as I know <cfexit> has never quite behaved the way it is documented to, when used outside of a custom tag. The docs claim that outside of a custom tag, it acts like a <cfabort>, ie: aborting processing altogether. I have never known it to behave this way; what it instead does is simply exit the current file. However processing continues in any "outer" files that had called in the exited one. Huh? I mean like this:

<!--- testExitOuter.cfm --->
Top of testExitOuter.cfm<br>
<cfinclude template="testExitInner.cfm">
Bottom of testExitOuter.cfm<br>

<!--- testExitInner.cfm --->
Top of testExitInner.cfm<br>
<cfexit>
Bottom of testExitInner.cfm<br><!--- should never get to this --->

On all three of ColdFusion, Railo and OpenBD, the behaviour here is the same:

Tuesday 26 November 2013

Random idea: get rid of the need to specify a variable's scope

G'day:
This idea popped into my head the other day when looking at some of my colleague's C# code, and noticing at how nicely uncluttered it is. A good part of this was the fact they don't need to deal with scopes, so they don't need to mention them. But this got me thinking... why do we need to mention them either?

Sunday 24 November 2013

Can a function expression circumvent closure?

G'day:
I'm stumped. I "need" to have a function expression that can reference the context it's being executed in as well as the context it was declared in. And I can't work out how. I suspect this is because of one of two reasons:
  1. I'm thick;
  2. it's not possible.
(I am not suggesting those are mutually exclusive options).

Saturday 23 November 2013

How to see the Java that your CFML compiles down to

G'day:
This is in response to a question Upendra asked on my earlier article "CFCamp: <cfprocessingdirective> and how not to use it". Within that article I said this:

This results in being compiled to:


this.MSG.set("??, ?????, ????? ???? ??? ???? (????) – ??????!");

Upendra's question is: "how do I know what it compiles to?". Good question.

First some history. Back when ColdFusion ported onto Java in CFMX 6.0, it went from being an interpreted language to being a compiled one. Not compiled to a native executable like C code would be, but compiled into Java bytecode that is then executed by the JVM. Your CFML itself is not executed, it's just an intermediary language between you and the JVM. Note: OpebBD is still interpreted, but ColdFusion and Railo CFML are both compiled.

Initially on CFMX 6.0 the CFML was translated into Java source code, then that was compiled. If one looked in the cfclasses dir (C:\apps\adobe\ColdFusion\10\cfusion\wwwroot\WEB-INF\cfclasses for me), one could see the .java files appearing as you browsed to a .cfm URL, and then being replaced by .class files shortly afterwards. This process was as slow as a dog, and by the time 6.1 (or perhaps even update 3 of 6.0?), the intermediary step to Java source had been scrapped, and the CFML was compiled straight to bytecode. Much quicker.

Friday 22 November 2013

CFML: Slightly interesting (?) but mostly pointless exercise with inline function expressions

G'day:
I was watching Blow-up and Dead Man Down with one eye on the TV screen and one eye on the code screen last night (actually all I have is a laptop, so it was different halves of the same screen, but hey), and I came to be thinking about some Ruby, and wondered how it could work in CFML.

Yesterday one of my colleagues (Chris) said something curious: that he doesn't "approve" of the ternary operator. I think it's a fine construct if used with caution... the caution being "the resultant code must still be easy to read" (so the same as with any code, really). IE, this sort of thing is fine:

result = randRange(0,1) ? "heads" : "tails";
writeOutput(result);

This, however:

H = (
    C == 0 ? null :
        V == r ? (g - b) / C :
            V == g ? (b - r) / C + 2 :
                (r - g) / C + 4
);

Is a shooting offence. Even if one only considers the ternary operator usage, and ignores the poor variable-naming (I lifted this from Stack Overflow: "A somewhat painful triple-nested ternary operator").

But I like the notion of having an conditional statement which is an expression.

In Ruby, everything is an expression, so every statement "returns" a value. Even an if statement. One can do this:

result = if Random.new().rand(0..1) == 1
    "heads"
else
    "tails"
end
puts result

In this case the value "returned" from an if statement is the last expression from within whichever of the true or false block was executed. So result ends up containing one of "heads" or "tails".

I thought it'd be handy to have an equivalent construct in CFML, where one could have an if() function, which would work like this:

result = if (randRange(0,1)){
    return "heads";
}else{
    return "tails";
}
writeOutput(result);

However this doesn't follow normal function syntax as it requires two code blocks (one for true, one for false), not just the usual one. So perhaps not completely straight fwd for the Railo or Adobe bods to implement.

Then it occurred to me... it's actually very bloody easy to implement in CFML, using inline function expressions. Here's a proof of concept:

function _if(required boolean condition, required function _true, function _false){
    if (condition){
        return _true();
    } else if(structKeyExists(arguments, "_false")){
        return _false();
    }
}

This mimics if / if/else. It's very straight forward really: instead of having blocks, it just takes a function or two, and calls one of them based on the results of the condition.

And an example calling of this using inline function expressions demonstrates the code kinda mimics an if() block visually, but it has the benefit of returning a value:

result = _if(
    randRange(0,1),     // condition
    function(){         // true
        return "heads";
    },
    function(){         // false
        return "tails";
    }
);
writeOutput("#result#<br><hr>");

One good side effect of this approach - and it's probably more handy than the construct itself - is that because the true/false blocks are functions, any function-local variables within them are indeed local to the function block itself, and do not pollute the calling scope. This would help keeping the variables-scope uncluttered in larger tracts of code. Demonstration:

scope = "calling code";

_if(
    randRange(0,1),
    function(){
        var scope = "true block";
        writeDump(var=[{variables=variables.scope}, {local=scope}], label="Within true block");
    },
    function(){
        var scope = "false block";
        writeDump(var=[{variables=variables.scope}, {local=scope}], label="Within false block");
    }
);

writeDump(var=[scope], label="Back in calling code");

This outputs:

Within true block - array
1
Within true block - struct
VARIABLEScalling code
2
Within true block - struct
LOCALtrue block
Back in calling code - array
1calling code

See how the function-local scope variable a) didn't interfere with the calling-code's variable; b) is gone after the function exits.

This could be beneficial.

JavaScript has a concept of  self-executing anonymous functions, which are handy for much the same reason. I've raised this as an E/R for ColdFusion, but it's been deferred: 3346435.

Continuing on this tangent, I figured I could perhaps contrive a looping construct too: one that works like a for() loop, but returns a value. And it was easy enough, using exactly the same technique:

function loop(function before, function condition, function afterEach, function body){
    if (structKeyExists(arguments, "before")){
        before();
    }
    if (!structKeyExists(arguments, "condition")){
        condition = function(){
            return true;
        };
    }
    while (condition()){
        var result = body();
        afterEach();
    }
    return result;
}

The arguments here mimic how an indexed for() loop works:
  • before() is called once at the beginning of the process;
  • condition() is checked at the beginning of each iteration;
  • afterEach() is called after each iteration;
  • body() emulates the code block.
Indeed it's slightly better than a for() loop in that it allows more than one expression in each of the first three arguments, whereas the native version only permits one.


Thursday 21 November 2013

Can you run some code for me please?

G'day:
I have a quick favour to ask.

<cflocation>

G'day:
This is not the article I started writing this morning.

Closed/deferred/NotEnoughTime, eh?

G'day:
I was goaded (OK, not really) into this by some observers on IRC. This is in regards to ticket number 3123145.

Adobe, you really don't "get" how client-liaison works, do you?

Wednesday 20 November 2013

Unit Testing / TDD - getting stuck on how / what to test (part 1/2)

G'day:
Today I'm gonna go over some head-scratching (some of which is still bugging me) I did on the weekend. I kinda got stuck with how I should be testing something, and this raised questions as to whether I even should be testing something. It's a reasonable exercise to go through, so I will document it here. First: recap.

This is an ongoing series of articles about unit testing and TDD (and will diversify from there as I progress), with - so far - five previous entries:

Ways to call functions in CFML

G'day:
We've got Brad Wood and David Epler to thank for this article (sorry that Twitter presents information back to front, so start at the bottom and read up. Like one never generally would):




Monday 18 November 2013

Request for clarification on some stuff from Adobe

G'day:
I've encountered some questions regarding the recent update, and have questions of my own... and I don't know the answers. So I'm gonna raise 'em here and bring 'em to Adobe's attention and see if we can get some answers. It's nothing major, and for once not a gripe (well... not on the scale that I often gripe, anyhow...).

Unit Testing / TDD - more tests, more development

G'day:
So enough prattling about <cfclient> for the time being (and, no, I haven't finished with that topic, but Adobe have demonstrated themselves up to the task of ridiculing themselves without my help at the moment, so I'm just leaving them to it). Back to something more useful: TDD / unit testing.

So far I've written four articles in this series:

Only the third of which had any code in it: the rest was just general discussion. Today I'm going to continue developing this createEventObject() idea I've had, using TDD.

Friday 15 November 2013

Simon Baynes

G'day:
Just very quickly. My mate / colleague Simon finished at HostelBookers.com today, and moved on to a new position. It's not for me to share the details, but it sounds like a really good gig, and Simon's a good fit for it.

Simon was the Technical Architect at HostelBookers.com, and was responsible for hiring me. I did not report to him directly, but we worked reasonably closely on various projects over the last almost four years.

Synthesised accessors & variable scope

G'day:
Whilst vegetating at home last night, I had a look at some code Ryan Guill had posted on the ColdFusion IRC channel. It relates to ColdFusion's ability to automatically create accessors on CFC properties, if told to do so. He was seeing some "unexpected" behaviour.

London Railo Meetup, Weds Nov 27

G'day:
I'd just like to encourage people in the London / SE part of the UK to come along to the next London Railo Meetup: "Debugging Railo and general Railo discussion". It's - again - being held at the Pixl8 offices in Clapham / Wandsworth (very accessible via various transport links).

The topic for this meeting is summarised thus (from the page linked-to above):
We are going to get the opportunity to review how to debug Railo.

Mark Drew from Railo has agreed to run through the layout of the code, working with eclipse and debugging.

Time permitting we could select some bugs or features from the Jira tracker and talk about how we could approach them.

Thursday 14 November 2013

Weirdness with installing ColdFusion 10 update 12

G'day:
A coupla days back update 12 came out for ColdFusion 10: "ColdFusion Help / ColdFusion 10 Update 12". I had some installation "challenges" with it, and have now heard of two other people with the same experience.

Tuesday 12 November 2013

Locking investigation for Brad

G'day:
I will admit I'm not in a blog mood at the moment, hence the silence over the last few days. However Brad Wood has asked for a second set of eyes on some code of his, so here are my findings.

Friday 8 November 2013

Vote for CF.Objective() presentations... even if you're not attending

G'day:
There was chatter doing the rounds on Twitter a few days back that there's perhaps not as much community uptake as far as voting for what presentations will be given at CF.Objective() 2014.

I've voted for a few presentations, even though I'm unlikely to be attending the conference. I think it's important and useful information for the conference organisers to know what sort of thing the broader community is interested in as far as technology topics go.

Go have a look at the cf.Objective() Call For Speakers 2014 page, and vote for stuff you find interesting. Unfortunately the UI is a bit obstructive, and not a great UX, but stick with it. Also worthy of note is that a lot of people seem to be missing that there is a horizontal scroll bar... most of the presentations are listed off the right-hand side of the screen. So vote 'n' scroll.

As a taster / tempter, here's the list of presentations I'd attend if I was going (in order of left to right ;-)

ColdFusion Builder comes to Linux

G'day:
Real quick... this morning Matt Gifford blogged "ColdFusion Builder Linux Support", observing:

Many developers have been asking for ColdFusion Builder support for Linux for a long time, [...]

Initially reported in 2011, “ColdFusion Builder 2 Won’t Run Under Linux” (bug #2832512 ) has been commented on by a fair number of people (24 is a fair number in my book), but sadly the ticket has been closed and the reason marked as “not enough time”. Say what?
However...

Wednesday 6 November 2013

<cfclient>: worrying discussion

G'day:
The more I read about <cfclient>, the more the alarms bells change from tending towards air raid sirens, and more like the horns of the Rapture (or if you prefer). Here's a series of comments on the Adobe ColdFusion Blog about how looping over arrays will "work" in <cfclient>.

ColdFusion: <cfclient>: from a pig's ear, a silk purse could rise?

G'day:
I've got two muses today: Dan Fredericks who had a go at me yesterday about being a big meany about <cfclient>: and Sean for giving me the "penny-drop" moment. I think the concept of <cfclient> is salvageable. Just the concept. Not the implementation. Nuh-uh.

Firstly Dan had a half-way decent point, as articulated on Twitter:


And the conversation went on from there (you'll need to look it up). In theory Dan is right: constructive criticism is better than criticism. However I really don't actually see anything that's good to a useful degree about <cfclient>. Otherwise I would have mentioned it. Here's the best constructive criticism I can muster for <cfclient>:

Tuesday 5 November 2013

<cfclient>: source code of CFSummit app

G'day:
Being true to his promise, Rakshith (well: actually it was Ram who posted it, but Rakshith announced it on Twitter) this morning posted the source code for the CFSummit mobile app, which was written using CFClient. I hastily downloaded it and had a quick look through the source code. Fairly rapidly reaching a conclusion.

Monday 4 November 2013

My readers doing my work for me

G'day:
Sometimes the comments on this blog are better that the articles themselves. I've elevated one of Sean's comments to a full "guest" article a while back: "An Architect's View: Sean's feedback on my recent article about ColdFusion interfaces", and over the weekend my mate Simon put his oar in on one of my recent Unit Testing / TDD articles to feedback some useful info to one of my other regular commenters, Bruce. What Simon says is very true, and something I think all devs should bear in mind. It's got nothing to do with testing or TDD, but is all about how we ought to be approaching our work, as professionals. Simon's comment:

Sunday 3 November 2013

Unit Testing / TDD - why you should bother

G'day:
OK, I actually showed some code in the last entry in this series, but now we're back to me spouting rhetoric (read: waffling on). This stems from Andrew Scott making a very good observation about a benefit of unit testing (not so much TDD) in a comment in my last article:
Adam, can I add another under estimated use for TDD. Apart from the bit you touched on about refactoring. But there comes a point when one will need to migrate to a newer version of ColdFusion or Railo, and this would help identify migration problems as well.

And Andrew is dead right.

Saturday 2 November 2013

Unit Testing / TDD - MXUnit and test scenario

G'day:
OK, so I've prattled on a coupla times about TDD and unit testing from a theoretical point of view:

I think today I'll actually get around to writing some code.

This assignment I'm setting myself could all end in tears, as I'm really putting my money where my mouth is... not only am I going to take a straight TDD approach to writing these tests, I'm also actually doing the design of the function I'm testing as I go too. I have just an idea of how something might be able to work, but I don't actually know if it will be viable yet: I've gone over it in my head, but I've not written any code yet. Other than the test rig.

Similar to my code deferral function from a coupla weeks ago ("Threads, callbacks, closure and a pub"), which handles calling blocks of code in an asnyc fashion, running callbacks at various milestones in execution, I started to wonder if I could write an event-driven system in a single function too. Only a proof-of-concept sort of thing, and most as an exercise in leveraging closure in a real world way (most closure examples I've seen don't actually leverage closure, so I'm all for examples that do), and just to see if the thought exercise can pan out into real code.

My theory is I should be able to have a function which returns a coupla other functions which handle event triggering (trigger()) and listening (on()), and because they'll implement closure, they'll remember the main function's variable context, so will both be able to communicate with an central event registry.

Friday 1 November 2013

CFML: More on inappropriate use of <cfinclude>

G'day:
I didn't expect to be revisiting this topic - let's face it, it's definitely "slow news day" material - but Ryan Guill, who I chat to on IRC, put me onto this one, and it was intriguing enough to follow-up.

And it's a slow news day.

So previously I wrote this article: "<cfinclude> and JavaScript", which discussed what happens when a non-CFM file gets included.

Disclaimer:

Just in case it's not abundantly apparent from the title of the article or the observations I make as I go: I do not mean this exercise to suggest I recommend the practice detailed below.


Ryan's variation on this is what happens when including a CFC file. Interesting. So I tried that: