KevLinDev Rocks

August 18th, 2007

Here I thought I was a ‘unique and beautiful snowflake’. Was all proud of the javascript inheritance scheme I thought NOBODY was doing. Well…KevLinDev SMOKED me. He had his inheritance tutorial up since back in April of 2002. And apparently his tutorial is the reason the approach is used in YUI.

He seems to be a pretty smart guy though and he works on Aptana, so I take some solace in knowing that we think alike ;) And I still haven’t seen a better callSuper implementation (even though I still think its an unnecessary feature). Anyway, way to go Kev, that’s awesome.

The Importance of Tinkering

June 25th, 2007

About 3 months ago, I got onto a .Net project. I’ve been doing java and java web application development for over 7 years now and this was my first .net project…first microsoft code really. I remember dabbling with the clr and getting the .net framework and compiling a simple hello world or something from text pad back when it first came out, but that was it. It has been harder than I expected to get really rolling. Here are some thoughts…from a Java developer just trying adjust.

If you know java, then you can do .Net
“…its just syntactic differences”. Just about everyone says that. I did manage to get pretty far with just refactoring and pairing and such, but there comes a point when you just need to know whats going on under the hood. How are transactions managed, how does the app server work, what is the lifecycle, are there any hooks into it. You need to know these things when you start to venture outside the lines of written code and pair programming. I’d love to tell you I’ve learned the differences and the key points…but I haven’t. Why? Because I can’t tinker with .Net.

One must Tinker
Thinking in code is such a vital part of being a developer. As a java developer, code was constantly taking up residence in my head. Whatever I was working on at the time was being combed over, refined, spun around on its head, crunched down, reworked and just generally evolving as I slept, drove, ate, whatever. So it was inevitable that I’d have something bubble up to my conscious thought and I would HAVE to go code. I’d pull up my laptop and fire up my trusty java IDE and code. Now, I didn’t bill for that time, I don’t even necessarily see it as time spent ON the project. But, it was almost invariably related to something for work, and the project always benefits from the tinkering process. When I moved to .net, I naturally wanted to tinker, all I had to do was fire up the IDE.

Just Launch Visual Studio
Well, ya see, I have 2 problems here: I don’t have Windows (we’ve become Mac people at home) and even if I did, I’m not wanting to fork over the money for Visual Studio. Sure, there are free versions of Visual Studio available (Express editions) but the first thing EVERYBODY says is “But it doesn’t support plugins”. Well, I can get by with that I guess, but the thing is I’d prefer to have the same setup as I have at work…at least as a .net newb. If I’m on a java project I could seriously care less…I’ll fire up text pad and drop to the command line to compile if I was in a real pinch (ie stuck with no network and no ide). But being new to the .net world makes that a bit more of a curve for tinkering especially since just about every walk-through tutorial or example on the web starts by saying “just fire up visual studio”. And since Express doesnt support plugins, that means I can’t do any TDD tinkering either.

So I did bite the bullet and got windows and installed it on my intel mac. Then promptly installed SharpDevelop (a free C# IDE) and began to tinker. Yeah its not the same as work, and its going to be a curve, but its free (well…300 for the OS). It just really sucks that if I really wanted to do this the “Microsoft” way I’d be out about $800 (300 for windows, 300 for VS Basic, and 200 for ReSharper…which is pretty much required for agile development). I’m suddenly reminded why I never got into .net development. Going that route is just a non-start for a dabbling developer.

Where are all the Application Containers?
Now that I can code some stuff up, where the hell are all the app containers? You know, the Tomcats and JBosses and Jettys of the .net space? It’d be nice to code up some web apps too. Oh…yeah…there are none. Its IIS and that’s pretty much it. Ok. I’m pretty sure thats free. What is the file structure for a web application? Can I just drop it in. Oh…well if you google it you get like 4 ways to deploy a web application. Most of them requiring/assuming you have Visual Studio to do it. I KNOW this is possible, and I KNOW it ain’t rocket science…it IS possible to deploy web applications that were NOT written with Visual Studio and do it WITHOUT Visual Studio. But you wouldn’t get that from the folks that write the web ;)

