mtrpcic.net Writing software since 1932

29Dec/110

Bug Fixes for the Holidays

With the holidays just finished, I've finally got some time to peer into the dank and dusty crypts that are the Github Issues pages on my projects and try to clear out some of the skeletons in those particular closets.  For anyone who has been using PathJS or PollJS, I've fixed all bugs that I could reproduce.  This includes:

PathJS:  Doesn't work in IE7

This ended up being a bug with Internet Explorer 8 or 9 in either Compatibility Mode or Quirks Mode.  IE8+ supports the "onhashchange" event, which PathJS binds to.  Unfortunately, when in Quirks Mode or IE7 Compatibility Mode, this event never gets fired.  The problem?  It's still reported as being supported.  I've added some secondary checks for IE to ensure that the proper methods get fired when in Quirks/Compatibility Mode.

PathJS: "Root Route" doesn't get executed on Android

This was just a condition of certain pieces of code being called in the wrong order.  A simple re-arrangement fixed the problem, and now it works and is tested on Android 2.3.5.

PollJS: Minified file is not up to date

When I fixed the "overwrite" bug in late Novemeber, I neglected to update the minified version of the file.  I've updated the minified file, and it can now be pulled into your projects to fix that bug.

In addition to fixing the issues and bugs on my existing projects, I've also been working on a project that aims to make client-side javascript logging and debugging a lot more powerful.  Expect a release of Lumberjack.js sometime in the very near future.

22Aug/110

Introducing PollJS – Javascript timers made easy.

One thing that has always caused issue when writing web applications is the issue of querying the server for long-running background tasks (generating thumbnails or PDF's, sending batch emails, etc).  Often times these actions are too long-running to be contained in an HTTP request, so a short request is made and an interval is set up to begin querying for the eventual finish.  This isn't a terrible way to do things, but the current implementation was lacking.  For example, to kill the interval you need to assign the returned value of your "setInterval" call to a variable, and clear it out with "clearInterval".  This raises the problem of variable scope.  Now you need to go up and up and up, and declare a global variable to contain this interval, simply so you can kill it later.

But what if that long running job never gets executed during this particular session?  And what if you have many different operations that need this type of implementation?  You've now got your global namespace polluted with oft-unused variables.  That's where PollJS steps in.

PollJS is a convenience wrapper for the native "setTimeout", "setInterval", "clearTimeout", and "clearInterval" methods.  It wraps them with a simple definition method, and extends their functionality with additional options:

// A Basic Example
Poll.start({
    "update_users",
    interval: 1500,
    action: function(){
        alert("Updated!");
    }
});

Poll.stop("update_users");

You can read more about the project, and download the source code on the Github page.

11Aug/110

Javascript Variable History

I recently answered a Stackoverflow Question where a user wanted to know if there was a way, in JavaScript, to check if a variable has ever been a particular value.  Of course, there is no default built-in way to do this, but I provided (what I think to be) a valid answer.  However, after a few minutes, I looked at it and thought that it might be able to help other people as well.  So here it is - Chronicle.  Chronicle lets you define a special type of object, and you can check the history of that object at any point in time.  Here's a quick example:

var isValid = new Chronicle(false); // Default the value to false

isValid.set("not valid"); // Set it to a string
isValid.set(true); // Set it to true

// This will return true if the value inside this Chronicle
// has ever been true, and return false otherwise.
isValid.was(false);

If anyone wants this functionality on your site, it's as easy as including/running the following javascript anywhere before you need to use a Chronicle (as long as it's within the proper scope, of course). Chronicle works in any scope, in any situation.

function Chronicle(val){
    this.value = val;
    this.history = [];
    if(val != undefined){
        this.history.push(val);
    }
}

Chronicle.prototype.set = function(val){
    this.value = val;
    this.history.push(val);
};

Chronicle.prototype.was = function(val){
    return this.history.indexOf(val) >= 0;
};

Chronicle.prototype.toString = function(){
    return this.value.toString();
}
25Jul/110

Documentation – The Nectar of the Gods

Since day one of college, documentation was toted as being of the utmost importance.  It was necessary, at all times and in every situation.  "By god, what does the variable "i" mean in this "for" loop!?" I could imagine my professors mumbling as they read through my code.  Of course, when I was writing that code, it was painfully obvious what "i" was doing.  It's always obvious what "i" is doing - isn't it?

