Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

Thursday 7 April 2016

Maintaining untested code, and mocking too much when backfilling test (with JavaScript & Jasmine)

G'day:
Here's another example of me doing something wrong. Well: there's a litany of wrongness in this exercise, and I'll show the whole thing from start to finish. But this all stems from me ballsing something up.

Caveat

Be warned: there's a lot of code in this one, but the main point is the volume of the code I found necessary to write to test and fix a tiny bug. You don't need to worry too much about the content of the code... the important part is the line number at the bottom of the file.

The background to this is that I was helping a former colleague with some CFML code ("just when I thought I was out..."), and it was whilst reconfiguring stuff, I got hit by a trivial bug... the resolution to which is the basis of this article. I could not use their actual code in the article here due to NDA reasons, but I also didn't want to be discussing CFML either. So I've undertaken to "refactor" the entire thing into JavaScript instead (I don't mean their code; I mean a version of their logic which I will discuss here). The JavaScript code closely resembles the actual code I was looking at, but obviously some of the approaches to doing things needed to change, and I've repurposed some of the elements of it to better suit what I'm discussing. The logic and "code distribution" is about a 95% match to the original case though, I think. Also I'm using Jasmine to do JavaScript testing in this example, and I was using a CFML-based solution for the original code. This is irrelevant to the situation as both work mostly the same way, and produce similar amounts of code for the equivalent testing and mocking tasks.

I will start by saying that the code is a product of its time and their coding policies at that time. I'm happy to say they've since revised their approach to things, and are fine-tuning it as they go. the code base - like all others - is an evolving beast. And indeed to be fair to them: it's a testament to their evolving coding process that I'm able to write this article.

Background

This code comes some a project which is built with an MVC framework: the details of which are irrelevant to this article. They also use a dependency injection container to handle their dependencies.

The code in this article is part of the TranslatorProvider, which creates a TranslationService, and loads it with translations originally stored in some (optionally cached) data repository. The implementation details of these are not relevant here. These translations are for on-screen labels and other text. The bit of code I'm focusing on in this article is the logic to load the translations from storage. They don't quite follow the service / repository model I have presented here, but it's the same beast by different names, and the service / repository model suits me better so that's how I've labelled things here.

My mate's organisation produces numerous small websites, all of which are multi-lingual, and all share this code.

New site

They're in the process of building a new site, which is where I came in. We'd been piggy-backing onto the translation dictionaries for one of the existing sites whilst we were protoyping. the onscreen-labels we need to translate follow the same general theme, so it's workable - during development - to use one site's translations for another site, to a point (some translations don't work, but that's OK). It took a while to prepare the dictionaries for the new site (a different team was doing that), but when they came back from the translator I switched the dictionary bundles over.

I did this, and the whole site broke. Switched the dictionary back to the older one: site worked again. Switch it forward: site broke. OK: there's something wrong with our translations. Oh, I switched the translations on another one of their test sites - one I knew in which all the work was sound (ie: not written by me) - and that site broke, Harrumph. What is it about some translation dictionaries that can break a site?

Bug

I dug into the translator code and quickly (well: it took a few hours) found the problem:

var translations;

// ...

for (var key in rawTranslations.primary){
    translations.primary = translations.primary || {};
    translations.primary[key] = rawTranslations.primary[key];
}

for (var key in rawTranslations.secondary){
    translations.secondary = translations.secondary || {};
    translations.secondary[key] = rawTranslations.secondary[key];
}

var ttl = config.ttl;

cacheService.put(cacheKeyPrimary, translations.primary, ttl);
cacheService.put(cacheKeySecondary, translations.secondary, ttl);


Can you see it?

What happens if - as it is in our case - one hasn't got any secondary translations? translations.secondary never gets created, so that last line will break.

The fix is simply to initialise that object outside of the loop:

translations = {primary : {}, secondary : {}};

Simple.

Well except for one thing. No test coverage. This code was written before they had a TDD policy, so it's got no tests at all. Note that this bug never would have happened had they used TDD when developing this code, because the very first test would have been with empty arrays. I made sure to point this out to them, but they rightfully pointed out when it was written and they now do have a full TDD policy. And that comes into play for my fix: I needed to use TDD for implementing my fix.

Back-fill

My policy with maintaining untested code using our new TDD approach is that I will not back-fill all missing tests. I will only implement the minimum testing needed for the case I'm fixing. if I have time I'll make shell tests with a "skip" in them so the missing coverage gets flagged in the test run, but I'll not bother too much other than that.

So in this case all I need to test is that if the secondary object is null, that null gets send to the cache. Simple.

Or is it?

Unclean code

Unfortunately this code was also written before the era of "write Clean Code", so the function itself is doing way too much. It's 50 lines long for a start, which is a red flag, but one can easily see different sections of processing in it too, so it violates the "functions should do one thing" rule. This becomes a problem because even to test my wee fix, I need to make sure the preceding 40-odd lines of code don't break or do the wrong thing before I get to my line of code. And as this code leverages a fair number of dependencies, there's a bunch of mocking work to do before I can even get to what I want to test. Note: the dependencies in the original code were handled differently in that they passed the DI container into this provider, and just plucked out whatever they need when they need it. I cannot bring myself to show code like that (even for a blog article), so I've broken them down into multiple dependencies with specific roles. The logic is the same, and it produces the same amount of code (both sample code and test code).

If the code was Clean and I was just looking at a function that map the source objects(s) into the target objects(s), then my test job would be easy. But no.

Let's look at what stands between me and where I can test the results of my line of code. I've highlighted what needs mocking:

if (!requestService.isTranslatorEnabled()){
    return;
}

var currentLocale = requestService.getLocale();

var cacheKeyPrimary = getCacheKey("primary", currentLocale);
var cacheKeySecondary = getCacheKey("secondary", currentLocale);

var okToGetFromCache = cacheService.isActive()
    && cacheService.exists(cacheKeyPrimary)
    && cacheService.exists(cacheKeySecondary);

var translations = {};
if (okToGetFromCache) {
    translations.primary = cacheService.get(cacheKeyPrimary);
    translations.secondary = cacheService.get(cacheKeySecondary);
}else{
    var rawTranslations = {
        primary : translationRepository.loadBundle("primary", currentLocale),
        secondary : translationRepository.loadBundle("secondary", currentLocale)
    };

    for (var key in rawTranslations.primary){
        translations.primary = translations.primary || {};
        translations.primary[key] = rawTranslations.primary[key];
    }

    for (var key in rawTranslations.secondary){
        translations.secondary = translations.secondary || {};
        translations.secondary[key] = rawTranslations.secondary[key];
    }

    var ttl = config.ttl;

    cacheService.put(cacheKeyPrimary, translations.primary, ttl);
    // [...]

  1. requestService.isTranslatorEnabled
  2. requestService.getLocale
  3. cacheService.isActive
  4. translationRepository.loadBundle
  5. config.ttl
  6. cacheService.put
But that's not all. The function has to complete without error. So I also need to mock this lot:

var translationService = translationFactory.getTranslator();
var arrayLoader = translationFactory.getArrayLoader();

translationService.load(arrayLoader.load(translations.primary), 'primary', currentLocale);
translationService.load(arrayLoader.load(translations.secondary), 'secondary', currentLocale);

  1. translationFactory.getTranslator
  2. translationFactory.getArrayLoader
  3. arrayLoader.load
  4. translationService.load

What a nightmare. If this code was written cleanly, I'd simply have to test a method that takes a coupla arguments and returns a value. Simple.

Thursday 17 March 2016

JavaScript: clarifying in my head this and that and proxies

G'day:
This came up in our team meeting the other day, We write a reasonable wodge of JavaScript, and its of varying degrees of veneration, quality and uniformity (if that last one isn't an oxymoron). One of the quality-variations we have is how we handle our event handlers specifically in the context of how they access the parent-object's this reference. Now I haven't read-up thoroughly on how this works in JS, but I know enough to get by. Until I don't. I think many people are like this. Anyway, within an object, this refers to the object itself. Within an event handler, it refers to the object which caused the event to occur, and the handler to run. If the event handler method is in an object, and it needs to access both the object firing the event and the object the handler is in, one cannot use this to reference both of them.

That's be easier to visualise in code - and I will - but I'll finish some framing first. In our code base we use a mixture of a coupla different approaches:

  • use something like that = this to make a second reference to the object's this so the handler can reference this to refer to the object firing the event, and that to refer to its parent object. Bleah. That just reeks of "hack"
  • use JQuery's proxy() method to re-task the function's this to be its parent object's one, rather than the event-firing object.
Personally I prefer the latter version. It seems less hacky.

Anyhow, the meeting discussion got snarled up with the idea that if we use the proxy to re-purpose this, we then can't use this to reference the object firing the event, which we often have to do at the same time. This made us go "hmmm...", and then we ran out of time to come up with a satisfactory answer, and moved on.

I kept thinking about this and then kicked myself cos it was obvious. this in the context of the event handler is pretty much just syntactical sugar as far as I can tell, and it's all a bit magical. As well has having that event object exposed via this, it's also obviously exposed in the event argument that's passed to the handler. We don't need to use this to reference the event-firing object. Indeed IMO it's cleaner if we simply don't do that.

I had to get this clear in my head, so jotted some code down. Which is here:

<!doctype html>

<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Event variables</title>
    <script src="https://code.jquery.com/jquery-2.2.1.min.js"></script>
</head>

<body>
    <button id="noProxy">Event handler without proxy</button>
    <button id="proxyRef">Using proxy reference</button>
    <button id="jqueryProxy">Event handler using jquery proxy</button>
    <button id="usingBind">Event handler using bind</button>

    <script src="./Page.js"></script>
    <script src="./init.js"></script>
</body>
</html>

So I've got some buttons which I can push.

And here's Page.js:

Page = function(page){
    this.page = page;
};

Page.bindHandlers = function(page){
    $("#noProxy").on("click", page.clickHandlerWithoutProxy);
    $("#proxyRef").on("click", page.clickHandlerWithProxyRef());
    $("#jqueryProxy").on("click", $.proxy(page.clickHandlerUsingJQueryProxy, page));
    $("#usingBind").on("click", page.clickHandlerUsingBind.bind(page));
};

Page.prototype.clickHandlerWithoutProxy = function(e){
    console.log("'e.target' refers to the button that triggered the event: " + $(e.target).text());
    console.log("'this' also refers to the button that triggered the event: " + $(this).text());
    console.log("Cannot reference 'this' from the Page object");
};

Page.prototype.clickHandlerWithProxyRef = function(){
    var self = this;
    return function(e){
        console.log("'this' refers to the button that triggered the event: " + $(this).text());
        console.log("'self' still refers to the Page object: " + self.page);
    }
};

Page.prototype.clickHandlerUsingJQueryProxy = function(e){
    console.log("'e' refers to the button that triggered the event: " + $(e.target).text());
    console.log("'this' still refers to the Page object: " + this.page);
};

Page.prototype.clickHandlerUsingBind = function(e){
    console.log("'e' refers to the button that triggered the event: " + $(e.target).text());
    console.log("'this' still refers to the Page object: " + this.page);
};


And init.js:

$(document).ready(function(){
    page = new Page(&quot;Home page&quot;);
    
    Page.bindHandlers(page);
});

Page defines a sorta class (as much as JS can), and within that there's a method to bind some event handlers to those buttons, and then the handlers themselves. Each bind and handler uses a different technique to access the event-firing object or the page object.

In clickHandlerWithoutProxy() we don't try to handle anything special... it just demonstrates that e.target refers to the object that the event was fired by, and also that this points to the same thing.

On the other hand clickHandlerWithProxyRef() exposes both the Page object's this (via a proxy variable self (we variously use that or self or probably _this too), and then the event handler's this still points to the event-firing object. Note how here I'm binding a method call to the event handler, and that method returns the actual handler, having first created that proxy self variable. This is an example of closure at work.

JQuery rescues us in the third option - clickHandlerUsingJQueryProxy() - $.proxy() let's one specify a different context for the event handler's this. This is all very cool and easy to do. It's predicated on using JQuery though. Which we do. And to access the event-firing object, we use the event argument passed into the handler, which has a target property which is that object. So we are accessing the handler's own object via this, and the event's object via target. Cool. And also doesn't have any surprises in the code: this always means the same thing, as is usage of e.target.

The last option - clickHandlerUsingBind - eschews JQuery and does the same thing using native JavaScript: the bind() method of the function object effects the same thing $.proxy() does. This was my research this morning, when I decided to find out how $.proxy() works. I think there is some browser compat issues with this... I read something about in IE8 needing to use a different approach. I still need to read up on that.

I'd err towards using the last approach, just using JS, but I think perhaps the JQuery approach is perhaps the safest here.

As I will say when I write about JavaScript, I am no expert in it at all. I know just enough to get by - this annoys me but it's the truth - so if I've got anything horribly wrong here, please do let me know!

Back to PHP...

--
Adam

Tuesday 19 January 2016

Floating point arithmetic with decimals

G'day:
As a human... what is the value of z, after you process this pseudocode with your wetware:

x = 17.76
y = 100
z = x * y

Hopefully you'd say "1776". It was not a trick question.

And that's an integer, right? Correct.

CFML

Now... try this CFML code:

x = 17.76;
y  = 100;
z = x*y;

writeOutput(z);

1776 So far so good.

But what about this:

writeOutput(isValid("integer", z));

You might think "YES" (or true if yer on Lucee), however it's "NO".

And this is where young players fall into the trap. They get all annoyed with isValid() getting it wrong, etc. Which, to be fair, is a reasonable assumption with isValid(), but it's not correct in this instance. It's the young player who is mistaken.

If we now do this:

writeOutput(z.getClass().getName());

We get: java.lang.Double

OK, but 1776 can be a Double, sure. But CFML should still consider a Double 1776 as a valid integer, as it should be able to be treated like one. So why doesn't it? What if we circumvent CFML, and go straight to Java:

writeOutput(z.toString());

1776.0000000000002

Boom. Floating point arithmetic inaccuracy.

Never ever ever forget, everyone... when you multiply floating point numbers with decimals... you will get "unexpected" (but you should pretty much expect it!) floating point accuracy issues. This is for the perennial reason that what's easy for us to express in decimal is actually quite hard for a computer to translate into binary accurately.

Aside: we were chatting about all this on the CFML Slack channel this morning, and one person asked "OK, so how come 17.75 x 100 works and 17.76 x 100 does not?". This is because a computer can represent 0.75 in binary exactly (2-1 + 2-2), whereas 0.76 can only be approximated, hence causing the "issue".

The problem really is that CFML should simply output 1776.0000000000002 when we ask it, and it should not try to be clever and hide this stuff. Because it's significant information. Then when the young player output the value, they'd go "oh yeah, better round that" or whatever they need to do before proceeding. CFML is not helping here.

This is pretty ubiquitous in programming. Let's have a trawl through the various languages I can write the simplest of code in:

JavaScript


x = 17.76;
y = 100;
z = x * y

console.log(z);


>node jsVersion.js
1776.0000000000002

>

JS just does what it's told. Unsurprisingly.

Groovy


x = 17.76
y = 100
z = x * y
println "x * y: " + z

println "x: " + x.getClass().getName()
println "y: " + y.getClass().getName()
println "z: " + z.getClass().getName()
println "z: " + z.toString()


>groovy32 groovyVersion.groovy

x * y: 1776.00
x: java.math.BigDecimal
y: java.lang.Integer
z: java.math.BigDecimal
z: 1776.00
>


This is interesting. Whilst Groovy keeps the result as a float (specifically a BigDecimal) - which is correct - it truncates it to the total number of decimal places expressed in its factors. That's how I was taught to do it in Physics at school, so I like this. This second example makes it more clear:

x = 3.30
y = 7.70
z = x * y
println "x * y: " + z

println "x: " + x.getClass().getName()
println "y: " + y.getClass().getName()
println "z: " + z.getClass().getName()
println "z: " + z.toString()


>groovy32 more.groovy
x * y: 25.4100
x: java.math.BigDecimal
y: java.math.BigDecimal
z: java.math.BigDecimal
z: 25.4100
>

In 3.30 and 7.70 there are four decimal places expressed (ie: two for each factor), so Groovy maintains that accuracy. Nice!


Java


import java.math.BigDecimal;

class JavaVersion {

    public static void main(String[] args){
        double x = 17.76;
        int y = 100;
        System.out.println(x*y);
        
        BigDecimal x2 = new BigDecimal(17.76);
        BigDecimal y2 = new BigDecimal(100);
        System.out.println(x2.multiply(y2));
        
    }
}

Here I added a different variation because I was trying to see why the Groovy code behaved the way it did, but it didn't answer my question. I suspected that perhaps it was a BigDecimal thing how it decided on the accuracy of the result, but it wasn't:


>java JavaVersion
1776.0000000000002
1776.000000000000156319401867222040891647338867187500

>

This is a good demonstration of how a simply base-10 decimal fraction is actually an irrational number in binary.

Sunday 17 January 2016

Stepping looping

G'day:
Yeah, this is an odd thing to write about, and there's no trick to it: I really do mean this sort of thing:

for i=1 to 10 step 2

I got to thinking about this because of a comment from Chris Dawes on my article Lucee 5 beta: <cfloop> tweak, in which he sung the praises of the CFML tag equivalent of that general construct:

<cfloop index="i" from="1" to="10" step="2">

This is fine for a view, but I'd steer clear of it in my business logic. But what would I use instead? The obvious answer is this:

for (i=1; i <= 10; i+=2)

But these days I try to eschew generic looping like that, in favour of a more purposeful iteration exercise using iteration methods. If I was iterating a collection to remap data, I'd use map(); if I was doing so to translate the collection data to another data structure or object, I'd reduce(); if I was getting rid of stuff I'd filter(), and - if the language allowed it - if I was checking to see if one or any of the collection elements fulfilled some criteria, I'd use some() or every(). It's really seldom that one wants to loop "for the hell of it", if one thinks about it. It's an exercise in processing data or checking data.

Obviously in a view one is likely to be just outputting data from the data collection, so using a general loop is as good as anything. Also if one is skipping records... a stepped general purpose loop is perhaps better than using like an array-based loop and conditionally continuing the loop or some nonsense like that. All good.

But this got me thinking... let's say I was:

  1. writing business logic;
  2. wanting to step over array elements;
  3. still wanted to use array iteration methods.

This is more a mental exercise than a programming one, but it just happened to pique my interest.

CFML

In CFML this is dead easy. Here's an example:

numbers = ["tahi", "rua", "toru", "wha", "rima", "ono", "whitu", "waru", "iwa", "tekau"];

oddNumbers = numbers.filter(function(_,i){return i mod 2;});

writeDump(oddNumbers);

Here I'm using ColdFusion 12's CLI, and the results are as follows:

C:\src\cfml\languageComparison\steppedLoop>cf cfmlVersion.cfm
array

1) tahi
2) toru
3) rima
4) whitu
5) iwa

