Wednesday, June 17, 2009

When Not to Use the Ternary Statement

The ternary operator is designed as a shorthand way to assign a value to a variable based on the result of an expression. The benefit of this is more compact code than the corresponding if/then/else structure. The drawback is that it's slightly less readable. But used properly it can enhance the quality of your code.

An if/then/else statement reads much like an english sentence. The structure can be understood at a quick glance. On the other hand, the ternary operator requires at least a tiny bit thought before you understand what's happening. Some of that mental processing time can be mitigated by using the ternary operator consistently and only where it's appropriate so readers of your code can build familiarity with how you're using it. What is the appropriate way to use it?

I'm a supporter of keeping lines of code shorter than 80 characters. That idea is certainly up for debate and is the subject for another post but just for now let's assume that anything longer than 80 characters is going to wrap and will greatly decrease the readability -- not to mention beauty -- of your code. It makes sense then to keep your ternary statements under 80 characters. This can be difficult since you're dealing with four different entities: a variable, an expression, the true condition and the false condition. With all of these things having to fit on a single line each part needs to be extremely terse. If you want to maintain readability anyway. My rule of thumb is that if I can't keep a ternary statement under 80 characters then it gets converted into an if/then/else structure. Readability is more important than conciseness in my book. Let's look at some examples.

Good Example:

$foo = ($_GET['foo']) ? intval($_GET['foo']) : 0;

You might see this in a typical web application today. You want to initialize a variable to whatever was specified as a request parameter or a default value if a request parameter wasn't given.

Bad Example:

$foo = (count($articles) < $min_article_count) ? get_articles_by_genre($status, $author, $site_id, $genre) : get_hot_topics($board_id, $platform_id, $min_date);

You really have to comb through that statement understand what's going on. Every time someone comes across this in the code they're going to have to stop and figure it out. This example isn't even as half as bad as some of the stuff I've seen in the wild. The above would be better written like this.

if (count($articles) < $min_article_count) {
$foo = get_articles_by_genre($status, $author, $site_id, $genre);
}
else {
$foo = get_hot_topics($board_id, $platform_id, $min_date);
}

Big difference. The lengthy ternary statement when broken up into multiple lines in an if/then/else statement becomes much easier to read. You get a sense of the logic very easily.

Another Bad Example:

foreach (innitech_comment_operations($arg == 'approval' ? 'publish' : 'unpublish') as $key => $value) {
// stuff here
}

Some programmers feel compelled to stuff as much logic into a single line as possible. I don't understand this.