Friday, November 13, 2015

Friday, November 6, 2015

Tuesday, October 27, 2015

PHP array de-duplication trick that'll save you lots of CPU (* YMMV)

Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.

Today, I discovered this curious gem in legacy code:

<?php
// ✂ ...snip... wall of code that creates array $ids
$ids = array_flip($ids);
$ids = array_flip($ids);
// ✂ ...snip... wall of code using $ids

Looks like a cut and paste error, and my gut reaction was to delete the second line. But, a sneaking suspicion stalled my reaction: the developer-that-no-longer-works-here who wrote that code had a talent for writing clever, uncommented code. Perhaps this was another instance of that pattern, and I'd better check myself.

PHP arrays map keys to values. array_flip spins the mapping around, values to keys. If the code intended to flip the array, then I'd expect to see iteration over values to keys. What I observed in later logic was instead iteration of keys to values, as if the flip never happened. So what was this code doing?

It's a de-duplication trick, first seen in a 2002 comment about array_unique. Purportedly, double flip is significantly faster than the equivalent array_unique call for large arrays. Before you rush off and change all your code to use this trick, keep these things in mind:

  • array_unique() and array_flip(array_flip()) produce different results where keys are concerned: array_unique keeps the first unique (key, value) pair while array_flip keeps the last.
  • array_unique([0, false, 0]) produces the expected result. Double flip does not (and raises a warning to boot).
  • For small arrays, the performance difference is invisible.
  • For very large arrays of numbers, the difference between array_unique($a, SORT_NUMERIC) and array_flip(array_flip()) is negligible. On a medium Amazon EC2 instance, 0.27s vs 0.4s for 10M integers.
  • For very large arrays of strings, the difference is significant. On a medium Amazon EC2 instance, 1.2s vs 10.9s for 10M strings of random length between 3 and 5 ASCII characters.

That's a real savings, and so this trick definitely has a place in the developer's tool box. But please, please for the love of all that is holy, comment the trick so that's clear what's going on. My preferred way of seeing this trick deployed is:

$ids = array_flip(array_flip($ids)); // want unique values, don't care about keys

Wednesday, October 14, 2015

404

I'm terribly sorry, but I can't find the page you have requested.

Believe me, I looked for it. Really! You can't even imagine the millions of calculations I had to go thru to look in all the places my owner could have left what you asked for. But I couldn't find it. It's not there! :-(

No, it's not your fault, it's all my own. I'm a bad server. I know. Terrible. I should get a new job one day or another, but what else can I do?

Tuesday, October 13, 2015

Friday, August 28, 2015

Jenkins and Skype: Back Together Again

So, all us developers use Skype. But there's one member of the team who, until today, wasn't on Skype: Jenkins.

Getting Jenkins onto Skype is possible, despite Microsoft killing API access in Skype. In this post, I show you a six step process to configure Jenkins to message you over Skype.


Tuesday, June 2, 2015

Wednesday, May 27, 2015

Shaking out dependencies in PHPUnit unit tests

Isolation is a unit test ideal. You should, in theory, be able to run them in a random order, or in parallel, with no effect on the results.  PHPUnit provides no options to do this, but, fortunately, two neat GNU command line utilities can help.

Thursday, May 21, 2015

How software dies

When software reaches its design apex, the passion to develop it wanes and it begins descending through maintenance hell.  What was once state-of-the-art becomes legacy, and once legacy becomes abandonware.  Except for those rare software gems that endure for generations.

Tuesday, May 19, 2015

"Writable" is wrong!

Incorrect and inconsistent spelling makes searching harder:

function initDb() {
    $datbase = PDO::get();
    $datbase->check();
}


If I searched my code base for "database", I'd miss this hit.  That sucks.  Please take the time to correctly spell.  (Corollary: if you misspell, misspell all instances consistently!)

With this in mind, what about "writable" and its variant "writeable"?  While the dictionary says "writable" is correct, I consider that spelling harmful.  Search for "table" and you'll hit "writable", which is undoubtedly a false positive.

Please use the "writeable" variation.

Thursday, February 19, 2015

Thursday, January 15, 2015

Memoization 2.0

You might think "Memoization" is a typo, but it's not. Memoization is a simple technique to improve software performance. Unfortunately, the technique relies upon repetitive boilerplate. In this article, I show you how to use memoization without any boilerplate code.

Tuesday, January 13, 2015

Saturday, January 10, 2015

Pudgy controllers? Try the Route diet!

Nestled between user and controller, the routing layer is a perfect home for common filtering and access-control oriented code. But you have to know your framework's routing capabilities to exploit this location. In this article, I share a users' group presentation on the supple Laravel 4 Route facade.

Thursday, January 8, 2015

Zero to PSR-4 in 60 seconds

By and large PSR-0 and PSR-4 are identical. Comparing and contrasting the two doesn't illuminate the crucial, but small, surface area where they differ.  Sadly, most documentation takes this compare and contrast approach. In this article, I break with that documentation pattern and rather focus on the essence of PSR-4.