C:\src\cfml\languageComparison\steppedLoop>

filter() allows us to create an array of every second element simply by doing the usual mod operation. This gives us a new array.

If we wanted to actually render the elements as a string, we'd just chain a reduce() call onto that:

oddNumbersAsString = numbers.filter(function(_,i){return i mod 2;}).reduce(function(combined, oddNumber){
    return "#combined##oddNumber##chr(10)#";
}, "");
CLI.writeLn(oddNumbersAsString);


C:\src\cfml\languageComparison\steppedLoop>cf cfmlVersion.cfm
tahi
toru
rima
whitu
iwa

C:\src\cfml\languageComparison\steppedLoop>

Or, hey: not get so dogmatic about using collection iteration methods, and just leverage a list method:

oddNumbersAsString = numbers.filter(function(_,i){return i mod 2;}).toList(chr(10));

(yields the same output)

I turned my mind to other languages to compare.

JavaScript

Same as CFML really. Just some "spelling" differences:

oddNumbersAsString = ["tahi", "rua", "toru", "wha", "rima", "ono", "whitu", "waru", "iwa", "tekau"]
    .filter(function(_,i){return (i+1) % 2;})
    .reduce(function(combined, oddNumber){
        return combined + oddNumber + String.fromCharCode(10);
    }, "");

