February 11, 2010

Introducing Scisr, a PHP Refactorer

I'd like you all to meet my latest hobby project. It's a standalone refactoring tool for PHP. I call it Scisr.

I looked around for refactoring solutions a while back when I had some tedious renaming to do at work, and was surprised by how poor the options were. This question has a fairly complete list of everything I found, which is to say, not much. And what options existed were not very powerful or, more often than not, simply didn't work at all (I never did get Zend Studio to successfully refactor anything, even in the short periods between crashes).

So like any good nerd, I decided I could do better. I had been using PHP_CodeSniffer a lot, and thought that it would make a perfect platform to start work on - while my needs were slightly different than the typical "sniffs," the tokenizer architecture would suit me very well. Thus was Scisr born.

The design goals were influenced by aspects of the other tools that I disliked. I hated the idea of installing an entire IDE and twiddling with a whole bunch of project settings just to rename something. Despite what some Java programmers would have you think, refactoring is not an end in and of itself. Refactoring is something to do, test, and move on with as little fuss as possible. You're not using Scisr for the thrill of using Scisr - you're using it because it can help you get a job done. So Scisr is a standalone tool with incredibly simple installation, and I provide incredibly simple usage instructions on the project page. It should be possible to start using it on your work in under 5 minutes.

Here's something about refactoring PHP: it's impossible to do a perfect job of it. If you are renaming the class method Foo::bar(), how would you handle the following code?
<?php
$classname = $_POST['c'];
$item = new $classname();
$item->bar();
?>

There's no right way to handle this because PHP is weakly typed. I should also mention that you would have to be a madman to use the above code in anything, ever.

There are definitely some advantages to weak typing, but it means that we will never be able to write completely precise refactoring tools. So why fight it? Instead, Scisr accepts these limitations and just does the best it can. When renaming methods, it looks for typing information in a number of places - instantiations, PHPDoc tags, parameter type hints, the comment type hints that Komodo IDE and Zend Studio recognize. And when it comes across a potential match that it just can't be sure about, it will notify the user without making a change (unless you have it set to "aggressive" mode, in which case it will go ahead and hope for the best).

I'm also not going to bother supporting actions that require individual attention. I'm focusing on the tedious refactoring tasks that can be effectively automated, and will provide significant saved effort. Currently, Scisr can rename classes, class methods, and files. In the future I may also support renaming functions and class properties. These are things that would otherwise require a lot of repetitive find and replace, or a clever scripted solution, and even then you'll be in trouble if you're acting on something with a generic name (ever tried renaming a method named 'validate'?).

So, now that you've read about it, why don't you try it out? There are installation and usage instructions over at the project page. Scisr is currently at version 0.2.0, which means it's a little rough around the edges, but it is usable. I would very much love to hear from you if you use it and find bugs, or have suggestions, or if you just enjoy using it. I'm pretty pleased with it so far, and I hope other people will find it useful too.

Enjoy, and please, let me know how it goes!