Please, No Hand Holding
I guess my problem with this whole thing (aside from all the cost of course) is that I don’t want my hand held. I NEED to know what is going on under the covers. I NEED to know the environment, how the applications are related and where they live and what their role is. If I were to believe the top hits from my googling, Visual Studio is a required part of .net development…if you don’t have it, you cant really even talk to an app server to deploy your application. You NEED and IDE to deploy your applications? Again, I know this isn’t true, but please someone write about the reality…or kindly point a newb in the right direction.

UPDATE:
Ah let the web tinkering begin: http://msdn2.microsoft.com/en-us/library/ywdtth2f(VS.80).aspx And not a single mention of VS…man I REALLY should rethink my “go to the google” knee-jerk. Anyway within like 15 minutes of this post I went out and had another look at Cassini web server, downloaded the ultidev one and had a hello world web app up complete with an HttpHandler (servlet). Also saw that Cassini is open source…so I’m not sure why there aren’t many more (then again my google kung-fu has really sucked of late).

Interesting Back Button Bugs

May 10th, 2007

I didn’t mention these in the previous post (it was getting too long already), but there were some funky problems we ran into when dealing iframes for the back button. We were using an iframe so we expected that no matter what, if you leave a page and come back, the iframe will still contain the content it had when you left. This simple expectation failed in both ie and firefox for 2 different reasons.

IE:
It took us maybe a full day to figure the problem with IE and it STILL bothers me today because I cannot reliably reproduce the bug in isoloation. IE didn’t like doing ANY dhtml above the iframe that we were using. If ANY dhtml was done above the iframe, the iframe would be ‘reset’ to its original ’src’ when returning to the page via the back button. Sounds similar to the bug with safari that Brad Neuberg describes.

To get things rolling again in IE, we just moved the iframe to the very top of the page. That worked until just the other day. I decided to be fancy and use yahoo’s onDocumentReady implementation. Well I’m assuming they do some dhtml above the top of the body (maybe add script tags to the head?). Regardless, when I removed the yahoo files, the back button magically worked again.

Firefox:
We were seeing the EXACT same symptom: the iframe refused to remember its content. I couldn’t believe it…how did we break firefox’s new back button feature (where it stores the full state of the page including javascript and just restores it when you return…the uber back button fix). In the end, it wasn’t our code at all. We had firebug installed. All we did was disable firebug and the back button was as good as new. I can only suspect that firebug does some rigorous cache flushing or something.

Our Back Button Story

May 9th, 2007

Ah, the back button. That thing users want and don’t understand why it isn’t so simple anymore. Our project has a user story for the back button. It described a specific set of scenarios and what the users expectations were for when the back button was clicked. Suprisingly enough, it was easily one of the biggest stories for us in terms of difficulty and time to implement. I just wanted to talk through our path to making this story work. The back button is a fun, difficult challenge to be sure ;)

For the impatient, I’ll lay it out for you right up front. Put simply, the approach we were able to take to tackle the back button was as follows:

  • Have a client-side model that represents the state of the app (the user’s search criteria in our case)
  • Serialize that model (JSON) and post it to an iframe in response to user actions (actually, ours had a 300ms dirty-check interval that would post to the iframe).
  • Have the content that is loaded in the iframe notify (call a function) on the parent window passing it the result and the model used to get that result (basically just echo back the serialized model alongside the results).

And the longer-winded walk-through:

The site is for a real estate company. It allows users to find listings based on the typical (and some custom) criteria they specify via some widgets on the page. As they make their selections, the results are ajax-erifically loaded for them in the results area. They can page through the results and click on a listing to see further detail. The detail page is a full page load with a restful url.

From what I’ve described so far, the back button should behave as follows:

  • If the user is viewing page 3 of the results, then goes to page 4, the back button should take them back to page 3 of the results.
  • If the user is on a detail page, the back button should take them back to the results (and it should be on the correct page if the user was paging).

Sounds simple enough right? In Web1.0, this is no big deal. The user changes search criteria and clicks ’submit’, server answers with the results and pre-populates the page with the users’ criteria. One full-page load later, the page has everything it needs wired right into its very source code. User adds more criteria, clicks submit and voila, another page load and another full page that has all the data it needs. Click the back button and that first page returns…still wired up with the results AND the criteria for that page…as though the last page load never even happened.