console.log(oddNumbersAsString);

Output:


C:\src\cfml\languageComparison\steppedLoop>node jsVersion.js
tahi
toru
rima
whitu
iwa


C:\src\cfml\languageComparison\steppedLoop>

PHP

PHP is a bit disappointing here for a coupla reasons. Firstly PHP is still at its roots still procedural, so the code is intrinsically more clunky, plus it's collection iteration methodsfunctions aren't implemented that thoughtfully, so I have to jump through some intermediary hoops:
$numbers = ["tahi", "rua", "toru", "wha", "rima", "ono", "whitu", "waru", "iwa", "tekau"];

$indexedNumbers = array_map(null, range(0, count($numbers)-1), $numbers);
$indexedOddNumbers = array_filter(
    $indexedNumbers,
    function($number){
        return ($number[0]+1) % 2;
    }
);
$reindexedIndexedOddNumbers = array_values($indexedOddNumbers);

$oddNumbers = array_map(
    function($number){
        return $number[1];
    },
    $reindexedIndexedOddNumbers
);

$oddNumbersAsString = array_reduce(
    $oddNumbers,
    function($combined, $oddNumber){
        return $combined . $oddNumber . PHP_EOL;
    },
    ""
);
echo $oddNumbersAsString;

The issues here are:

  • we want to filter on the array index position, but PHP doesn't think to pass this to the array_filter()'s callback, so I need to push an index into the data using array_map() and range(). One good thing here is that array_map(), if not given a callback then it just maps all the arrays it's passed together into sub arrays. Which suits my purposes here.
  • Then I can use array_filter() to do the actual filtering, but array_filter() is a bit sh!t for a second time because it leaves a sparse array after it filters. So after I filter I don't have a new array with elements 0-4, I have one with elements 0,2,4,6,8 (!!!!). How bloody stupid is that? I guess this is down to PHP's array implementation being quite rubbish and basically being "kinda an array, kinda a struct, kinda - as a result - neither".
  • I need to fix this by creating a new array with just the values.
  • As I said PHP is procedural, so I can't chain stuff. I could nest it, but that makes for awful, inside-out code. So I use individual statements and intermediary variables.
  • Having filtered I still need to get my data elements back to "normal" by getting rid of the index I embedded in them. Another call to array_map() to undo what I did before.
  • And finally I can reduce things back down to a string.