Of course, my example above is a bit simplified, but it proves the point none the same.  No matter how complex the code that you're currently working on may seem, it's always within the realm of understandability.  Step back for several weeks, and walk into the hellish nightmare that is The Spaghetti Abyss, and you'll spend five minutes wondering, "What the hell was this fool doing?" followed by a brief flash of recollection and embarrassment - "Gasp! I am that fool!"

And therein lies the rub.

As soon as I finished my time in school, documentation seemed much less important.  You see, up until this point, students had been documenting merely to get the marks for it.  We documented our code because our grades depended on it.  As soon as I stepped out those doors for the final time, I remember thinking I was free of that nightmare.  I was a good programmer, I could look at code and understand what was happening under the hood; I didn't need an explanation.

Fast forward a couple of months, and I'm at work, trying to solve a particularly bad problem - a problem I inadvertently produced several weeks back, in a module that had since been left to stew in the bowels of a great beast of a project so terrifying, so insidious, it was Beelzebub incarnate (in code).  I open that file, thinking "This will be an easy fix - after all, I wrote it."  Never have I been more wrong in my life.  My undocumented code put a bucket over my head and slammed it with a baseball bat.  It took me several days to fix a bug that was incredibly simple, but my lack of documentation fanned the flames until my ego was burned to the ground.  I wasn't a good programmer anymore; a good programmer wouldn't have run into this problem.

Fast forward yet again.  I need to delve deep within the source code of ActiveSupport.  I'm looking at code written by the deities of code.  These men and women know Ruby from top to bottom, inside out, and to a peasant like me, it looked like they were making use of every trick in the book to get things done.  But, if that was the case, why was it so easy for me to understand everything?  Why was I able to follow along at a nice leasurely pace, instead of having my eyes melt off my face? Oh, I see now...

This code had documentation.  This code had a dictionary beside it, and I could find out what everything was doing every step of the way.  This code was easy.

It takes a situation like the one described above to let you know how important something really is.  You can be an amazing problem solver, and a prolific programmer, but you won't ever be considered one of the best until your code can be understood by thousands of people at a glance.  Now that I've got my own projects, I make sure that I do my best to document every code change.  I try to act like one of the best, because I'd like to be one of the best.

19Jul/112

PathJS and HTML5 History – A Match Made in Heaven

Nobody will argue that the HTML5 History API was a step in the right direction in regards to Web Applications.  Unfortunately, there was no simple, consolidated way that provided a routing mechanic that was both versatile and easy to manage.  As of today, the simple routing mechanic of PathJS is fully compatible with the HTML5 History API.  You get the power of a manual, with the simplicity of an automatic.  Here's how it works:

// Define all your routes as you usually would with PathJS - Simply omit the "#"
Path.map("/home").to(function(){
    console.log("Welcome home!");
});

Path.map("/users").to(function(){
    console.log("Users, users, users.");
});

Path.map("/contact").to(function(){
    console.log("Feel free to contact me via Github.");
});

// Now override the click events for any of your links, and call
// the Path.history.pushState method to invoke the PathJS router.

// This example uses jQuery.
$("a").live("click", function(event){
    event.preventDefault();
    Path.history.pushState({}, "", $(this).attr("href"));
});

It's simple as that.  The PathJS implementation of the HTML5 History API supports the same features as regular PathJS, including:  Before-filter chaining, enter/exit methods, parameterized routes, and optional route parameters.  You can read more about it's features and limitations on the Github Page.

8May/111

Introducing js:routes – Your Rails Routes in JavaScript

I am a strong advocate of clear cut separation when it comes to code.  All JavaScript should be in one spot, should be easy to find, and should be easy to maintain.  Unfortunately, the built-in helpers that Rails provides for doing this (specifically in Rails 2.x.x) can blur my wonderful lines of separation, which is something that has bothered me since the dawn of time.  In addition to this, using the built-in helpers removes you from the nitty-gritty of the code being generated, making you less likely to truly understand what's happening, as well as making it much more difficult to modify it.

Because of the reasons above, I never use these built-in methods.  I much prefer a nice, clear cut separation for my scripts, and I'll handle the work myself.

application.js // Our document.ready wrapper
functions.js // Any utility functions we might want
extensions.js // any jQuery extensions we write
routes.js // All of our PathJS routes

