Coding with Jesse

Keeping a Live Eye on Logs

In web development, you can get really used to getting good error messages. If you're coding in PHP, you come to rely on the web server telling you if a variable is undefined or a file is missing.

Likewise, when you're debugging, sometimes the easiest sanity check is to output some text. You'll find me using echo "wtf?"; die; quite often when I'm trying to figure out why a block of code isn't being executed.

But sometimes, even these rudimentary methods of developing aren't available to you. Maybe error messages are turned off on the web server you're stuck debugging. Or maybe you have a lot of Ajax requests flying around and are tired of peeking at the result of each request.

Log files to the rescue. Nearly every framework and server has logging functionality. Apache usually logs every request, so you can see when images, static files, and other requests are made. CodeIgniter has several levels of logging, including DEBUG, ERROR and INFO. Whatever framework you use, or if you're using one you built yourself, you'll probably find some way of writing log messages to a file.

And if you have a log file that's being updated, you have a way of watching things happen in real time. I'm not talking about opening up the log file every now and then and looking back through it, I'm talking about watching it being updated as it happens.

Let's say you have a web server running Linux and are trying to debug something using CodeIgniter. You SSH into the web server, find the log file, and tail -f it. tail is a command which will dump the end of a file out for you. If you add the -f parameter, it will "follow" the file, printing out any new lines as they are added to the log file.

$ cd thefutureoftheweb.com/system/logs
$ tail -f log-2008-10-23.php

If you're working locally on Windows, make sure you have Cygwin installed. (Cygwin gives you a Linux-style console in Windows so you can do awesome stuff like this.) If so, you should have or be able to use tail in the exact same way. Mac and Linux users should have tail installed already.

Back at my old job, we used to keep console windows open using tail to watch the live web servers, especially after an update. This way we could see errors appearing to users live and could investigate and solve problems that would otherwise a) get buried in the logs, or b) go completely unnoticed.

It can really help to get in the groove of having one or two terminal windows open tailing the logs of the servers you're currently working on. And then if you get the urge to write echo "wtf?"; die; you can instead write log_message('info', 'wtf?'); (or equivalent in your framework of choice).

For further information, check out:

Happy tailing!

Published on October 22nd, 2008. © Jesse Skinner

Using PHP's empty() Instead of isset() and count()

I often work with data arrays in PHP as a way to pass information around or store information in sessions. When you work with these, you can't always assume that all properties are defined. I had some conditional logic code in PHP that was only supposed to execute if an array contained any values:

$data = array(
   'text' => array( 'hello', 'world' ),
   'numbers' => array( 43, 2, 55 )
);

if (count($data['text'])) {
   // do something with $data['text']
}

But then I was in a situation where $data['text'] may or may not be defined. So I was going to update my if statement like so:

if (isset($data['text']) && count($data['text'])) {
   // do something
}

But that looks kind of messy. I don't really like isset() but it is a necessary evil to avoid "Undefined" errors. Or is it?

if (!empty($data['text'])) {
   // do something
}

empty() to the rescue - it returns true if $data['text'] is undefined, or if it is an empty array, or if it is false or null or 0. So !empty() is what I'm really trying to determine, and it works great.

For more info, see: empty() at PHP.net.

Published on October 20th, 2008. © Jesse Skinner

Testing Web Pages with Lynx

If you're not familiar, Lynx is the most basic web browser, found on Unix and Linux servers. There are no photos, just pure text, links and forms.

You're probably wondering why you would ever think about supporting a browser that's based in a console window. Does anyone actually browse the web from a bash shell?

Basically, here's the benefit: if you know it works in Lynx, you know it works everywhere. Lynx doesn't have JavaScript or CSS available, and there are no images. It doesn't get more limited than that.

And actually, a lot of the traffic to your site is viewing things in this HTML-only form. I'm talking about search-engine spiders, bots, and people stuck using text-only devices such as screen readers.

So run through your site with Lynx now and then. You will be able to see at a glance if there is enough hidden or alternate text on the page to be useful to search engines and the blind. You'll also be able to ensure that forms and functionality are available to absolutely everyone, even people browsing under Bash!

Update: I just discovered Seebot, a web app which lets you browse the web the same text-only way Lynx (and bots) do.

Published on October 19th, 2008. © Jesse Skinner

Stop CSS Background Flickering in Internet Explorer 6

I was once again reminded of an IE6 bug I had forgotten about - background images flashing or flickering when the mouse hovers over them.

So, I went looking for a solution. Here's what I found:

try {
  document.execCommand("BackgroundImageCache", false, true);
} catch(e) {}

Works like a charm. Turns out it's due to the browser not caching the background images. This command turns on background image caching.

Do you think this would be good code to add to the core jQuery library?

Published on October 18th, 2008. © Jesse Skinner

Test Driven Development

I had heard of Test Driven Development (TDD), an agile development technique, and I knew people I knew were using it. I started using it recently after I finally learned the philosophy behind TDD.

I had always understood it to be just a method of developing where you just make lots of unit tests. I've tried that and felt it was quite a lot of extra work, rather than just testing by hand as you go. I also thought it was mainly geared to Java-type development and not really web development. It turns out that it was boring and not beneficial because I was writing the tests after I wrote the code!

The secret to TDD is the whole "driven" part. You create the test before you write a single line of code. This makes you figure out what you want to do first, and forces you to structure the code in a way that makes testing easy. Basically, it forces each chunk of functionality to be in its own function, which makes the functionality more reusable.

Here's the basic process:

  1. Write a test.
  2. Run the test. Since you're writing a test before the functionality exists, it should definitely fail because you should be testing functionality that doesn't exist yet.
  3. Next, create the simplest thing that makes the test pass. You can even cheat here if it's easier. The sooner you see a passing test, the better.
  4. Once all the tests pass, you refactor your code to make it cleaner and more organized.
  5. Commit to version control (optional).
  6. Repeat.

You should also make sure you add a test whenever a bug creeps up, or whenever you realise there's some rule or assumption that needs to be made. Essentially, you should make a test any time you change the code. Often enough, you'll surprise yourself that things don't work the way you expect.

It turns out to be a lot of fun, and psychologically rewarding. By that I mean that you have short problems and successes. You see a red bar, solve the problem, and see a green bar a few minutes later. It makes you feel confident that you're building a system that works perfectly as expected.

The tools are definitely there for you:

  • For PHP and CodeIgniter, I highly recommend SimpleTest and/or SimpleTester for CodeIgniter. SimpleTest comes with lots of different test types, so you can test MVC controllers by loading URLs, clicking links, and making sure everything is there as expected.
  • For JavaScript and Ajax, there is JsUnit.
  • You can also do browser-side testing with Selenium.
  • And of course, Ruby on Rails is well known for its built-in testing features.

But even once you have the tools, you might look at your code and wonder where to start. I know I did. Without frequent unit testing, it's easy to end up with different functionality combined across multiple functions.

But you have to start somewhere. For the next piece of functionality you want to add, create a test for it first. This means you'll have to decide where that code will go. But how will you test the output?

It might occur to you that you could test the code easily if it were put into a single function in a library somewhere. This might involve creating a new class separate from everything you've done prior. You can always reorganize your existing code out of it's scrambled mess and into a set of easily testable, separated libraries and classes. You just need to start somewhere.

For more information do a Google search - there's tons written about it, and there are certainly libraries available for all the languages and frameworks you use.

Published on July 20th, 2008. © Jesse Skinner
<< older posts newer posts >> All posts

Contact Jesse

Need help with a project? Any questions about my writing? I'd love to hear from you.

Email me at [email protected]