Friday 24 March 2017

Help explain closure to the Adobe ColdFusion Team

G'day:
OK, this is a CFML-centric article. But it's also a call to provide code analogies in different languages to a CFML example, to show the ColdFusion Team they dunno what they're on about.

Here's some CFML code:

function doit() {
    var a = ["a", "b", "c"];
    var b = ["x", "y", "z"];
    var counter = 0;
    
    arrayEach(a, function(foo) {
        counter = 0;
        arrayEach(b, function(bar) {
            counter++;
            // in dump counter is always 0
            writeDump({
                counter: counter, 
                foo: foo, 
                bar: bar
            });
        });
    });
}
doit();

This leverages closure to reference the outer counter variable within the innermost function expression. Ergo, it's the same variable. So the expected output of this would be:


Note how the counter is declared in the main function, reset in the outer arrayEach handlers and incremented for each iteration of the inner arrayEach call. So it'll cycle through 1,2,3 three times when output.

That was run on Lucee. Running it on ColdFusion yields:


See how the counter is messed up: it's always zero. It should increment for each iteration of the inner function expression.

Adobe - being their typical selves - is claiming this is "by design":

https://tracker.adobe.com/#/view/CF-4197194:


That's nonsense.

Other languages behave predictably:

JavaScript:

function doit() {
    var a = ["a", "b", "c"];
    var b = ["x", "y", "z"];
    var counter = 0;
    
    a.forEach(function(foo) {
        counter = 0;
        b.forEach(function(bar) {
            counter++;
            // in dump counter is always 0
            console.log({
                counter: counter, 
                foo: foo, 
                bar: bar
            });
        });
    });
}
doit();
VM128:11 Object {counter: 1, foo: "a", bar: "x"}
VM128:11 Object {counter: 2, foo: "a", bar: "y"}
VM128:11 Object {counter: 3, foo: "a", bar: "z"}
VM128:11 Object {counter: 1, foo: "b", bar: "x"}
VM128:11 Object {counter: 2, foo: "b", bar: "y"}
VM128:11 Object {counter: 3, foo: "b", bar: "z"}
VM128:11 Object {counter: 1, foo: "c", bar: "x"}
VM128:11 Object {counter: 2, foo: "c", bar: "y"}
VM128:11 Object {counter: 3, foo: "c", bar: "z"}


And PHP (apologies for the rubbish way PHP does closure):

function doit() {
    $a = ["a", "b", "c"];
    $b = ["x", "y", "z"];
    $counter = 0;
    
    array_walk($a, function($foo) use (&$counter, $b) {
        $counter = 0;
        array_walk($b, function($bar) use (&$counter, $foo) {
            $counter++;
            // in dump counter is always 0
            var_dump([
                "counter" => $counter, 
                "foo" => $foo, 
                "bar" => $bar
            ]);
        });
    });
}
doit();


array(3) {
  ["counter"]=>
  int(1)
  ["foo"]=>
  string(1) "a"
  ["bar"]=>
  string(1) "x"
}
array(3) {
  ["counter"]=>
  int(2)
  ["foo"]=>
  string(1) "a"
  ["bar"]=>
  string(1) "y"
}
array(3) {
  ["counter"]=>
  int(3)
  ["foo"]=>
  string(1) "a"
  ["bar"]=>
  string(1) "z"
}
array(3) {
  ["counter"]=>
  int(1)
  ["foo"]=>
  string(1) "b"
  ["bar"]=>
  string(1) "x"
}
array(3) {
  ["counter"]=>
  int(2)
  ["foo"]=>
  string(1) "b"
  ["bar"]=>
  string(1) "y"
}
array(3) {
  ["counter"]=>
  int(3)
  ["foo"]=>
  string(1) "b"
  ["bar"]=>
  string(1) "z"
}
array(3) {
  ["counter"]=>
  int(1)
  ["foo"]=>
  string(1) "c"
  ["bar"]=>
  string(1) "x"
}
array(3) {
  ["counter"]=>
  int(2)
  ["foo"]=>
  string(1) "c"
  ["bar"]=>
  string(1) "y"
}
array(3) {
  ["counter"]=>
  int(3)
  ["foo"]=>
  string(1) "c"
  ["bar"]=>
  string(1) "z"
}


But I'm quite keen to know if there's any language that behaves as ColdFusion does in this example? If you've got a mo', could you knock out an equivalent of this code in [your language of choice], and share the results?

I'm 99.999% sure Adobe are just not quite getting closure, but wanna make sure I'm not missing anything.

Righto.

--
Adam

Wednesday 22 March 2017

Code puzzle: find any match from an array of regex patterns