Web2.0(-ish, there really isn’t a social aspect to this app, but its more lively that the typical sites) we want to stay on the same page…just load the results portion. This makes the user experience more fluid as the page reloads tend to be more jarring. It should also be more performant as there is less to render (fewer database queries) and ultimately less data to transfer.

The first task to handle is actually getting some results via ajax, and this is fairly simple. The user makes their selections and an ajax call is made to get the matching results. The results are then plopped into a div on the page when they return. The server code is pretty straight forward, simpler than 1.0 even, because it just has to answer the specific question and render only the results. No need to re-populate the user’s criteria. Now, how to handle the back button?

As described, the back button will do what it was designed to do: take the user to the previously viewed page. When the user is searching in our app, they are only ever on one page, so nothing they are doing is added to the browser history. The actions that they expect to be able to be ‘backed out’ of are not. For the back button to EVER work, we needed to have our ajax code add to the browser history.

One approach (described http://dojotoolkit.org/node/100) is to simply add to the fragment identifier portion part of the url (everything after the #). The browser treats these as links to elements within the current document and will attempt to scroll to the element whose id matches the hash value. So it will add to the history, but it won’t reload the page. In our case, we’d do this for every criteria change or pagination change (switch from results page 3 to results page 4).

At this point our app would be adding to the ‘history’ and the back button would be changing the url…but the results won’t be changing just yet because we don’t have anything to respond to/reset the results when the back button was clicked. Essentially, we need to store some state (the users criteria and the results) with the value we put on the url, so that when the back button is clicked, that state can be restored. That is exactly what the dojo undo and the RSH and others do for us…but we have to have clean urls so adding #’s to the current url won’t do.

The other approach is pretty old-school. Load the results via a hidden iframe. As the user changes criteria we modify the src of an iframe to get the results instead of via an XmlHttpRequest. The iframe src changes are added to the browser’s history as well. We’d need a way to know when the iframe was ready with the results so that the page could pick them up and display them. We knew that some ajax frameworks would degrade to using an iframe approach when a proper XHR is not available…but the simplest thing we could get to work at the time was to have an onload in the result content that the iframe loaded that would tell the parent window what the results were by calling a javascript function on the parent. Basically the results would announce themselves to the containing window. (In hind-site our final approach may be more re-usable if we switch to monitoring the readystate of the iframe via and onreadystatechanged handler).

So at this point, we have results loading in the iframe, then the iframe telling the parent that results were loaded and the parent placing the results on the page. When the back button is clicked, the iframe loads the previous page of results (because iframe src changes are added to the browser history) and the iframe again tells the parent that results were loaded and the parent displays those results. And we still have our pretty urls ;)

However…we don’t have the correct criteria. The iframe only loads the results. So if the user changes the criteria a few times, then clicks the back button, the results will ‘go back’ but the criteria will not change, so they still appear to be the last criteria used. Not only that, but if we load a detail page (those are full page loads) and hit the back button, the correct results page will load, but there will be NO criteria present (because the criteria change on the page dynamically and hence are not part of the source that is restored by the back button…and the iframe that IS restored only has the results). If only the criteria were part of the results…

That’s pretty much what we did. We decided that we needed to have the results page also pass along the search criteria. When loaded, the results AND the criteria used to get those results would be passed along to the parent. Then the parent would render the results and restore the criteria.

The real key in simplifying the back button problem was to organize our javascript into true objects and have a model that could be used to represent the state of the page. That model could be passed around via the iframe and restored with ease in response to the back button. The road to refactoring the javascript to get to this point is another interesting topic for another day.

Thinking out loud, it would be interesting to revisit the RSH and dojo approaches and see if there could be a hybrid to what we needed to do here (or maybe they could already support what we need and we just didn’t see it ;)). I’m thinking like an api that would make an XHR call, then when the results come back, adds a # to the src of an iframe, then puts the result text as well as the model into an input in the iframe. There would be a readystatechanged listener on the iframe that would attempt to restore the state of the parent page from the ‘results’ and model stored in the iframe.

Sorry, no code for this one…just our story.

Binding to Views

March 26th, 2007

I’ve landed on something of a simplified View object that can be used for javascript widgetry. The notion really is that the views are just some template
html string that gets plopped onto a page and bound to a model and a controller. This implementation takes that pretty literally. The View expects a model, controller, peer element (where it should ‘paint’ its template), Template, and Binders. Subclasses should just pass the right thing to the View constructor. The TaskView became quite simple when it switched to using the base View:

