How do you tackle big refactoring projects for your chosen language, framework and platform?
I’ve been sort of struggling with a very old, twisted and convoluted PHP mess as of lately, and I’m finding that there are just not that many good tools for this sort of task. For PHP that is. Some languages are just easier to refactor than the others I guess. Java, for example, despite being a convoluted mess of needlessly verbose boilerplate is actually a dream to refactor. Because of the rather rigid structure (everything is an object) and file naming conventions (each file must have same name as the main class it contains) a good IDE can really make this sort of thing painless. If at some point you decide to rename a class Eclipse will seamlessly rename all the files that need to be renamed, and propagate the change throughout all the code almost automatically. It can do this because it can pre-compile the code, see which classes reference which and make necessary adjustments.
PHP is… Well a bit of a mess in this department. It was originally supposed to be something akin to a templating language that grew too large and too popular, too fast. An average PHP file can (and usually does) contain raw HTML, php code, and php code that outputs HTML. The import statements in PHP are just simple concatenation – and you can test it by including ordinary HTML or text file into your PHP code.
So refactoring PHP code is about as easy as walking into Mordor. It can be done, but it is non-trivial and thus your average editor or IDE is not going to even touch it. There seem to be some pretty decent refactoring support in Zend Studio and PHPStorm but… Well, for one those are pretty heavy duty IDE’s with their own specific quirks and workflows you sort of have to learn before you can start hacking. Secondly, both cost money. Thirdly, both have been written in Java and thus run double-plus slow on my aging Ubuntu box. No, I checked – the PHPStorm actually took longer to display the splash screen, than it took me to download and install the trial version.
There are also a few stand alone refactoring tools for PHP – like Rephactor for example. Which is a tool I don’t fully trust since it actually uses regular expressions to do it’s job. I probably don’t have to tell you why this is a terrible idea. It is sort of equivalent to casting a fishing net, and dragging it across the sea floor hoping that you will only swipe up edible fish, and none of the equally abundant unexploded sea mines. Not to mention that the tool is incomplete, and that it likes to rely on unit tests for validation… Which is kinda cute, considering that if the code I’m dealing with had unit tests, I probably would not be needing to refactor it so urgently. Anyone with enough forethought to write some semi-robust unit tests is likely to know better than to write terrible spaghetti code.
I ended up using a tool named Scisr. I like it, because it is simple, easy to use and covers the basic refactoring actions I need: renaming files, classes and functions. It does this by actually parsing and tokenizing the code, rather than by shooting regexps at it which inspires me with more confidence.
So far I successfully used it to rename bunch of files and functions, without hitting any snags. Does that mean it is working? Well, maybe. It has been working well enough so far. Let me give you an example. I noticed this gem cropping up in the code a lot:
WTF is fun? Well, apparently fun stands’ for “functions” or rather “assortment of random utility functions”. The fact that the file doesn’t even have a proper extension is annoying, but what makes makes this extra shitty is that it is sitting smack dab in the middle of the root directory of the project… Why? Because it’s fun, apparently. So the idea was to move and rename this fun file into something more… I don’t know, descriptive. Like utility-functions.php for example. Then hopefully namespace it or something, but one step at a time. To do the renaming with Scir all you need to do is run:
scisr rename-file fun /path/to/includes/utility-functions.php .
This not only went recursively through all of the code and changed all the references to the file, but also moved the file where it needed to be. It took only couple of seconds, and actually managed not to break anything. I haven’t tried anything more complex than renaming files with it, but it seems fairly robust. In any case, if it does happen to break something, I can always check-out the last commit from git and start over.
Do you know any better refactoring tools for PHP? How do your refactor your stuff in the language you are working with right now? Let me know in the comments.