How Technology Choice Can Impact Your Design

Whenever we consider using a new framework, library, or technology, we always take a look to see what features it has, how fast it is, how it impacts our memory footprint, etc. We tend to focus on how the technology meets our current needs but sometimes forget to consider how the usage of this technology will impact the design of our system going forward. Whenever we incorporate something new, we also adjust how we do things to match what the technology is expecting. If you don’t, most often you will seriously regret it later when you have to jump through fiery hoops to get simple things to work. When dealing with the client layer, this becomes a highly visible change to your system...not by the user but by anyone looking under the hood. For example, when you start using Prototype, you will most likely also start using a lot of ids in your DOM. We do this because Prototype provides us with the handy $(“id”) function, which encourages us to reference individual elements. This also allows us to continue writing the rest of our JavaScript in a procedural manner. The entire library is designed around working on individual elements in the DOM and not groups. Sure they provide $$ for CSS selectors and the invoke function for dealing with arrays, but whenever I use Prototype I feel like this was an afterthought. Although being a more verbose way to write JavaScript, it allows us to write in much the same manner that we do on the back end. Whether your system is Java, .NET, or Ruby, the vast majority of your developers are probably not very functionally oriented. This style is also largely due to Prototype’s origins with Ruby on Rails. Prototype works in a very Ruby-esque manner in many ways, such as how it enhances existing DOM elements instead of just encapsulating them and providing new objects. When we work with jQuery on the other hand, we see a complete 180 on the approach. There is no distinction between a single element or many. Everything is accessed through a CSS selector, so you no longer feel the need to reference DOM elements individually. Also, DOM elements are not enhanced, they are encapsulated by the jQuery object. When we use the $ function, we always get a jQuery object back, so there is little need to check for results or loop through the elements. We simply invoke methods directly on the results and it works the same whether there were 0, 1, or a thousand objects returned. The entire framework is designed around the however-many concept, which encourages us to think differently about the DOM and our JavaScript. Because of the CSS-selector-only approach, I find myself using very few ids at all and the way my functions end up is completely different than it would be if I had used Prototype. I end up taking more time to analyze the DOM to keep it cleaner and more lightweight. I make very heavy use of CSS selectors and when I use the “colon” attributes, I end up eliminating the need to perform checks on the returned objects. All in all, my DOM and JavaScript end up being much more condensed when I write with that mindset. I am not saying that one approach is better than the other, just that it drives many other decisions and the way other aspects of the system will be implemented. The next time you find yourself evaluating a new technology, remember not just to look at how it meets your needs, but what impact it will have on the way you do things going forward.

CSS? The DOM? I'm a developer. I don't care about that.

This is the common mindset of most developers. Most of us think that the DOM and CSS are just output from the server that gets displayed in the browser. I know, I used to be in that camp. It used to be easy to ignore it and get it just good enough so that it would look right in IE. We have been going like that for years now and it has been working, right? Well, not really. As we see Web 2.0 applications becoming more and more common, that mindset is becoming very troublesome for both development and maintainability. JavaScript has become a large piece of most sites and if it isn't well designed and reusable, it can easily become an unwieldy beast. This is where CSS selectors enter the scene to help us write more compact JavaScript that is loosely coupled to any given page. The DOM and CSS now play an important role as metadata to drive the JavaScript. Using a library like jQuery or Prototype, you can reduce most, if not all, of the utility code that you would normally have to write yourself. You also get cross-browser compatibility as an added bonus. By far the most important aspect of these libraries, however, is the ease of using CSS selectors to gather DOM elements. We can now look at CSS classes as more than just aliases for style tags...they can be used to flag DOM elements for easy manipulation by your JavaScript. For example, let's say you are displaying some sort of data list on your screen that has some singular items and others that are expandable groups. In the old days, you would most likely put an onclick="..." attribute somewhere on the expandable items and embed some JavaScript on your page to show and hide the elements. By using a CSS selector instead, you can separate your JavaScript completely from the DOM and flag the expandable items with a CSS class. If the class name is "expandable", the code might look something like this: $(".expandable").click(function() { $(this).next().toggle(); }); Using jQuery in this instance, we have written some very simple and easily readable JavaScript that can be applied on any page whether there is an expandable class present in the DOM or not. We also avoided generating JavaScript from our back end code, which helps keep our codebase cleaner and makes it easy to unit test our JavaScript. This code can now be moved to an external file, minified, and gzipped to reduce the payload sent to the client. Also remember that when you embed onclick elements in your DOM, you are repeating code over and over and preventing it from being cached, increasing load times and bandwidth usage. The above example is just the tip of the iceberg with what can be accomplished with CSS selectors. Classes are just one of the many things you can key off of, so if we had some more complex logic that required us to run the "foo" function on page load for all text input tags, anchor tags with a rel attribute of "crazy", a div with an id of "meatball", and images with an alt attribute containing the text, "chocolate", we might do something like this: $(document).ready(function() { $(":text, a[rel='crazy'], div#meatball, img[alt*='chocolate']").each(foo); }); As you can see, this is a very versatile and powerful tool. We need to get out of the mindset of purely imperative coding in our JavaScript to take full advantage, but once we do a whole new world is opened up. Now that we see how CSS can be leveraged by our JavaScript, how does the structure of the DOM fit into all this? First, having a simple DOM means that you will have simpler selectors when you are dealing with more complex logic. Second, keeping your DOM lean will allow you traverse the elements very easily. In the first example, I am assuming that the DOM element that is "expandable" is immediately followed by the element that will be toggled on and off, allowing me to simply call "next()" on the result of the selector and move to the next element. Let's say we are doing something a little more complicated, such as a row that contains a clear button and five inputs that may be text, selects, or a combination of the two. Traditionally, we might hard code the names of the inputs and run a "input_name.value = '';" for each one in the onclick for the clear button. Using jQuery, we might do something like this instead: $("a.clear").click(function() { $(this).nextAll(":input").val(''); }); Once again, we have taken something that would have been a horrible hard-coded mess and turned it into something easily reusable on multiple pages. We cringe at the thought of hard coding, duplicating logic, and writing unreadable code on the back-end, so why do we so often write it that way on the front-end?