G'day:
I'm being slightly cheeky as I'm hijacking someone else's question / puzzle from the CFML Slack channel that we were discussing last night. Don't worry, that'll be the last mention of CFML in this article, and indeed the question itself was asking for a JS solution. But it's a generic code puzzle.

Let's say one has a string, and an array of regex patterns one wants to check for in said string. A number of solutions were offered, using a number of techniques. And it even branched away from JS into Clojure (thanks Sean).

How would you go about doing it?

The input data is:

patterns = ["Savvy", "Smart", "Sweet"]
testForPositive = "Super Savvy"
testForNegative = "Super Svelt"

And in these cases we want true and false to be returned, respectively.

Note that the patterns there need to be considered regular expressions, not simple strings. The example data is just using simple strings for the sake of clarity.

Initially I was gonna do something like this:

function matchesOne(str, patterns) {
    var onePattern = new RegExp(patterns.join("|"));
    return str.search(onePattern) > -1;
}

Here I'm joining all the patterns into one big pattern, and searching for that. I was slightly hesitant about this as it's loading the complexity into the regex operation, which I felt perhaps wasn't ideal. Also it's not very clever: if any of the individual patterns had a | in them: this'd break. Scratch that.

Ryan Guill seeded the idea of approaching it from the other direction. Using the array as an array, and using one of JS's array higher-order functions to do the trick. We saw examples using find and filter, but I reckoned some was the best option here:

function matchesOne(str, patterns) {
    return patterns.some(pattern => str.search(pattern) > -1);
}


I'm happy with that.

The ante was raised next: write a function which returned the position of the first match (not just a boolean as to whether there was a match or not).

To me this was a reduction operation: take an array and - given some algorithm applied to each element - return a final single value.

I tried, but I could not make it very clean. This is what I got:

function firstMatch(str, patterns) {
    return patterns.reduce(function(first, pattern){
        var thisMatch = str.search(pattern);
        return first == -1 ? thisMatch : thisMatch == -1 ? first : Math.min(first, thisMatch);
    }, -1);
}


I'm happy with the reduce approach, but I'm really not happy with the expression to identify the lowest match (or continue to return -1 if no match is found):

first == -1 ? thisMatch : thisMatch == -1 ? first : Math.min(first, thisMatch)


To be clear, if we expanded that out, the logic is:

if (first == -1) {
    return thisMatch;
}
if (thisMatch == -1) {
    return first;
}
return Math.min(first, thisMatch);

That's actually "cleaner", but I still think I'm missing a trick.

So the puzzle to solve here is: what's a clever (but also Clean - in the RC Martin sense) way returning the lowest non -1 value of first and thisMatch, or fall back to -1 if all else fails.

Using this code (or some approximation thereof):

function firstMatch(str, patterns) {
    return patterns.reduce(function(first, pattern){
        var thisMatch = str.search(pattern);
        // return result of your code here
    }, -1);
}

console.log(firstMatch("Super Savvy", ["Savvy", "Smart", "Sweet"]));
console.log(firstMatch("Super Svelt", ["Savvy", "Smart", "Sweet"]));


One should get 6 and -1 for the respective "tests".

Use any language you like.

Oh and hey... if you have any interesting solutions for the two functions themselves, feel free to post 'em too.


Righto.

--
Adam

Thursday 9 March 2017

CFML: that survey... sit. rep.

G'day:
A coupla people have asked me what's happening with my feedback from that survey you all did for me (Survey: CFML usage and migration strategies).

I have to simply apologise for the delay. I started to look at it, but could not work out how best to present the data. Then I buggered off to NZ to sit in the sun watching cricket and drinking beer with me mates; and "CFML survey data analysis" was not high on my list of priorities. I did start looking at the data some more though.

So not much progress yet, but I'm now back in London and trying to refocus on IT stuff, so I'll try to start feeding back soon. -ish.

Again: apologies for the delay.

Righto.

--
Adam

PHPUnit: setMethods and how I've been writing too much code

G'day:
Seems our technical architect is becoming my PHP muse. Good on ya, Pete.

Anyway, he just sent out what I thought was a controversial email in which he said (paraphrase) "we're calling setMethods way too often: in general we don't need to call it". To contextualise, I mean this:

$dependency = $this
    ->getMockBuilder(MyDependency::class)
    ->setMethods(['someMethod'])
    ->getMock();

$dependency
    ->method('someMethod')
    ->willReturn('MOCKED RESULT');


See here I'm explicitly saying "mock out the someMethod method". Pete's contention is that that's generally unnecessary, cos getMockBuilder mocks 'em all by default anyhow. This goes against my understanding of how it works, and I've written bloody thousands of unit tests with PHPUnit so it surprised me I was getting it wrong. I kinda believed him cos he said he tested it, but I didn't believe him so much as to not go test it myself.