Way too much horsing around there. Note: I know this is - as a result - a contrived example. There's no way a sane person would do this sort of thing. In PHP, one's better off eschewing the array iteration methods and just using general forEach() loops. Old school, but they work.

Monday 14 September 2015

JavaScript: a eurekaFFS moment

G'day:
This was going to be another "how would you solve this?" code quiz things, but in the end the problem proved to be really a lot easier to solve than I expected it to be, so I'll just use it as a demonstrating of me being daft instead. Oh, and some Jasmine unit tests.

This puzzled stemmed from this article: "Expectation management: mapping a changing array". I was wanted to take an array:

["a","b","c","d","e"]


and pass it through a function and end up with this:

[
    ["a", "b", "c", "d", "e"],
    ["b", "c", "d", "e"],
    ["c", "d", "e"],
    ["d", "e"],
    ["e"]
]

Where each progressive element has the rest of the array that was in the previous element.

My initial - not working - attempt was this:

// closure.js

var letters = ["a","b","c","d","e"];
var remappedLetters = letters.map(function(number,index){
    var localCopyOfTheseLetters = letters.slice();
    letters.shift();
    return localCopyOfTheseLetters;
});

But this demonstrates the issue that I'm altering the array as I remap it, which is pretty poor form. And doesn't work. The "doesn't work" part is the killer there.

