Archive for April, 2009|Monthly archive page

Marketing

It’s time.

My web tool is starting to show slivers of promise! This in no way correlates with functionality; it’s still 99% incomplete. But, my goal has been to get to the point where I can *explain* my concept to someone, who can then explain it to others – i.e. investors, customers and future employees and work with me to morph the idea into something we can build and sell. I think I’m close enough to start looking for that person.

I have a few friends and relatives I’m hoping will help me get started on the search.

In the meantime, if you are or happen to know someone who might be this person, please let me know.

Interface

I’ve been working on the web tool interface recently. I don’t have much to write about, since it mostly involves me reading about design, trying ideas, learning about new YUI components, etc.

I’m trying to decide exactly how structured to make the test case editor right now. Free-form? Free-form with tags? Structured lines, but free-form within the line? Or, not free-form at all and build everything from structured tags. I would give an example, but I don’t have anything that I can show yet.

I have many conflicting goals: it needs to be *fast*. Fast to enter, fast to work with imported tests and fast in terms of the actual UI responsiveness.

On the other hand, almost all “add ons” will need structured data. It is very difficult to do processing on free-form data.

My Synchronous Javascript Solution

I wrote about the problem I was having with the asynchronous (albeit single-threaded) nature of Javascript in my last post.

After looking at the options to make my code more clear when using asynchronous calls in Javascript, I’ve decided to take a simple approach. Instead of using one of the libraries, I’ve come up with what is basically a different way to format my code.

I can’t tell if this will be my long-term answer yet; I’ll just have to get further into the project and see how it goes.

So, here’s what I did. First, I wrote a function to do the actual asynchronous call. The only special thing about it is that it returns TRUE or FALSE, plus the return object.

PX.Rest = function (method, url, data, callback) {
    var successHandler, failureHandler, makeRequest, request;
    successHandler = function (o) {
        callback(true, o);
    };
    failureHandler = function (o) {
        callback(false, o);
    };

    makeRequest = function () {
        YAHOO.util.Connect.initHeader('Content-Type', 'text/json', true);
        request = YAHOO.util.Connect.asyncRequest(
            method,
            url,
            { success: successHandler,
              failure: failureHandler,
              connTimeout: 8000
            },
            data
        );
    };
    makeRequest();
};

Now, this lets me write my code like so:

// The first AJAX call.
PX.Rest(method, sUrl, jsonData,
    function (result, o) {
        if (result) {
            // If I'm here, it means the initial call was successful.

            // The second AJAX call (for example, to tag the record I just created).
            PX.Rest(method, sUrl, undefined,
                function (result, o) {
                    if (result) {
                        // The second call passed also
                    } else {
                        // The second call failed (after the first call succeeded)
                    }
                    // Code that runs no matter if the second call passes or fails
                }
            );
            // Code that runs when the first call passes but BEFORE the second one returns.
        } else {
            // The first call failed.
            // In this example, I don't do anything else.
        }
    }
);

Now it flows!  It’s almost like using nested if statements.

Here’s why I (think) it works:

  • The arguments are ordered in such a way  that the last one is the callback. This allows you to simply indent it in order to make it obvious you are inside conditional code.
  • The PX.Rest function from above returns TRUE or FALSE, which allows me to use a ‘If (request)’ in-line. That way, I can continue to simply indent and don’t have to create separate callbacks, define them ahead of time, etc.

I certainly don’t think this is a perfect solution, but it does allow me follow the flow of my code much more easily. I wouldn’t want to go more than two or three calls deep, though!

Wrapping my head around Asynchronous Javascript

Most of the Javascript I use involves AJAX. Even before I really knew how to program in Javascript , my first cut & paste programs were AJAX simply because of the site I’m building. As I get deeper into the coding, trying to get multiple parts of my site to work together, the asyncronous model is getting harder and harder to work with.

Here is a simple pseudo-code example:

myFunction = function () {
    successHandler = function () {
    }
    failureHandler = function () {
    }
    ajaxSetup = function () {
    }
    ajaxSetup();
}

That’s not too bad. As I’ve said before, I think it’s a bit verbose, but workable.

Putting it into the regular flow of code is harder. Here is my (made up) example:

  1. Create a new window
  2. Get data from the server
  3. Format the data with links
  4. Update a counter on the server

In pesudo-code again, it might look like this:

createMyWindow();
myFunction = function () {
    successHandler = function () {
        formatTheData();
        myCounterUpdate = function () {
            myCounterUpdateSuccessHandler = function () {
            }
            myCounterUpdateFailureHandler = function () {
            }
            myCounterUpdateajaxSetup = function () {
            }
            myCounterUpdateajaxSetup();
        }
    }
    failureHandler = function () {
    }
    ajaxSetup = function () {
    }
    ajaxSetup();
}

Yuck! I actually have some code like this and was just going to deal with it. But, one of my flows required a third layer.

I simply can’t maintain any sense of the program with so many layers! So, I went looking for solutions and found this blog post by Harry Fuecks. It’s a couple of years old, but seems to capture exactly what my issue is and has some solutions. One is called Narrative Javascript and another is jwacs.

I’m not sure I like any of the solutions, though, since they involve adding a lot more code. But, I’m still wrestling with this issue, trying to re-factor a bit to gain control and see what other solutions there might be.

“Dime a Dozen”

I’m searching for a co-founder. It’s not easy. I’ve been attending group meetings and events for months where the kind of person I’m looking for might attend, but haven’t had any luck (yet).

My latest idea was to simply post an ad. I’ve had great success selling, giving away and buying things on Craigslist, so it seemed like a natural choice.

I think of Craigslist as free, but quickly remembered that they do charge for some things and job postings in the San Francisco Bay Area are one of them. I didn’t really want to spend $75, so I choose the Gigs/Computers area instead of Jobs. So far, so good.

