Made of Everything You're Not

Because there's too much info for my brain.
  • Home
  • Projects
  • Portfolio
  • Resume
« Validation; Don’t Waste My Time
Facebook Connect Primer »

Shifting Requirements = Better Coder

So often in the development process shifting requirements can wreak havoc on the entire project. But sometimes, every once in a while, if the moon is in just the right place and the wind is blowing in the proper direction, you can walk away a better coder for it.

Rhino

Rhino

Take for example my recent experience integrating the FriendFeed API into a client’s site.

Pop Quiz

The client has a website that utilizes the FriendFeed API, on the homepage only, to display information about their online activities. Basically, they want the site to be updated automatically whenever they update their MySpace or YouTube pages and the like. They’ve specified the layout to be something like the below:

“ClientName” just published a piece titled “Title” on “Site”. Published “X hours ago”

Pretty simple right? An obvious design would go something like this:
1. Connect to FriendFeed API.
2. Make request for data.
3. Display on the page.

The only issue is the formatting of the date / time difference. No worries though; there’s php code all over the place for that:

function RelativeTime($timestamp){
	$difference = time() - $timestamp;
	$periods = array("sec", "min", "hour", "day", "week","month", "years", "decade");
	$lengths = array("60","60","24","7","4.35","12","10");
 
	if ($difference > 0) { // this was in the past
		$ending = "ago";
	} else { // this was in the future
		$difference = -$difference;
		$ending = "to go";
	}
 
	for($j = 0; $difference >= $lengths[$j]; $j++) {
		$difference /= $lengths[$j];
	}
 
	$difference = round($difference);
	if($difference != 1) {
		$periods[$j].= "s";
	}
 
	$text = "$difference $periods[$j] $ending";
	return $text;
}

Using the above you can just execute the output like the below:

echo $me.' just published a piece titled '.$post_title.' on '.$site;
echo ' Published '.RelativeTime($relative_time);

Feeling pretty proud of yourself you show it off to the Producer in charge of the program and they come back with, “Nice! But how will it hold up after caching is enabled?”.

Well, I hadn’t thought of that (my bad fully)…

The Oh Shit Moment

Turns out, they’re expecting a lot of traffic (or the website is pretty resource intensive; take your pick) so full page caching is going to be required.

The problem is the timestamp; since all output is going to be cached the generated time, “5 minutes ago” or “2 days ago”, etc, isn’t going to change until the cache expires. This is not good…

How I Fixed This (The Wrong Way)

The first thing I did was make the conclusion that if php couldn’t be used then the job of formatting the string is up to JavaScript. “OK”, I thought, “fine, I’ll just port the php function to JavaScript and go about my day.

Here’s what I came up with:

 
function getUnixTimestamp(timeObj) {
	var dateObj = null;
	if (timeObj != null) {
		dateObj = new Date(timeObj);
	} else {
		dateObj = new Date();
	}
	return (parseInt(dateObj.getTime().toString().substring(0, 10)));
}
 
function RelativeTime(timestamp){
 
	difference = getUnixTimestamp() - timestamp;
	periodArr = new Array();
	periods = "sec,min,hour,day,week,month,years,decade";
	periodArr = periods.split(',');
 
	TimeLengths = new Array()
	timelength = "60,60,24,7,4.35,12,10";
	TimeLengths = timelength.split(',');
 
	if (difference > 0) { // this was in the past
		ending = "ago";
	} else { // this was in the future
		difference = - difference;
		ending = "to go";
	}
 
	for(j = 0; difference >= TimeLengths[j]; j++) {
		difference /= TimeLengths[j];
	}
 
	difference = Math.round(difference);
	if(difference != 1) {
		periodArr[j] = periodArr[j]+"s";
	}
	text = difference+' '+periodArr[j]+' '+ending;
	document.write(text);
}

Feeling sure of myself, again, a thought occurs to me that this still doesn’t fix the issue 100%. Sure, the date format will be consistent with the relative requirement, but the feed won’t be updated in “Real Time” so the full requirement isn’t there.

The Real Solution

A better idea would be to use AJAX to populate the area of the site where the blurb will be displayed. Since the AJAX request is independent of the rest of the site caching won’t be an issue. Sure, it’s a little more complicated but by doing an AJAX call the client gets exactly what they want.

The Lesson

Now, I’m not going to go into detail about the AJAX solution, mostly because I haven’t written it yet :) , but, to me, this is the far superior solution.

Admittedly, I was a little frustrated that I didn’t think of the AJAX solution sooner. That is, until I realized how much I had learned going in the “wrong” direction.

I had no idea that generating a UNIX timestamp in JavaScript was “complicated”.
I learned a lot about JavaScript string handling.
I got a quick primer in how JavaScript’s builtin Split function works.
I got a little humility out of the process too.

Sometimes, it’s good to go astray on a project.

Bookmark and Share

Related Posts

Stand Alone ExpressionEngine Authentication
Importing Legacy Users Into ExpressionEngine
CartThrob 2.0 Beta Fun
ExpressionEngine and the Mystery of M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr
Custom Routes With Zend Framework

Tags: friendfeed, JavaScript, php, relative time

This entry was written by Eric Lamb and posted on Tuesday, March 10th, 2009 at 6:00 am and is filed under Code, Programming. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply

Click here to cancel reply.

  • Subscribe: Entries | Comments
  • About Me

    Email Email
    Twitter Twitter
    310.739.3322
  • Categories

    • Brain Dump
    • Business
    • Code
    • IT
    • Programming
    • Rant
    • Servers
  • Archives

    • October 2011
    • August 2011
    • July 2011
    • June 2011
    • May 2011
    • April 2011
    • March 2011
    • February 2011
    • January 2011
    • December 2010
    • November 2010
    • October 2010
    • September 2010
    • August 2010
    • July 2010
    • June 2010
    • May 2010
    • April 2010
    • March 2010
    • February 2010
    • January 2010
    • December 2009
    • November 2009
    • October 2009
    • September 2009
    • August 2009
    • July 2009
    • June 2009
    • May 2009
    • April 2009
    • March 2009
    • February 2009
    • January 2009
    • December 2008
    • November 2008
    • October 2008

Copyright © 2008 - 2012 Eric Lamb - All rights reserved