So I decided "OK, let's have a quiz how to do this best".

First things first I knocked together some unit tests to make sure the thing works as I develop it:

Sunday 23 August 2015

JavaScript: running Jasmine unit tests from the CLI

G'day:
I can't see as this will be very long as I've not much to say about it, and it was surprisingly quick to sort out once I bothered to do so.

My weekend mission was going to be to start getting up to speed with Clojure, by reading & working through the relevant chapters from Seven Languages in Seven Weeks, but whilst that kept me occupied on my flight from London to Shannon, I didn't really revisit it after that, as I got sidetracked on these Jasmine tests. Well firstly I decided my mission would be to do a Clojure version of my "get a subseries" quiz ("Something for the weekend? A wee code quiz (in CFML, PHP, anything really...)"), and before doing that I wanted to get a working version of the code I discussed in "Some CFML code that doesn't work" working, chosing JavaScript as my control language. And in deciding to do that, I decided not to just copy and paste it into the browser console to test it, I decided to do it properly and do a file-system-based exercise running it via Node (note to Acker: I already use Node. Just sparingly because the need for it doesn't crop up for me that often. You don't actually have any special knowledge the rest of us also don't already have). And if I was gonna do that, then I was also gonna get Jasmine working via Node too, as we actually do have a real requirement for this at work. We have an ever increasing amount of ever increasingly complex JS in our application... and so far not a line of testing gets done on it. We're shifting our mindset to be writing more testable JS: reducing inline callbacks; putting a much of our code in "class" file, and writing small, clean, testable methods an the like all ready for testing... but getting the actual test infrastructure up and running is just not happening.

