Get your FREE 30 page Developing SOLID Applications guide!

Validation Blind Spots Hurt Real Users

A friend of mine lives on Bonieta Harrold Drive. I live on a Windsor Hill Drive. Both of us have a problem in common, which is that poorly designed software is incapable of accepting the length of our street address. For me, American Express refuses to accept more than “WINDSOR HILL D”, which still arrives at our home. I can’t imagine if my friend ever got an American Express card, since given the maximum length available for an address, he would live on “BONIETA HARROL”. If you live in a place where direction (e.g. NW, SW, SE) matter, not having enough space can be extraordinarily problematic to the proper delivery of mail and packages if there is not enough room for the whole address.

Clearly, these software systems have a design flaw. That design flaw is that the programmers responsible for programming the software assumed that 20 characters (house number and street information) was long enough for a standard address. It’s likely that in the best case, developers picked 20 characters based on some given experience (e.g. they considered all the street names in their own town in conjunction with known house number lengths, and came to an answer) or worse, simply picked a number out of thin air. Real users are worse off because of it.

(more…)

Data Formatting: It IS Our Job

It’s happened to each and every one of us: we fill out a long form, complete with username and password. We double and triple check everything, because want to make sure the submission works. We verify our email address, our date of birth, and even maybe retype our password, just to make sure they’re both right and they both match. And then we fill out the CAPTCHA, with so much care (passing those things is still random, whether you’re a human or not). And then we hit submit.

And we wait. Breathless.

(more…)

Peer Review: Testable Code And Architecture

This entry is part of an ongoing series involving the review of a code sample and it’s refactoring. For the original code sample, see here.

Now that we’ve worked out the abstraction issues and the logic questions, we should take a moment to focus our attention on a few of the issues relating to the architecture and testability of the class we’ve worked out.

A couple of big architecture issues raise their heads early on. The first one is this set of code:

< ?php
// class_Twitter.php - NPC TWITTER AUTO-FEED
error_reporting(E_ALL); 

// DO NOT RUN THIS SCRIPT STANDALONE (HAS PASSWORD)
if (count(get_included_files()) < 2) {
    header("HTTP/1.1 301 Moved Permanently"); header("Location: /"); exit;
} 

This raises a number of architectural issues that we should address. My recommendation is that we remove this code altogether. The first line, about error reporting, really should be set at the application level, rather than the script level. As for the redirect, this is intended to prevent the script from being called directly. However, it’s a good idea to place classes like this outside the document root anyway, meaning that they would never be called directly. When including this file, there’s the potential that you’ll not have included enough files and you’ll inadvertently redirect your user. So let’s drop these lines altogether. This will improve reusability and improve the architecture.

There’s another line of code that is particularly troubling:

$this->http->setHost($this->baseHost . "statuses/update.json?status=".urlencode(stripslashes( urldecode($message))));

It may not look obvious at first, but this code relies on the assumption that the magic_quotes_gpc directive is set to on.

For those who don’t know, magic_quotes_gpc automatically adds slashes to all GET, POST and COOKIE variables that come into an application. This deprecated feature represents a poor programming practice, and its use is discouraged. Though it remains on by default in PHP installations, it should be turned off altogether if at all possible. It’s slow, and potentially dangerous. Additionally, it will be removed in future versions, meaning that code relying upon magic_quotes_gpc will break in the future.

Now, oftentimes programmers don’t have direct access to the magic_quotes_gpc directive in php.ini, but it can be set on the htaccess level, if your hosting provider allows you to access PHP variables in this way.

I’m going to make the assumption that we’ve disabled magic_quotes_gpc, as is recommended by the PHP manual.

Another problem that we need to address is the fact that this object gets thrown away after it’s been used. We have the property $done, which gets set when a tweet is successful. Unless there’s a good reason for it, objects should never be designed this way. We’ll remove this code in the final draft (see below).

Moving on to testing, again we have to ask ourselves about abstraction. Where testing is concerned, it would be very easy to abstract the testing out of this object. Making use of things like the HTTP_Request2_Adapter_Mock class will help us to “test” the Twitter interface without actually posting a tweet. Unit testing software like PHPUnit will give us reports on code coverage.

If we opt to leave the test code in the object itself, it should be abstracted into its own method. But I don’t recommend this course at all, because testing should be conducted at the application level. Moving testing out of the class also allows us to remove references to the $done property, and remove the $you property as well as the test() method, the $test property, and a large bit of code from the tweet() method. All of this code will then not be loaded on each request of our class. Not a bad improvement.

Something else that we’ll do in order to improve testability is we will inject (rather than create) the HTTPRequest object into the class. This allows us to both inject an object that is a mock object, and it also allows us greater control over the environment when we do our testing.

It was pointed out by the blog PHP In Action that one of the things that we should have done first is write unit tests. I think that this is good advice for most applications. Obviously, the small size of this class make unit testing less critical, but it is a good practice to write unit tests first, and then refactor.

A good example of this is the work being done by web2project with regards to bug fixes. According to Keith Casey, one of the leads on the project, their rule now is that any time a bug is fixed, a unit test identifying the bug must be submitted along with the bug fix. This has allowed them to significantly improve their testing system, and it’s a great idea for existing projects that don’t have unit tests but want to implement them.

Testing is not to be underestimated. Testing allows you to refactor methods and the internal workings of a class, and still know that the results are right. It allows you to work on a very small part of an application without necessarily understanding the whole application, because you can run a unit test suite and see if your code works properly. And writing tests first, even on bug fixes, forces you to think about how you expect your code to work, and face the assumptions you’ve made about that process, as well.

We’ve made a good number of changes to the code, and we’ve made a vast number of improvements. Let’s take a look at what we’ve got:
(more…)

Examining Zend Server CE On The Mac

Zend yesterday released a beta of it’s release candidate for both Zend Server and Zend Server CE (Community Edition). Zend Server is not available for the Mac, but Zend Server CE is, so I decided to give it a try.

There are many good things in this product. Among them, is the ability to easily activate and deactivate most of the plugins and extensions that come bundled with PHP by default. I was able to turn imagick on with no trouble – something I’d been unable to previously compile on the Mac myself (problems with libraries and a lack of time). Most of the extensions are included by default, and it’s easy to configure the directives that PHP has for extensions and core alike. Plus, restarting PHP is as easy as a click of a button.

(more…)

Where Comments Are Useful

PHP In Action writes on the use of comments in code, specifically citing Eli White’s Commenting on Commenting over at PHP Advent. They are critical of Eli’s advice, saying that comments should be unnecessary, and that code should be clean enough to easily understand it.

There’s a lot of good advice, especially about writing clean code. But the article fails to address a good number of really critical details and to some degree misses the point of Eli’s article.

(more…)

Keeping Superglobals Out Of Classes

Have you ever written code like this?
(more…)

« Older Entries