On HAML and jQuery 2
I just got carried away, responding to "another blog post":http://www.toohardtopronounce.com/code/2009/05/02/on-haml-and-jquery/. I spent enough time on that comment, I thought I'd post it here as well:
When I found HAML at its inception, I found something powerful that I couldn't explain. I told people it was because I didn't have as much noise in my templates, but there was something more powerful about it than just that. I've realized that simplicity is a form of power: it saves me time, but it also begins to unveil meaning to me.
A simple thing embodies the task at hand. The egg-shaped handle for a kitchen utensil, seems to say, "hold me." Quiet HAML seems to say, "shape meaning with me." As a handle is built for holding, I realize that template languages are for structuring. HAML invites me to engage in the meaning of a document by seeing the structure rather than the syntax.
And, I find that using HAML, I adapt my templates more quickly. That's partly because it's much more expensive to change HTML than to write it. HAML is easier to write, but MUCH easier to edit. If I move something with HAML, I don't have to chase down a closing bracket, somewhere else on a page. I just move the content I am working on.
The web is not HTML, it is a universal expression of meaning. We build web applications and pages because we mean something by them. HAML, then, didn't add an abstraction layer, it removed one. It did this by the laws of reduction: shrink, hide, and embody.
Yes, there are those pesky moments when I miss a space, or a tab sneaks into my white space somehow, and all hell breaks loose. I have to go and find out what's wrong before I can move forward. The act of keeping my HAML pristine, however, leaves me with a sense that I actually accomplished my purpose, I presented my meaning in a clean and orderly way.
jQuery seems to do the same. It is not Javascript, and so doesn't try to take over the Javascript space. It humbly offers its services, unless they are otherwise engaged. Non-jQuery objects become jQuery objects with a simple $() wrapper around them. Lists and single items behave in the same ways, so that unnecessary object inspection is hidden away from my code. The selectors simply embody most of the selectors I've already come to know. jQuery doesn't try to add layers, but remove them. It implements server communication through GETs and POSTs with $.get and $.post. It makes it as easy to extend the library as it is to use it. It presents itself as a designed library, rather than just a slipshod collection of methods and features.
AJAX: Big Picture
I've been baffled by AJAX. Maybe I lack the imagination to work through visual problems and create interesting solutions. Maybe I get stuck on the details and don't ever get to see the big picture. Probably I get overwhelmed by the difficulty of all the exceptions a good designer needs to know. Certainly writing front-end code feels a lot like eighth-grade composition: a lot of rules, and little outstanding progress.
So, I took a step back this morning and started to look at the big picture. I read code from books and projects I admire, comparing and contrasting what I saw. Here is what I saw:
Using any Javascript functionality requires a server-side foundation. For me, this is jQuery and the plugins I choose to use. It involves questions of caching, the order code should be loaded, and managing the paths where things are kept. It pays for me to slow down a little and say out loud what I'm doing here, asking and answering questions. That's because I haven't setup these things enough times to self-correct if I make a little mistake. It also helps when I hear myself say: I'm putting this feature in application.js because it really is a foundational piece that affects the whole site. That way, I don't feel like I'm building chaotic messes with my Javascript. I realize that this is one of the main blocks I have to this kind of work: I started learning it when it was a real mess, much worse than it is today, and so I don't get that balanced feeling that I get from well-written Ruby.
Good Javascript is unobtrusive. This reduces the pains of maintenance by a large exponent. I lay out the content as structured outlines, and I attach behavior and style to that outline with CSS patterns. This process can be iterative if I'm patient. It feels more like writing regular expressions than designing a class. I don't have to figure it all out at once, I can ask simple questions and come up with simple answers. The critical issues is whether I keep going, or allow myself to get flustered and impatient.
I have mostly ignored the interface between the client and the server in years past. These were details that web server architects had to deal with, not web developers. Most of my work was just serving up HTML in the early years, and I was content to follow recipes for delivering that content. I didn't bother much with headers, content types, formal interfaces, and that kind of thing. Writing good AJAX means I know a bit about the data being transferred, since it can be in several different formats. For instance, I'm aware of delivering AJAX as JSON, XML, HTML, or Javascript. All of these are valid and have their uses. On the server side, I need to make sure Rails understands what it's getting. This could mean setting the request header to "Accept", "text/javascript" so that Rails understands what kind of data is coming in. It could mean setting headers with
response.headers["Pragma"] = "no-cache"
or
response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
without knowing the evolution of browser features that lead to this type of code. To me, this is all jibberish. I wouldn't know to consider no-store, no-cache, or any kind of age. I wouldn't know where to go to look up that kind of information. For all I know, that is a secret incantation from the deep magic of designers.
I've seen that there are simple ways of telling Javascript about model state. In Rails, we can call an ERB template that has script tags with javascript variables declared. Then, it can include a set of events and functions that a particular page will need to function properly. Those functions can depend on the values of those variables, changing the behavior of the page dramatically.
I see that there are many ways to solve a particular problem. I don't read the right kinds of blogs to hear about the relative strengths of each one. I wasn't introduced to this kind of code the way I was introduced to data modeling. I don't see grace in the making, only as a finished product, so I don't fully appreciate what it takes to actually create such things.
I think this article uncovers that I'm still grasping for a big picture when it comes to designing usable Javascript-driven sites. What little structure I have right now is:
- Build a simple and solid foundation with the server. Make it jQuery + some plugins. Take the time to get it right.
- Make my javascript unobtrusive. Write callbacks and CSS selectors in small steps. Build a pattern across the pages slowly, over time. Take the time to refactor my presentation organization, I can't know all that is happening at once.
- Respect the work browsers are doing. Take the time to look at headers. Use Firebug's Net tab to see what's actually going across the wire. Compare sites that work with my own work to start to tease out the differences.
- Build up simple feature sets per page. Don't try to architect this stuff from my station at this time. After a while, I'll see patterns and come up with my best practices. Don't get ahead of myself on this stuff. Just keep the code DRY, refactor, keep an audible dialog going so that I don't get ahead of myself.
- Surround myself with better ideas. Instead of snacking on this kind of stuff every once in a while, find a steady diet of it. These are some of the resources I've found: "Scott Olson's blog":gscottolson.com/weblog/, "5 ways to make AJAX calls with jQuery":http://net.tutsplus.com/tutorials/javascript-ajax/5-ways-to-make-ajax-calls-with-jquery/, "the jQuery blog":http://blog.jquery.com/. This isn't good enough, but it's something.
Anyway, these are notes for the next person walking down a similar path, for what they're worth.