So, anyway... other than installing Clojure via Leiningen and runing "G'day World" via the REPL, my Clojure investigations didn't move much.

But  I got the JavaScript version of my CFML code running, and also got its tests running via the commandline too. So that's cool.

Saturday 25 July 2015

JavaScript: expectations re-adjusted re Promises

G'day:
First off a proactive apology. I generally sit in the pub on my Saturday afternoons in Galway (every second weekend), and write some ballocks on this blog. I think we're all used to that. I'm doing that now, but prior to kicking off with the writing I have already been sitting around for two hours watching the All Blacks play the Springboks in a hard-fought, narrow-margined 20-27 victory to NZ. And this entailed drinking four pints of Guinness as the build-up and match was under way, and I'm tucking into my fifth now. So f*** knows how coherent this article will be. The up-side is that I wrote the code for this beforehand :-S

OK, so the framing for this article is the previous article: "JavaScript: getting my brain around Promises", and my admission here is that I didn't actually get my brain entirely around JavaScript promises. I set my bar slightly too high (or: just wrong) for how I'd expect JavaScript to work, as it turns out. I'm spoilt by CFML, I guess. I'll update key points of that article, but make sure to read that one first as it's still mostly all right (IMO), and this article just clarifies a coupla points I didn't quite "get" last time.

My chief misapprehension was that JavaScript Promises themselves imparted some manner of asynchronicity to code execution, but this is not the case. They are just a handling mechanism for other code which itself is asynchronous. Once I wrote some code that respected that, things made more sense to me.

Here are some examples of how Promises help streamlining async code.

Friday 24 July 2015

JavaScript: (not ~) getting my brain around Promises

G'day:

Update / caveat

2015-07-24

I just had it wrong about this. See my next article: "JavaScript: expectations re-adjusted re Promises". Ignoring this side of things, the rest of this article does correctly reflect the mechanics of Promises, I think.

2021-01-14

I've just come back to this, and feel the previous update - originally buried halfway through the article - was not as emphatic as it should have been. My understanding / expectations of how Promises in Javascript work are just wrong in this article. I considered taking it down completely, but decided to leave it here. There's a lesson to be learned here: at the point at which things were not behaving how I'd expected, I should have done more research, rather than plouging ahead with even more wrongness. Oh well.

Thanks to Ryan for setting me straight in his comment.

My recommendation is to only read this if you want to laugh at me being extensively wrong. There is very little value in it other than that.