I then wrote what I thought was a very clear and simple add. I clicked “No Pay” at the bottom (no bait and switch here!). After I posted, I quickly received a response for a company who was selling the services that I menteioned in my ad. So far, so good. And, fast!

Then– wham! Flagged.

Flagged?! Why?

I re-read the Terms of Service and was sure I was fine. So, I posted my query to the discussion board suggested in the message and found out right away what the issue was: people want to get paid. And, even though my ad was not against the Terms of Service, they hate “no pay” ads.

  • A dime a dozen.
  • Everyone wants a free geek (hey! I’m the geek here!).
  • People just want to pay their rent.
  • No Pay – No Stay.

Here’s the actual ad, in case YOU are interested.

I’m building a web tool for software test design (QA, basically) and need someone who can make it look good. I have ideas in terms of the functionality and some vague ideas about how it will look, but have zero ability to actually make it gel in terms of design.

Since I have the technical skills,  I’m not looking for a framework or a turnkey site. I’m specifically looking for someone who can create a look and feel, including colors, typography, graphics, etc. and then put it all together using CSS, HTML, graphics and fonts. I’ve started  using Yahoo’s YUI, so experience or a desire to learn how it works is necessary. Knowledge and expertise in user experience would also be great.

My goal is to get this tool working to the point where I can give a demonstration,  then start looking for funding. In the meantime, I’m out of a job and working on this full-time.

So, are you interested in being a co-founder? Having some kind of deferred compensation? Out of work and bored and want something to add to your portfolio? I’m open to pretty much anything, so if you are the person that I’ve described above, let’s talk!

Managing a non-trivial amount of JavaScript

Even though I’m still new to JavaScript, I’m using it most of the time now. My initial attempts with copy & pasting code, watching YouTube videos, reading blogs, etc. were not getting me up to speed fast enough. I also came to realize that I had some fundamental misunderstanding about the language. So, I took a break and read Douglas Crockford’s JavaScritpt: The Good Parts. How refreshing!

Now many of the  issues I was having, especially when comparing Perl code with JavaScript, had real answers. And, getting some real answers for differences in style of JavaScript code had some actual answers as well (due to things like the automatic semi-colon insertion).

My biggest discovery of all is the “Method Pattern.” (pp. 40-21). Eric Miraglia explains it very, very well in his blog post. This shows how to avoid Global Variable problems, make code more modular and all that other good stuff. It is *very* verbose (in my opinion). But, it works, I understand it and I can build a site with code structured like this with confidence.

With this new knowledge and the knowledge I already had about page size and performance issues with Rich Internet Applications (RIAs), I developed a way to load code on demand. I first wrote a “Loader” script. Then, I wrote a template to use that would interact with the Loader.

An example. Let’s say I wanted to open an interactive window. This window might require CSS files, JavaScript files, markup and data. And, some of it might already be loaded, but there is no guarantee. So, instead of dealing with this when you want to make the call, just call the Loader script with the action you want and let it take care of it.
Examples:
To open a dialog box:

pxLoader.open("dialog_box");

To close the dialog box:

pxLoader.close("dialog_box");

To make this work, I would need a standard set of commands (init, open, close, etc.)

So, if you want to check it out, here is the actual code. I ran it through JSLint with Recommended Options and Good Parts turned on. Be aware that I’ve only used it a bit and so have not flushed out all the issues that will make this truly robust.

Note: px is just a placeholder name. “plain_jane” would become “dialog_box” or “category_dialog) or whatever feature you were implementing. Oh, and I log. A lot.

// Copyright (c) 2009 Brian Estes - All Rights Reserved

/*global YAHOO */
YAHOO.namespace("px.plain_jane");
YAHOO.px.plain_jane = function () {
    YAHOO.log("Instantiating", "begin", "pxPlainJane");

    var example, setupListeners;

    example = function (o) {
        YAHOO.log("examle", "begin", "pxPlainJane");

        YAHOO.log("example", "end", "pxPlainJane");
    };

    setupListeners = function () {
        YAHOO.log("setupListeners", "begin", "pxPlainJane");
        YAHOO.util.Event.addListener(
            "plain_jane_one",
            "click",
            function () {
                YAHOO.log("clicked plain_jane_update", "info", "pxPlainJane");
            }
          );

        YAHOO.util.Event.addListener(
            "plain_jane_two",
            "click",
            function () {
                YAHOO.log("clicked plain_jane_one", "info", "pxPlainJane");
                YAHOO.px.Loader.open('some_package');
            }
        );
        YAHOO.log("setupListeners", "end", "pxPlainJane");
    };

    return {        // public methods
        init: function (o) {
            YAHOO.log(".init", "begin", "pxPlainJane");
            example(o);
            setupListners();
            YAHOO.log(".init", "end", "pxPlainJane");
        },
        open: function (o) {
            YAHOO.log(".open", "info", "pxPlainJane");
        },
        refresh: function (o) {
            YAHOO.log(".refresh", "info", "pxPlainJane");
        },
        close: function (o) {
            YAHOO.log(".close", "info", "pxPlainJane");
        },
        destroy: function (o) {
            YAHOO.log(".destroy", "info", "pxPlainJane");
        },
        exists: function (o) {
            YAHOO.log(".exists", "info", "pxPlainJane");
        },
        visible: function (o) {
            YAHOO.log(".visible", "info", "pxPlainJane");
        },
        ready: function (o) {
            YAHOO.log(".ready", "info", "pxPlainJane");
        }
    };
}();

YAHOO.util.Event.onDOMReady(function () {
    //YAHOO.px.plain_jane.init();
});

YAHOO.log("Instantiating", "end", "pxPlainJane");