Archive for the 'Uncategorized' Category

Bending PHP to Your Will

Posted on 6 August 2011, in Uncategorized. 2 Comments.

One of the best features of Objective-C is protocols. These are akin to PHP and Java interfaces, but have one huge advantage: you can mark certain methods as required or optional. This is useful in implementing the delegate pattern because if you do not care about a certain method, you can simply not implement that method. In PHP, this is not possible with interfaces: you must implement all the methods of an interface in order to implement the interface. While this is fine and makes sense in most cases, it’s not always convenient.

So I set off to find a way to create protocols in PHP. The language is fairly dynamic, so I was able to come up with a solution called WeakInterface. Before jumping into the implementation details, let’s see how it works in practice:

First you define your interface as you would normally:

interface AllOptionalInterface {
  public function DoSomething();
  public function DoSomething1(Closure $arg);
}

The class that implements this only cares about the DoSomething method, so it implements it:

class AllOptionalImpl {
  public function DoSomething() {
    echo 'I did something!';
  }
}

Note that this class isn’t said to implement this interface because it does not implement all the methods. Now in the code that is going to call this interface, you do the following:

$delegate = new WeakInterface('AllOptionalInterface');
$delegate->Bind(new AllOptionalImpl);
$delegate->DoSomething();
$delegate->DoSomething1(function() { echo 'Wow!'; });

This code will output “I did something!”. Let’s go line-by-line. First, $delegate is being created as an instance of WeakInterface, whose constructor takes the name of the interface to “implement.” Then the interface is bound to an instance of the implementation. And then finally two methods are called on the interface, and the one with an implementation is actually called. Calling DoSomething1() is a no-op.

I mentioned above that in Objective-C you can mark some methods as required, too. And that’s done with a docstring when using WeakInterfaces:

interface OneRequiredInterface {
  public function DoSomething();
  /** @required */
  public function DoAnything();
}

If you failed to implement DoAnything(), the call to WeakInterface::Bind() would throw an exception. But what if the number and type hints of the arguments of an implementation do not match that of the interface? WeakInterface has that base covered, too. Bind() will also check the parameters of all method implementations to make sure that the signatures match the interface’s.

That’s WeakInterface in a nutshell, but how does it actually work? It’s easiest to start with a callstack. So when $delegate->DoSomething() is called, this is how WeakInterface actually invokes the implementation:

# Time Memory Function Location
1 0.0033 975328 hoplite\base\WeakInterface->DoSomething( ) ../example.php:14
2 0.0033 975856 hoplite\base\WeakInterface->__call( ) ../weak_interface.php:0
3 0.0033 975856 hoplite\base\internal\MethodImp->Invoke( ) ../weak_interface.php:84
4 0.0033 976568 ReflectionMethod->invokeArgs( ) ../weak_interface.php:145
5 0.0033 976608 AllOptionalImpl->DoSomething( ) ../example.php:0

WeakInterface implements the magic PHP method __call(), which is invoked whenever a method call is performed and no method is found by the runtime. It captures this and then forwards the invocation on to an implementation helper MethodImp, which then uses reflection to finally invoke the proper implementation.

Going deeper, when a WeakInterface is constructed, the interface passed to it is reflected and the method list is walked. For each method, a MethodImp is created. When the WeakInterface is bound, that set of MethodImps is looped over, checking that any required methods are implemented and that any implementations match the interface’s method signature. At call time, the method name is looked up in the MethodImp table and the arguments are forwarded to the actual implementation.

One note on performance: due to the number of intermediate method calls, using WeakInterface is roughly four times slower than a plain method call. For most applications, this should not be significant at all; but for performance-critical code, you should steer away from WeakInterface.

The code is available here along with a unit test.

Downloads Work Again

Posted on 14 April 2010, in Uncategorized. No Comments.

Due to a server misconfiguration issue, the site couldn’t connect to its database. As a result, downloads stopped working since yesterday’s rollout. This has now been fixed. Sorry for any inconvenience.

Welcome to the new Blue

Posted on 13 April 2010, in Uncategorized. 1 Comment.

After about two months of work, I’ve finally completely redesigned the website. I think it sucks a lot less than the previous version, which is always a good thing. It’s written in HTML5 using CSS3. The best part is that I have no idea whether or not it works in Internet Explorer. My traffic is always less than 10% IE, so I’m not going to bend over backwards to support it. Anywhoo, check it out! You’ll also notice that the entire site is now being served over HTTPS.

Toolchain and Gitcrement

Posted on 4 April 2009, in Uncategorized. No Comments.

I’ve posted today a git repository called Toolchain. This is a collection of scripts that I use that others may find helpful. You can find the repository here. In this post, I’m going to talk about one of the items in Toolchain called Gitcrement.

Gitcrement is a set of two scripts that solves the problem of creating build numbers when using git for source control. Unlike Subversion, where the repository revision is the perfect choice for a build number, git has no such luxury because it uses SHA1 hashes for identifiers.

This is where Gitcrement comes in. Gitcrement is a simple interface to a database that contains a sequential ID number (the build number), a username, the current date/time, and a git SHA1 hash.

The gitcrement.py has four commands: init, next, list, and current.

To create a new Gitcrement database, go into any git repository root and type “gitcrement init“, which will create a new database file called .gitcrement.

When you want to create a new build number, simply type “gitcrement next” to record the current user (`whoami`), date and time, and whatever SHA1 hash `git info .` would reveal.

To see the current build number type “gitcrement current” and to get a list of all the build numbers type “gitcrement list“.

That’s all there is to it. To make this system useful, however, it needs a script that can be run in Xcode to automatically call “next” and save the value as CFBundleVersion in Info.plist. So, there’s another Python script called xcbuild.py, which you can use as a Custom Shell Script Build Phase. This will advance the Gitcrement number every time you build the “Release” target in Xcode.

Gitcrement requires Python 3.0, which is not installed by default in Leopard. You can find it here or through MacPorts or fink.

Also, you may need to edit the installation paths in the tops of both files to point to where your copy of “git” is (in gitcrement.py) and where you install the “gitcrement” script (in xcbuild.py).

You can download Gitcrement here:
Link in Gitweb
Source TGZ

Chromium for OS X

Posted on 26 March 2009, in Uncategorized. 2 Comments.

Mac users interested in Google Chrome can now try out the latest pre-alpha development version. I have compiled the source tree and the binary can be found here. I’ll be rebuilding and posting the build roughly once a week.

As it says on the page, these builds are unstable and should only be used to see how development is progressing. I will not support these builds and (I’m assuming) neither will the Google team. That being said, enjoy.