A few weeks ago I made a suggestion that some manner of Futures / Promises could be added to CFML ("What I'd like to see in ColdFusion 12 (redux, as is happens): Futures/Promises"). If nothing else this yielded a hilarious/frustrating series of comments. I also raised a ticket for same: 4010501.

I've messed around with a Future-ish sort of construct in the past ("CFML: Threads, callbacks, closure and a pub"), but never looked at Promises before, beyond reading the JavaScript docs for them ("Promise"), and being intrigued.

Way back when all the Acker-fracas was taking place I started knocking together some code to get me up to speed with JavaScript's implementation, just so I knew how they worked, and also to verify my suggestion had merit for CFML. I parked the code due to being sidetracked by other things, but I figured I'd write it up now. First I need to remind myself what all this code does.

According to the JavaScript docs, a Promise is:
The Promise object is used for deferred and asynchronous computations. A Promise represents an operation that hasn't completed yet, but is expected to in the future.

[...]

A Promise represents a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers to an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of the final value, the asynchronous method returns a promise of having a value at some point in the future.
I'm always rubbish at understand docs, so my reaction to that is "that's nice". I figured I needed to write some code and observe the behaviour, then I'd get a handle on what was going on.

The syntax of promise usage is:

new Promise(executor);
new Promise(function(resolve, reject) { ... });

Basically the constructor takes an argument that is a call back function, which itself takes two arguments (both call backs themselves), which can be called by the executor in either success or failure situations.

Tuesday 30 June 2015

JavaScript: deduping an array?

G'day:
I'm being a JavaScript dev at the moment, which is... interesting. My JS ain't bad, but I need to spend a lot of time with my nose in Google  / StackOverflow / MDN.

Here's something that I feel should be easier than I've made it:

Friday 27 February 2015

JS: opinions solicited regarding passing data values from server to client

G'day:
Just quickly.

Almost all of our JS is in separate JS files, and we try to take as much of an OO approach to our JS as is sensible in such a OO-hamstrung language. We do have separate "class" files (methods, stateful properties etc) and then script files which are used for event handlers when bootstrapping the page (creating said objects, etc).

Our JS inclusions would typically be along these lines:

<script src="/me/adamcameron/someapp/somepackage/SomeClass.js"></script>
<script src="/me/adamcameron/someapp/codeThatUsesSomeClass.js"></script>

Where:

// codeThatUsesSomeClass.js
var obj = new SomeClass(initParam, anotherInitParam);

// do stuff with obj

Thursday 29 January 2015

Second set of eyes on some code, pls?

G'day:
I'm having some trouble working out if I'm doing something wrong, or whether there's a bug in the library I'm using here. I'm erring towards it being me being daft and missing something. Could you perhaps cast yer eyes over this lot and see if I'm being a muppet? Cheers.

Tuesday 23 December 2014

JavaScript: Jasmine for unit testing

G'day:
At work, I've been tasked with getting the team up to speed with TDD whilst we redevelop our website in PHP. I knocked together a presentation on the subject a coupla months ago, but before having a chance to present it, got shifted about in the internal dept structure for a month or so, and it kinda got temporarily shelved. I posted it online: "TDD presentation". I'm back on the PHP Team now, and need to update said presentation to be more work-requirement-specific, as well as cover unit testing our JavaScript. This has been on our agenda for a coupla years, but was never allowed to get any traction by the decision makers. Decision-making has improved now, so we're all go.

I have heard about Jasmine, and like the look of it, but have never actually downloaded / installed / ran it. I'm gonna do that today.

(Oh, blogging my work is not something I do... I'm actually off on sick leave at the moment - which I feel slightly guilty about - but I need to get this stuff done, so gonna do it today whilst I am unlikely to get interruptions. I figured as I'm doing it on my own time, I get to blog about it too ;-)

I am writing about this as I do it.

Jasmine


First up: Jasmine. This is what Wikipedia has to say about Jasmine:

Jasmine is an open source testing framework for JavaScript. It aims to run on any JavaScript-enabled platform, to not intrude on the application nor the IDE, and to have easy-to-read syntax. It is heavily influenced by other unit testing frameworks, such as ScrewUnit, JSSpec, JSpec, and RSpec.
And from its own website:

Jasmine is a behavior-driven development framework for testing JavaScript code. It does not depend on any other JavaScript frameworks.

And a code sample from the same page:

describe("A suite", function() {
  it("contains spec with an expectation", function() {
    expect(true).toBe(true);
  });
});

If you're familiar with TestBox (and if you're a CFML dev, you bloody should be!), then this will look comfortingly familiar. Indeed that code would run on TestBox. I know a bit about TestBox, so this is pleasing: I have a head start!

Download & Install