var TaskView = function(_task, _viewPort){
	View.call(this, {
             model:_task,
             controller:this,
             peer:_viewPort,
             template:TaskView.Template,
             binders:TaskView.Binders
        });
}
TaskView.extend(View);
TaskView.Template = '<input type="checkbox"/><span></span>';
TaskView.Binders = [
	new ModelBinder(new TagNameLocator('input',0), 'checked', '_complete'),
	new ModelBinder(new TagNameLocator('span', 0), 'innerHTML', '_description'),
	new EventBinder(new TagNameLocator('input', 0), 'click', '_handleCheckboxClicked')
];
TaskView.methods({
	_handleCheckboxClicked: function(event){
		if(event.target.checked){
			this.getModel().complete();
		}
	}
});

What’s going on here? The TaskView constructor just calls the super class constructor with the params it wants: model, controller, peer element, template, and binders. Thats a lot of args, and we may be able to help that with some good conventions. But what are all the args for?

  • The model is the data that the view will display.
  • The controller is meant to handle the behavior of the view. User gestures (mouse clicks and such) are ‘bound’ to methods on the controller via EventBinders.
  • The peer is the html element the view should “paint” into.
  • The Template is..well…the “template” or “mock” markup for the view.
  • The binders are what bind behavior and data to the view. ModelBinders are for binding bits of the model to bits of the view. EventBinders are for binding user gestures (html events) to methods on the controller.

OK, but how does it get put together? The View constructor will set the innerHTML of the peer element to the value of Template and then iterate over the binders telling them to ‘bind’ to the peer. Binders use Locators to find the html elements to bind to. The TagNameLocator will find elements with a particular tagName. Optionally, it will take an index which would make the locator only return the N-th element with that tagName where N is the index provided.

So, in the TaskView, there are 2 ModelBinders and 1 EventBinder. The first ModelBinder binds the ‘checked’ attribute of the first ‘input’ element to the ‘_complete’ property of the model. The second ModelBinder binds the ‘innerHTML’ attribute to the ‘_description’ property of the model. In both cases, the Binder creates a ModelBinding object which becomes an observer of the model and will keep the model and html element in sync. The EventBinder binds a ‘click’ event on the first input to the “_handleCheckBoxClicked” method on the TaskView (which is serving as the controller here).

Not too bad I’d say. Needs some work still though. My first thought is to
take the template and binders out of the call to the super constructor and make them smart defaults. If the super class constructor doesn’t have them in the call, it can look on the subclass for a ’static’ Template and Binders fields. Another thing I’d like to do is have the ModelBinder support methods as well as properties, so it could bind the return value of a method (that way we can bind to ‘getDescription’ instead of ‘_description’).

Maybe tomorrow.

Views Clearing Up

March 17th, 2007

Made some more progress on the TaskList widget. Sure feels like I got off on the wrong foot or something…its been changing a lot. I guess its really just been cleaning up more than really changing. At any rate it is moving along and I’m starting to get a clearer picture of what the views are supposed to be doing and how contained they really can be. Today’s progress was made in the TaskListView2_UT.html.

I’m thinking about heading in a Template direction with it next. I really don’t like the idea of locking up all the markup into javascript dom element creation. Templates are much easier to read and easier to modify. The template work should start in TaskListView3_UT.html.

Smaller Steps or Less Wine

March 17th, 2007

“They” say that you should take small steps when refactoring. Super small steps at first. Then as you become more comfortable with the pace and are more confident in your ability to do specific refactorings, you tend to start taking bigger steps. And if you have some trouble…back off the changes and take smaller steps. I was doing a refactoring last night and I took too big of a step. It took me an hour to finally back off and take smaller steps. I was SO confident in the code I’d written that I was refusing to accept it was flawed. Once I backed off it took one test to find the culprit:

$A = function(){
	var arr = new Array();
	for(var i=0;i<arguments.length;i++){
		var currArr = arguments[i];
		for(var j=0;j<currArr.length;j++){
			arr[i+j] = currArr[j];
		}
	}
	return arr;
}