So I knocked out a quick service and dependency for it:

namespace me\adamcameron\myApp;

class MyService
{

    private $myDecorator;

    public function __construct(MyDecorator $myDecorator)
    {
        $this->myDecorator = $myDecorator;
    }

    public function decorateMessage($message)
    {
        $message = $this->myDecorator->addPrefix($message);
        $message = $this->myDecorator->addSuffix($message);
        return $message;
    }

}

namespace me\adamcameron\myApp;

class MyDecorator
{

    public function addPrefix($message)
    {
        return "(ACTUAL PREFIX) $message";
    }

    public function addSuffix($message)
    {
        return "$message (ACTUAL SUFFIX)";
    }

}

Nothing surprising there: the service takes that decorator as a constructor arg, and then when calling decorateMessage the decorator's methods are called.

In our tests of decorateMessage, we don't want to use the real decorator methods, we want to use mocks.

First I have a test the way I'd normally mock things: explicitly calling setMethods with the method names:

public function testWithExplicitMock()
{
    $decorator = $this
        ->getMockBuilder(MyDecorator::class)
        ->setMethods(['addPrefix', 'addSuffix'])
        ->getMock();

 $decorator
  ->method('addPrefix')
  ->willReturn('(MOCKED PREFIX)');

 $decorator
  ->method('addSuffix')
  ->willReturn('(MOCKED SUFFIX)');

 $service = new MyService($decorator);

 $result = $service->decorateMessage('TEST MESSAGE');

 $this->assertSame(
        '(MOCKED SUFFIX)',
        $result
    );
}

And this mocks out the method correctly. This is my baseline.

Secondly, I still call setMethods, but I give it an empty array:

public function testWithImplicitMock()
{
    $decorator = $this
        ->getMockBuilder(MyDecorator::class)
        ->setMethods([])
        ->getMock();

 $decorator
  ->method('addPrefix')
  ->willReturn('(MOCKED PREFIX)');

 $decorator
  ->method('addSuffix')
  ->willReturn('(MOCKED SUFFIX)');

 $service = new MyService($decorator);

 $result = $service->decorateMessage('TEST MESSAGE');

 $this->assertSame(
        '(MOCKED SUFFIX)',
        $result
    );
}

This also mocks out the method correctly. Passing an empty array mocks out all the methods in the mocked class.

Next I try passing null to setMethods:

public function testWithNull()
{
    $decorator = $this
        ->getMockBuilder(MyDecorator::class)
        ->setMethods(null)
        ->getMock();

    $decorator
        ->method('addPrefix')
        ->willReturn('(MOCKED PREFIX)');

    $decorator
        ->method('addSuffix')
        ->willReturn('(MOCKED SUFFIX)');

    $service = new MyService($decorator);

    $result = $service->decorateMessage('TEST MESSAGE');

    $this->assertSame(
        '(ACTUAL PREFIX) TEST MESSAGE (ACTUAL SUFFIX)',
        $result
    );
}

This creates the mocked object, but the methods are not mocked. So the result here is using the actual methods.

In the last example I mock one of the methods (addPrefix), but not the other (addSuffix):

public function testWithOneExplicitMock()
{
    $decorator = $this
        ->getMockBuilder(MyDecorator::class)
        ->setMethods(['addPrefix'])
        ->getMock();

    $decorator
        ->method('addPrefix')
        ->willReturn('(MOCKED PREFIX)');

    $service = new MyService($decorator);

    $result = $service->decorateMessage('TEST MESSAGE');

    $this->assertSame(
        '(MOCKED PREFIX) (ACTUAL SUFFIX)',
        $result
    );
}

Here we see the important bit: when one explicitly mocks one or a subset of methods, then the other methods are not mocked. Which is kinda obvious now I say it, but I guess we had been thinking one needed to call setMethods to be able to then mock the behaviour of the method. And, TBH, I don't think we thought through what was happening to the methods we were not mocking. I think we started calling setMethods all the time because we were slavishly following the PHPUnit docs, which always call it too, which is a less than ideal precedent to "recommend".

Generally speaking, one should want to mock all methods of a dependency, and it should really be the exception when explicitly not wanting to mock a method: ie, to leave it actually callable.

The win here is that we can now de-clutter our tests a bit. We really seldom need to call setMethods, and we sure want to make it clear when we do want to only mock some of a dependency's methods. So this will make our code cleaner and clearer, and easier to code review and maintain. Win!

Cheers Pete!

Righto.

--
Adam