I'm gonna use 2.1.3, which is - at time of writing - the latest version of Jasmine. The download page is here: jasmine 2.1.3. I've D/Led that and unzipped it into a public directory.

Running

This is too easy... it ships with a file SpecRunner.html, and browsing to that runs the tests. Here are the samples:



Nice!

Example Code

Looking at the code within SpecRunner.html, we see this:

Thursday 18 September 2014

Rendering a GitHub file in this blog

G'day:
A few days back I released that CFScript documentation effort, which at the time was just done inline as a blog article. I had not decided how best to home it so it could be found. I thought about putting it on GitHub, but in my experience Google is lousy at finding stuff on GitHub. As unimportant as the adamcameron.me domain is in the bigger scheme of things, I seem to rank quite well when it comes to CFML topics (ed: that CFScript page bloody doesn't, mate), so I figured putting it here would be a good first step.

Monday 28 April 2014

ColdFusion 11: <cfclient> ports a lot of CFML functions to JS

G'day:
I will start this article - which won't be a long one - by stating I am an adequate JavaScript developer, but I am by no means an expert. I'm at that stage wherein I'm au fait with the syntax and the nuts and bolts of writing OO-esque JS, but I don't spend enough time doing it to know the minutiae of "best practice" and don't automatically know the differences between the "best" way of doing something, and just "a way of doing something". Hence this article asks a question, rather than making any concrete statements.

Tuesday 25 March 2014

myArray.each()... extending the array whilst iterating..?

G'day:
I dunno what to think about some behaviour I'm seeing when iterating over an array with the .each() method.

Consider (but do not run!) this code:

numbers = ["one","two","three","four"];
numbers.each(function(value,index){
    if (value=="one") {
        numbers.append("five");
    }
    writeOutput("Index: #index#; value: #value#<br>");
});
writeDump(var=numbers);


Saturday 28 September 2013

arrayEach() could stand some improvement

G'day:
I'm going to lobby to get Saturday renamed "Sidetrackday". I sat down to write up a bunch of stuff one Ruby, and so far have written some CFML, some JS, some PHP and some Ruby... but not the Ruby I was intending do. Oh well.

I've touched in the past on my opinion that ColdFusion 10's new arrayEach() function is rather poorly/superficially implemented (here too), but today decided to check out how other languages deal with the same thing, and try to conclude what's the best approach for CFML to take.

So what's the story with arrayEach()?

Digression:

Those docs, btw, are frickin' useless:
  • Where's the code example?
  • Where's mention of the arguments passed to the callback? How many? What are they?
  • See also "other closure functions". Should that be a hyperlink, or is it just meant to be a pointless exercise of stating the obvious?
  • Category "Closure functions". Again: no link. And there isn't a category elsewhere in the docs "Closure Functions".
  • The function argument doesn't need to be inline. It just needs to be a function reference.
There's more wrong about those docs that there is that is right. That's quite an achievement.

End of digression.

So in lieu of the docs explaining this, what does it do? Here's a baseline demonstration:

rainbow = ["Whero","Karaka","Kowhai","Kakariki","Kikorangi","Tawatawa","Mawhero"];

arrayEach(
    rainbow,
    function(v){
        writeOutput(v & "<br>");
    }
);

This outputs:

Whero
Karaka
Kowhai
Kakariki
Kikorangi
Tawatawa
Mawhero


Basically what arrayEach() does is loop over the passed-in array, and then passes the value of each element to the callback function. The callback function receives one argument, that value. That's all it receives. And it can return a value if it likes, but nothing is expecting the value, so for all intents and purposes, the callback's method signature is:

void function callback(Any value)

Superficially that's fine. However it's a very isolated-element-centric approach. What I mean is that as far as the callback goes, the value it receives - for all intents and purposes - is not an element of an array, it's simply a value. You cannot act on that value in its content in the array. What? Well let's say I want to transform the array's elements. A simple example would be to upper-case the elements of an array of strings. Maybe like this:

rainbow = ["Whero","Karaka","Kowhai","Kakariki","Kikorangi","Tawatawa","Mawhero"];

arrayEach(
    rainbow,
    function(v){
        return ucase(v);
    }
);

writeOutput(rainbow.toString());

Well... no. Remember how I said that nothing is listening for a return value? Well it's not. So you're returning your upper-cases element back to the ether. v is a disconnected value here: the callback doesn't get it as part of the array, it just gets it as a value.

Monday 29 July 2013

Javascript: explicit arguments or config object? When to use which?

G'day:
Just to go off on a tangent... I'm doing Javascript this week, so the puzzling stuff I encounter will probably be JS rather than CFML.

Whilst I know a decent amount about CFML, my JS is... limited. I know enough to get into trouble... I know enough to know when I'm in trouble... but not necessarily enough to get me back out of trouble again.