I put all of my JavaScript in it's proper place, and it enjoys life there.  But there's one problem - one minor thing that has always bothered me about handling this myself...constructing URLs.  There has been many times where dragging an item from one location to another needs to make an AJAX call to update a "position" or a "parent_id".  Every time these calls are needed, you'll see some code like this:

$.ajax({
    url: "/books/" + book_id + "/pages/" + page_id,
    data: {
        "position":"top"
    },
    success: function(response){
        alert("Hazaa!");
    }
});

There is absolutely nothing elegant about the way that URL is being constructed.  Well, now there's a better way.

Say "Hello," to js:routes.

js:routes provides a simple rake task that will take all of your existing routes and convert them into JavaScript functions that take the appropriate parameters.

# Calling this will generate ./public/javascripts/rails_routes.js
rake js:routes

# You can name the file anything else by doing this
rake js:routes[other_file.js]

Now, you can tidy up those dirty constructed URL's.

// This...
url: "/books/" + book_id + "/pages/" + page_id

// Becomes this!
url: book_pages_path({"book_id": book_id, "id":page_id})

Everything is nice and tidy.  You can read more about it on the Github page.

1May/111

Accents are a funny thing.

Accents are a funny thing, eh?  Being a native Canadian, I'm constantly told that I sound Canadian.  I guess that makes sense, the same way that someone can sound Texan, or someone can sound British, Irish, or Scottish.  They're all speaking English, but there's definitely something different about each and every one of them.  Whenever you speak, you don't just speak in a particular language, you most certainly have a particular accent.

This got me thinking - When I program in a particular programming language, do I also program in a particular accent? Of course I do.

There are a thousand little things we all do when programming that individually have their own names (Naming Conventions, Indentation Style, Equality Checks, etc), but when you think of them as one combined unit, they construct your individual accent.

Naming Convention

There are so many different possible naming conventions that it's nearly impossible to guarantee that a large development team will all use the same ones in the same situations:

var userName = "Mike"; // Camelcase
var UserName = "Mike" // Upper Camelcase
var strName = "Mike"; // Hungarian Notation
var user_name = "Mike"; // "Ruby" Notation
// And many, many more.

Which conventions do you use in what situations?  Do you name Modules different than Classes?  Classes different than Methods?  Methods different than variables?

Indentation Style

// Do you like to keep your braces on their own line?
function totallyBananas()
{
    alert("Bananas!");
}

// Or with method/class definitions?
function totallyBananas(){
    alert("Bananas");
}

Do your conventions differ for method definitions, class definitions, if/else statements, or other code blocks?  Do you prefer 2, 4, 6, or 8 space indents for different pieces of code?

Equality Checks

// Do you like to check that things are equal?

if(authorized == true){
    alert("Hello, Mike.");
}

// Or inequality?
if(authorized != false){
    alert("Hello, Mike.");
}

Value-First Comparison

We most often see the variable name come first when doing a comparison, but this can lead to some embarrassing mistakes...

var name = "Mike";
// We've all seen this before.
if(name == "Dave"){
    alert(name); // You should never see this!
}

// But this isn't what we meant!
if(name = "Mike"){
    alert(name); // You're going to see "Mike"!
}

Some people have taken to doing "value first" comparisons, which can avoid these mistakes.  Which way do you speak?

if("Mike" == name){
     alert(name); // You should never see this!
}

// This will throw an error.
if("Mike" = name){
    alert(name);
}

There are hundreds of other little things that make up your "programming voice".  Your documentation style, namespacing habits, source file naming conventions, and even your SCM commit messages are all little pieces of what your code sounds like.  So, is your code from the royal palace, or the Louisiana swamps?  Regardless of what your code sounds like, just make sure that your coworkers and colleagues can understand your accent.

16Feb/1126

Hashbang URIs – They’re not as bad as you think; really.

The internet has been abuzz since the suite of Gawker sites switched from regular old links, to Fragment URIs.  Long story short, a JavaScript bug caused all content, on all of their sites, to be inaccessible to the entire world.  Ouch, I know.  But just because one developer made a farce of a piece of technology doesn't make it as horrendous as everyone's saying it is.

A Brief Introduction