That logic (problem part colored in red) made perfect sense to me…in my defense I was on my third glass of wine ;)

This is basically prototype’s function that ‘casts’ the provided object to an array. This one supports passing multiple iterable objects (any object with a length property whose members are index-accessible) and it will effectively concatenate them. There is a concat method on an array object, and I’d love to just use that, but you can’t pass the ‘arguments’ variable to the array ‘concat’ method…and that is what I needed to do.) I could have just used prototype. I really like some of what prototype provides, but (I’m sure this has been said before) I don’t want to pull the whole thing in just for a few of the functions I like. Some folks have the same issue with open source java code, but that isn’t as big an issue to me as the javascript one…anyway that’s another post.

Moral of this story: take smaller steps or drink less wine ;)

Not the Simplest Thing

March 15th, 2007

I realized last night I’m probably not *REALLY* doing the “Simplest thing that could possibly work” with this Test First Javascript Widget. If you’re nodding your head thinking “Umm…yeah, you could do that with like 2 lines of javascript” you’re right. With the simple requirements I listed, you could accomplish the TaskList with and input and a button with an onclick that adds a row to a table with a checkbox. Obviously I’m diggin for more depth in the implementation.

Perhaps its because I’m the customer? I know i’m going to eventually need to persist these tasks, and potentially need to handle a back button. I also (since i also have the customer hat here) know that I’m wanting to support nested sub-tasks. When a parent task is completed, all of its child tasks are marked completed as well…and when all child tasks are completed, then the parent task is automatically marked as complete. If only part of the sub-tasks have been completed, then the parent task is put in a ‘partially completed’ or ‘in progress’ state.

So really I’m coding for more requirements than I’ve let known. I’m not sure if that’s being fair to the process…but its and experiment.

I had a little time to kill tonight so I knocked out some refactorings that I was itching to do. Check them out on the TaskListView test page. (The stuff I did today is about half-way down…I dropped in an HR and today’s date…probably should have just started a new Test file).

Test First Javascript

March 11th, 2007

I want to try an experiment. My goal it is to demonstrate how good OO principles and patterns can be applied when solving a problem with javascript. To achieve this goal, I’m going to develop a custom javascript component Test First and try and document the process as I go. I’m hoping this will also help me with some ideas I’m struggling with in the javascript component arena.

The component is a Task List. The first set of requirements are:
The user can add tasks to a list
Tasks are just a short description of what is to be done
The tasks can be marked as complete

The tasks won’t be persisted right now. It will just be in the browser. I know thats not a lot…but I’m the user and I can clarify as we go ;). Each page in this experiment is a JS Unit test page. I’m gonna do my best to communicate what the thought process is for each test and for each refactoring. The ‘thoughts’ will be followed by the test code and then the Task List code that made the test pass. Changes are in red. The test code background is blu-ish…and the code background is gray.

I’ll post more blog entries as the component progresses. You can follow the progress of the tests here. Each test page will link to the next at the bottom. At the top of each test page is a link to open the jsunit test runner for the page.

Selenium Remote Control

August 1st, 2006

So, as you might have guessed by my previous post, I’ve been playing with selenium more and more of late. I totally forgot about my JSUnit + Selenium + JUnit post! Since then, Selenium was split into 2 parts: Selenium Core and Selenium Remote Control (Selenium RC). Selenium RC is really nice. As I suspected, it removes the need for the SocketBasedCommandProcessor I had written.

In short, RC comes with a server-side component that acts as the host for the selenium code as well as a proxy. When you connect to it (using the selenium-driver client: DefaultSelenium) and tell it to launch a browser, the server will configure the browser to use the server as a proxy…then open up the browser to [url of app under test]/selenium-driver/SeleneseRunner.html. Since the server itself is acting as the browser’s proxy it will handle all requests for /selenium-driver/* directly and let all other requests go where they were intended to. This makes the browser think that the selenium code is sitting right along-side the application under test and side-steps the same-origin-policy. Pretty Sweet.

With Selenium RC you can have completely separate Test Projects. The application under test doesn’t need to have a single reference or artifact of selenium in it. You could also use it to write automated scripts that will do some task on a website. For example, you could probably write a simple Swing-based wordpress publishing tool…then write your posts in it…and click ‘Post’…then it would login to your site and publish the post for you.