PhpRiot
News Archive
PhpRiot Newsletter
Your Email Address:

More information

Debugging

Note: This article was originally published at Planet PHP on 15 December 2010.
Planet PHP

aoThere are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.a

-a Sir Charles Antony Richard Hoare

As you've already been told, PHP is the language of the quick and dirty, where a developer's tendency is toward laziness (efficiency).

We don't always unit test our code. Sometimes, we take design shortcuts, even though we know they'll hamper us later on. Business constraints tie our hands and prevent us from doing our jobs in an optimal way.

If we consider what Fred Brooks has to say, we realize that the long-term cost of such shortsightedness far outweighs the advantages. In his seminal work, The Mythical Man-Month, Brooks explains, aoover 90% of the costs of a typical system arise in the maintenance phase, and that any successful piece of software will inevitably be maintained.a

Pay no attention to the man behind the curtain

All too often, aomaintenancea means taking a bug report, figuring out how to reproduce it, and patching the affected code. Or, in more serious cases, redesigning part of your architecture.

Fortunately, when it comes to debugging, the Swiss Army knife in the PHP developer's toolbox is Xdebug. Despite the incredible power and utility of this extension, it never ceases to amaze me how many developers haven't installed ita-aor worse, have never heard of it.

Installing Xdebug couldn't be easier. If you're running a real operating system, installing it is the same as installing any other PECL extension; run pecl install xdebug. If you're on Windows, you have to find the correct binary, which can be tricky. Fortunately, the author has been kind enough to provide a tool to help.

Once installed, you can see the benefits of Xdebug immediately. It replaces the plain messages generated by PHP errors and uncaught exceptions with formatted errors, including stack traces. (To see error messages in their full html glory, be sure html_errors is enabled.)

This is kind of a big deal. The most important (difficult) part of the debugging process is isolation, determining the root cause of the bug and where it occurs. In trying to isolate a bug, stack traces are indispensible; they let you know the path your code took to get there.

In addition to stack traces, Xdebug has two php.ini settings that are extremely useful. The first, xdebug.collect_params, specifies the level of detail of function or method parameters you'd like to see in your stack traces. The default value, 0, shows no parameter information, while a value of 4 shows the full details of every parameter. This may be a little much for most situations. I suggest tweaking this value as the need arises.

The second setting, xdebug.show_local_vars, further augments our ease of isolation by dumping the local variables where the error or exception occurred. Set this value to On to see a formatted dump of all in-scope variables.

What you don't see

Using the tools presented above, you should now be fully equipped to go forth and tear through your bug lists with impunity. Right?

Wrong!

Two things Xdebug's variable and parameter collection facilties won't show you are the state of the current object scope (i.e. $this), and access to any data that exists outside of the method.

Rather than brushing this off as a deficiency in Xdebug itself, consider the implications on how you design your methods. The principal cause of software logic bugs is poorly managed state; you're more likely to produce untestable, unmaintainable code by using data that can change unpredictably.

When we think about code that's optimized for predictability, we think of simple things, like string manipulation functions. Consider str_replace(), a highly-testable function. Given any three inputs, we can expect consistent, predictable output. If a call were repeated with the same three parameters, we would get the same result, because str_replace() doesn't depend on any external "/

Truncated by Planet PHP, read more at the original (another 8972 bytes)