So what's the big guffaw all about?  Wikipedia uses Fragment Identifiers to jump around the page, don't they?  Well yeah, but that's just static content.  The big dilemma is over the loading of remote content when a new fragment identifier is loaded.  It's a nice way to load remote content, while still allowing the user to use the "Back" button properly.  Why would anyone want to do this, you might ask?  Well, let me tell you.

Some Numbers

When loading any website, there's two things you pull from the server.  The Markup (HTML), which structures the page, and your helpers (CSS and JavaScript) to pretty the beast up, and make him shine.  I took a look at 4 sites that are kind of a big deal, to see what was being loaded every time I hit their homepage:

Reddit.com
  HTML.: 37.6 KB
  CSS..: 20.2 KB
  JS...: 47.7 KB
  Total: 105.5 KB, 35.6% Content

Google.com
  HTML.: 12.2 KB
  CSS..: 0 KB (Included in HTML)
  JS...: 73.1 KB
  Total: 85.3 KB, 14.3% Content

Youtube
  HTML.: 20.9 KB
  CSS..: 1.3 KB
  JS...: 17.1 KB
  Total: 39.3 KB, 53.2% Content

Github.com
  HTML.: 7.3 KB
  CSS..: 61.5 KB
  JS...: 127.9 KB
  Total: 196.2 KB, 3.7% Content

It looks like nearly every site is loading a lot of stuff other than content, especially Github.  Every time a request hits the server, it has to handle this additional content if it's not cached.  If that's the case taking away the constant loading of the JavaScript and CSS can significantly decrease bandwidth and server load.  In addition to  not needing to fetch the external resources, you also cut down on the amount of HTML required to be loaded with every request, as the DOM structure is only loaded once, and only the content needs to be loaded with every request. In the case of Reddit.com, the majority of HTML loaded is DOM structure and static content, with only 5.9 KB of the 37.6 KB being real, interesting content.  The example below is a rudimentary way to accomplish this, with very little overhead in cost, time, or complexity.

Server Side

There are three things you need to do to make this work, and that's it.  First, make all internal links begin with the root of your site, sans the domain name.  We want things that "/look/like/this".  Next, modify all of your content and views to host the majority of your markup in a Layout of some sort.  Basically, your controller action should only return a block of content that will be placed into the body tag of the layout.  Finally, modify your controller actions to return the content sans layout when AJAX comes calling.  In rails, it would be as simple as:

class WidgetController < ApplicationController
  def index
    @widgets = Widget.all
    respond_to do |wants|
      wants.html {}
      wants.js {render :layout => false}
    end
  end
end

That's it.  Now, when AJAX hits any of your existing controller actions, they'll return the content without the layout.

Client Side

There are two things to do here.  First, you're going to intercept the click of every "a" tag on your site.  This is easy with jQuery:

$("a").live("click", function(event){
    var href = $(this).attr("href");
    if(href[0] == "/"){
        event.preventDefault();
        window.location.hash = "#!" + href;
    }
});

The code block above checks to see if the link goes to a local resource, and if so, intercepts it, stops the link from acting, and changes the Resource Identifier instead.  Now, using a library like PathJS, listen for route changes and act accordingly.  With pathJS, it's as simple as:

Path.default(function(){
    $.get(window.location.hash.replace("#!", ""), function(data){
        $("#contents").html(data);
    });
});

Path.listen();

Now, whenever a local resource link is clicked, it will be picked up and routed to the default function.  This function does an AJAX call to get new content, which is returned without the layout thanks to our controller action changes, and injects it into the DOM.  Fast and easy.  If a user hits your site with JavaScript disabled, the links will never be intercepted, and will go to your regular routes, returned with the layout intact.

But what about...

There are a few things people complain about when confronted with as simple a solution as this:

It doesn't make use of the HTML5 History API!

The example above does not, but the onus is on you as the application developer to build in support for that.  As time progresses, libraries like PathJS will be updated  to integrate with new technologies, but the HTML5 spec is ever changing, and the majority of browser market share doesn't support a lot of these new technologies.

If I have JavaScript enabled, and send my friend (who has JavaScript disabled) a "Hashbang" URI, he won't load the content!

