Contact - Twitter Icon Twitter - RSS Feed Icon RSS

TomNomNom.com

The web stuff of Tom Hudson.

Bio

Friends

Files

Tweets

A generic caching function for PHP Tue Jun 15 18:57:05 2010

A short post is better than none. I threw together a generic caching function today; thought I'd share.


<?php
function createCached($fn$ttl = 100){
    return function() use($fn$ttl){
        $args = func_get_args();
        if (!is_string($fn)){
            //Use reflection to get a unique, reproducible identifier for an anonymous function
            $r = new ReflectionFunction($fn);
            $key = md5($r->getFileName().$r->getStartLine().serialize($args));
        } else {
            $key = md5($fn.serialize($args));
        }
        $result = apc_fetch($key$success);
        if ($successreturn $result;
        $result = call_user_func_array($fn$args);
        apc_store($key$result$ttl);
        return $result;
    };
}


It's pretty simple and immature (read: no error checking) at the moment, but here's an example...


<?php
function helloWorld($name){
    echo "You will only see this when the result is not cached\n";
    return "Hello, {$name}!\n";
}

echo helloWorld('Tom');
$cachedHelloWorld = createCached('helloWorld'10);
echo $cachedHelloWorld('Tom');
echo $cachedHelloWorld('Tom');


The output of that is something a little like this:


You will only see this when the result is not cached
Hello, Tom!
You will only see this when the result is not cached
Hello, Tom!
Hello, Tom!


As you can (hopefully) see, the first call too helloWorld() just calls it directly. The call to createCached() creates a cached version of helloWorld() with a Time To Live of 10 seconds. The first call to the resultant anonymous function calls helloWorld() and caches the result using APC. The third and final call just returns the cached result.

You can pass in an anonymous function instead of the name of a function too:


<?php
$myFn = createCached(function(){
    $result_array = someIntensiveFunction();
    sort($result_array);
    return $result_array;
}, 3600);

print_r($myFn());


This would create a function that caches the sorted output of someIntensiveFunction() for an hour. Very handy if someIntensiveFunction() lives up to it's name.

If you've got a big code-base with a lot of fetcher functions this approach can be pretty handy; you can cache the output of your most used functions without cluttering them up with caching code.

Limitations
There's a whole bunch wrong with my suggested code at the moment. I just wanted to get it out of my head while it's still fresh. It won't work with object methods and it's not very well tested, for example. I might get time in the next 6 months or so (that is my average interval between blog posts isn't it?) to write some tests for it and expand a little on the idea. Or I might just write an equivalent in JavaScript for comparison.

UK Scale Camp Mon Dec 7 9:37:48 2009

On Friday (The 4th of December 2009), my boss and I went to the first UK Scale Camp - organised by Michael Brunton-Spall.

Done as a BarCamp-style un-conference; the talks were provided not by pre-decided speakers, but by the attendees themselves. I was very impressed with the event on a whole. We were well looked after; the sponsors provided breakfast, lunch and plently of beer for the evening and everyone there was very polite and friendly. Of course, the talks were the main thing - and there was a lot to choose from. The talks went up onto the wall in post-it note form and were copied to a Google Speadsheet for easy viewing.

There were many highlights to the day. The introductions session was a great idea and turned out people from The Guardian (of course), The BBC, Last.fm, Microsoft, Wikia and many others. The talks were awesome and the speakers very professional. I especially enjoyed the talk from two guys from Media Molecule on the problems they faced scaling the web services associated with Little Big Planet; they were both very entertaining and knowledgeable. The group discussion on how to scale activity feeds was also most enlightening; I've got lots of notes to be trawling through from that. And 'Ed' did a great job of explaining how his small team had managed with their relitively high work-loads. To be honest, there was so much of interest to me that I would have been happy to pay for a single track conference over three or four days with the same content.

I'm not really any good at this non-technical writing (not to say I'm good at the technical writing either), so I shall leave it there. I would, however, like to say a big thank you to Mr Michael Brunton-Spall for organising it all; all the other attendees for being awesome and friendly; and, as my evening was spent getting really rather drunk and playing pool with fellows from Last.fm and Microsoft, the sponsors for buying the breakfast, lunch and beer. Hats off to you all.

Developers - the heroes of the internets Wed Nov 18 21:11:36 2009

Anyone who's ever been to a high-school style career guidance meeting will know that there are a lot of careers to choose from. You could be anything, they tell you: a doctor, a plumber, an accountant or even an astronaut; or you could be a developer. There is something that separates developers from people in most (but not all) other professions. Developers aren't people who picked their career for the money and the glamour. They're people who didn't pick their career at all; they're just wired that way. There are exceptions of course, but they are just that: exceptions.

There are not many accountants who sit at home and do accounting for fun, or plumbers who go home on a night looking forward to lagging their own pipes. There are not many astronauts who go into space in their own time either; there are a few practical reasons for that of course, but that's not the point. Developers are people who finish a long day of programming and debugging and head home looking forward to doing more of the same. It's not a just a career for them; it's just what they do.

The developer mentality is the reason the open source and free software movements exist; the thing that baffles the business men so much - "Why would you spend time on something you're not getting paid for?". It's the thing that drives a surprising amount of innovation in the world: if developers didn't do development in their spare time we probably wouldn't have Linux, Apache, MySQL or PHP. And given that these four technologies alone power a large proportion of the web: we probably wouldn't have much of what makes the web so awesome. In fact, we would probably live in a world where the web is dictated by corporate giants like Microshaft.

It is my personal opinion that anyone looking to employ a developer (or developers) should be aware of this. If you find yourself interviewing a candidate who doesn't do development work in their own time (without good reason) don't hire them unless they are your last resort. In this situation, it's likely that you have found someone who picked their job because it's what they studied at college or university, or because they couldn't think of anything else to do with their lives and needed the money.

Hats off to the real developers; the people who come home from their day job and then stay up late writing code - only to give it away for free to people who need it; you are the heroes of the internets.

Objects before classes makes for a cleaner API Mon Oct 12 10:49:57 2009

Quite often I find myself writing a new class for the hell of it - or in the hope that it will come in useful for some project or other. From all my experience in writing random classes, the most important bit of advice I can give is this: write the code using the class before you write the class itself.

If you're a relatively newbie OO programmer, it can be very easy to get tied up in the details and focus on writing clean code in your classes. There's nothing wrong with that in itself, but it can make for real headaches later on when you try to use them. As an example, here's a rather fruity class I wrote without bothering to think about how it will be used:


<?php
class Fruit {
  private $name;
  private $color;
  public function getName(){
    return $this->name;
  }
  public function setName($name){
    $name = ucfirst($name);
    $this->name = $name;
  }
  public function getColor(){
    return $this->color;
  }
  public function setColor($color){
    $color = ucfirst($color);
    $this->color = $color;
  }
}


The class may be clean and tidy, but having to call setName() and setColor() for every fruit I want to create is going to end up being a serious pain. Let's say I want to eat the fruit with a little function like this:


<?php
function eatFruit(Fruit $fruit){
  echo 'Om nom nom! I\'m eating a '
      . $fruit->getColor() . ' '
      . $fruit->getName();
}


I would have to create my object, set it's name and color, and then call the eatFruit() function:


<?php
$apple = new Fruit();
$apple->setName('granny smith');
$apple->setColor('green');
eatFruit($apple);


That might not seem like masses of code to get my lips around some tasty fruit, but it could be a lot easier. Let's start from the other end and write a use-case for the fruit before writing the class.


<?php
eatFruit(new Fruit('granny smith''green'));


That's a whole lot easier in my book. I could be eating four times as much fruit per line than I could before! The class doesn't even require that many changes to make it work; just a constructor...


<?php
class Fruit {
  private $name;
  private $color;
  public function __construct($name = ''$color = ''){
    $this->setName($name);
    $this->setColor($color);
  }
  public function getName(){
    return $this->name;
  }
  /*...And the same as before...*/
}


Although there's more code in the class cluttering it up, it only has to be written once.

I admit this may be an over-simplified example, but I think it carries the right message: don't worry about making your classes bulky and complicated if it means your code that uses them will be simpler.

That didn't take long Wed Oct 7 23:19:24 2009

I got bored and implemented my aforementioned syntax highlighter. There's a couple of teething problems, but nothing that should be too hard to sort out.

Maybe now I can look at having switchable colour schemes :-)

If you're wondering, I based the colours I've used on those from Dmitriy Zotikov's excellent vim theme Xoria256. Have a look at the CSS file here.