Pretty Horrible Programming
May 18, 2010 § Leave a comment
Since beginning my MLIS, I’ve heard so much about how the savvy librarians wield PHP. I put aside my skepticism and figured I’d see how PHP has evolved since the last time I’d looked at it about ten years ago. This would be a great opportunity to pick up a real web language and build a website that looked cool and helped people.
Since diving in, I’ve discovered that PHP has grown but not evolved significantly from its humble origins as a little macro language for building websites. The existing code for this application is messy and scattered (the app never progressed beyond a basic prototype), but it’s basically sound. The fault here seems to lie purely in the lack of core language features that characterize mature programming languages.
PHP’s OO functionality provides programmers with classes and interfaces (a good start), but in a language that’s so weakly typed it’s hard to see what benefits interfaces provide. PHP has class constants and private (and protected) fields, but it’s not possible to declare a field both constant and private. That means that you can make assertions about either the scope or the (im)mutability of a field, but not both. For now, I’ve chosen the abstraction leak over having mutable state, but in a larger application I’m not certain how I would be sure that nobody establishes a dependency on a class constant that isn’t intended for public consumption (ie, is subject to change in future versions).
Although PHP allows programmers to declare classes and interfaces, it does not support packages or modules. Instead, programmers must use a system of includes that’s even more primitive than that provided by the standard C preprocessor. Not knowing this, I moved a bunch of SQL statements used to populate data in a page from the script that generated the page (view.php) to a data access object, declared in a file called ViewDao.php.
One of the methods in ViewDao.php returns a simple data container object (think ORM, a representation of a row in a database table as a simple object). We’ll call the container class Individual and declare in an a file called Individual.php. Wanting to separate the viewable pages from the OO backend, I created a directory called ‘classes’ and moved both ViewDao.php and Individual.php into the classes directory. In the filesystem, the directory (classes) and the script (view.php) are siblings. I added the line
at the top of view.php and in ViewDao.php, I added the line
Switching over to my browser, I discovered that this approach is a great big ball of fail. The error messages were indecipherable and the failure modes unacceptable, but that’s another story. After putting in some debugging prints, I discovered that view.php was including ViewDao.php correctly, but then when processing the contents of ViewDao.php it could not find Individual.php, since it handled the include from the context of view.php rather than ViewDao.php. However, it would be incorrect to include Individual.php as
since the relative path from a script to the file Individual.php is not constant!
It turns out that the PHP solution to this problem is for every script to register a function that finds and includes the code for any class that’s used, based on the name of the class. If your web app is large enough to include multiple directories containing classes, your class loader needs to be sufficiently intelligent to find and include the right file (again, given only the name of the class). And, this function needs to be registered in every script that loads classes, thereby increasing the amount of idiotic boilerplate making up each PHP file. How to do this? Not surprisingly, it involves includes!
PHP also suffers from having a weak toolchain. I haven’t explored the debugger yet, but my colleague assures me that it’s very slow. Presumably because the language has weak typing and a backwards system of includes, the IDE support for PHP is far weaker than for Java. Neither Eclipse nor NetBeans support automatic code refactoring, finding uses of variables or classes, or code generation (I hate writing my own getters and setters). Given such an inadequate toolchain, it’s not surprising that so much PHP code exemplifies bad coding habits. The language does not encourage developers to write modular, reusable code.
I’ve gotten this far without mentioning another peeve: PHP has evidently only recently come around to supporting prepared statements, meaning that countless PHP scripts construct database queries on the fly using concatenation. Unfortunately, the number of PHP scripts that correctly escape user input is fewer (remember Bobby Tables?).
Since I’ve got a basically working prototype, I don’t think I can justify rewriting the entire application in Java, but I think this will be my last foray into PHP if I can help it. Instead, I’ll simply marvel at the websites (Wikipedia) and the frameworks (Drupal) that use PHP extensively and successfully.