You're right.  This is the primary drawback of an approach like this, and you'll need to figure out if that's acceptable for you.  Are you building a website, or a web application?  Will users ever share links?  What if you're developing an Admin Panel for an internal company tool, an authentication-locked wiki system, or any application that relies on JavaScript to function (image editing, data plotting, etc)?  In those cases, users won't be sharing links, and it's a moot point.  On the other end of the spectrum, you could be building a website, not an application, where users can often share links.  Well, what is your target audience?  Are they likely to have JavaScript disabled?  Is the edge-case of a broken shared link worth the benefits an approach like this provides?  These are all questions that you and your development team need to answer before making a decision.

Won't browser caching reduce server load already?

Yes and no.  In a perfect world, that would be the case.  However, there are a lot of things that can cause the server to send the additional contents on every request, such as  improperly set Headers, browsers with caching turned off/unsupported, clients that don't respect server headers, or any of a multitude of other possible scenarios.  In cases like these, a solution like "Hashbang URIs" makes sense.

Edit: In addition to the cases above, which are unlikely in the best of scenarios (as was pointed out to me by friends and strangers alike), some browsers have a very low cache limit, namely the mobile browser market.

Conclusion

No, it's not perfect.  No, it's not a solution for everyone. Yes, it has drawbacks and downsides.  So what?  It's pushing the boundaries of the browser, and treating the web as an Application Platform, rather than a dumb terminal for reading content and data entry.  The "Hashbang URI" makes your application feel like an application, instead of a website.  The drawbacks are things that need to be weighed against the benefits in your unique case, and the decision will be different for everyone.

Just because it doesn't make sense for you to use it, doesn't mean it's a stupid idea.  You are not the center of the Universe.

Google.com
HTML - 12.2 KB
CSS - 0 KB (Included in HTML)
JS - 73.1 asKB
9Feb/113

Introducing PathJS – Routing for the Real World

As the web experience continues to evolve, more and more people are coming to expect "Web Applications" instead of "Web Sites".  HTML5, CSS3, AJAX, and a ton more acronyms all help us reach the goal of turning our website into something more.  Now, PathJS is here to help.

PathJS lets you route URL hashes to functions in javascript.  These functions can (and likely will) perform AJAX request to populate your shiny Web Application with data and DOM Structures galore.  You can find the code, tests, and eventually examples on the github page.

Now, a brief example:

$(document).ready(function(){
    Path.map("#/home").to(function(){
        document.write("Welcome Home");
    });

    Path.map("#/contact").to(function(){
        document.write("Contact Us");
    });

    Path.map("#/download").to(function(){
        document.write("Downloads coming soon");
    });

    Path.root("#/home");
    Path.listen();
});
22Nov/103

The fine line between “Code” and “Good Code”

I've been spending a fair bit of my spare time working on my current project, and one of the major issues I'm having right now is drawing the fine line between writing code, and writing good code.

How many times have you sat down with a good, solid idea, only to sit and stare at your monitor for 30 minutes because you're trying to think of 30 different ways to accomplish the same goal. You end up asking yourself 10 different questions, each with 10 pros and 10 cons, and you wind up with a very solid understanding of what the end product will do, but you've made no progress towards it.

"Is this going to be DRY enough?"

"Should I use List Comprehensions here?"

"Should these be params to the method, or passed in when the object is initialized?"

I find myself running into this problem quite often, and always come to the same conclusion.  The conclusion that should be at the heart of as much as your logic as possible; Keep it simple, stupid.

When you're confronted with the "Mile-a-Minute Mind" scenario, just sit back and write whatever code comes to mind that gets the job done.  You're not writing good code, you're just writing code. Wow, that was easy?  It's ugly, but it was easy.  Alright, what's next?  Well, you could (and should) write any pertinent Unit Tests for the code you just wrote.  Make them as solid as you can.  Now you've got a product.

Congratulations, you fought through your own indecision, and wrote some code.

Now we're excited.  What next!?  Well, you wrote some code, and you wrote tests for your code.  Now comes the fun part.  Now you can get rid of that code, and replace it with what we've wanted all along; good code.  Thanks to our wonderful Unit Tests, you'll know if your new code is up to the same dastardly deeds as your old code.  Refactor your work of art to your hearts content, until it's as good as it can possibly be.

The moral of the story is that indecision is the bane of productivity.  Don't worry about writing concise code.  Don't worry about writing optimized code.  Just worry about writing working code, then take it from there.  As we say in the world of Test Driven Development, "Red, Green, Refactor."