Please join me at my new location bryankyle.com

Monday, April 20, 2009

Arrays and Objects

In Javascript, arrays and objects are different but many people treat them the same. This causes no end of grief because of the underlying differences in what it means to be an object versus what it means to be an array. An object is in essence simply a hash table or a dictionary. Another term for this construct, the term that I believe is responsible for much of the confusion, is "associative array."

The two constructs: hash tables and arrays are fairly similar in intent if you look at them in just the right way. Generally both imply a performant data structure for storing and retrieving data. These structures differ in their implementation, but fundamentally they both provide a way of associating a key with a value. Hash tables allow you to associate an arbitrary key with a value whereas arrays only allow numbers for the keys. Granted, there are usually some caveats to the numeric keys used for arrays. For example, they usually contain an upper and lower limit. But what why does this matter? It matters because this is how Javascript sees an array: as a hash table with numerical keys among some other non-numerical keys. Did I just blow your mind? Probably.

In this regard, arrays in Javascript are no different from any other object that shares the same characteristics. Where it differs is in the fact that an array is an object that is built into the interpreter and therefore has some special privileges granted to it, the main one of these being the "length" property which contains a value one greater than the largest numeric key.

Along with arrays and maps generally come looping constructs. Javascript has several, but the most common when working with objects and arrays is the "for" loop which comes in two flavours: the vanilla C style for loop and the less flexible but just as tasty for-in. The for-in loop iterates over the keys or properties of an object, not its values. It doesn't matter what type of object you're looping over, it will always iterate over the keys. For standard arrays both work fine, for example:

But what happens when someone starts monkey patching arrays, or adding extra properties to an array. Well, the for-in loop will cheerfully give you those keys as well. Maybe this is what you want, but I would guess that if you're looping over an array you probably want its contents not its properties which unfortunately Javascript treats the same.

 

The take-away here is that arrays and objects in Javascript are fairly similar. The language treats both of them in a universal manner which is refreshingly simple on one hand while jarring on the other. The language, like other dynamic languages assumes that the programmer knows what he is doing and stays out of the way.

Wednesday, March 25, 2009

GET Dirty!

Recently I've been working to design some RESTful APIs and I've come into a situation where it makes sense to update server state in response to a GET method. "What? Change state on a GET!? Are you mad? Are you insane? Have you even read the HTTP spec?" I hear you saying. But just hear me out, it's not as bad as you're thinking.

According to the HTTP 1.1 Specification GET is supposed to be both a safe and idempotent method, meaning that it doesn't have side effects and requesting once or a million times doesn't make any difference. So how is it that I can convince myself that it's OK to change state on a GET? Quite simply, by using a little used (in my experience) status code: 202 Accepted.

The HTTP 1.1 specification has the following to say about 202 Accepted (emphasis mine):

The request has been accepted for processing, but the processing has not been completed. The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place. There is no facility for re-sending a status code from an asynchronous operation such as this.

The 202 response is intentionally non-committal. Its purpose is to allow a server to accept a request for some other process (perhaps a batch-oriented process that is only run once per day) without requiring that the user agent's connection to the server persist until the process is completed. The entity returned with this response SHOULD include an indication of the request's current status and either a pointer to a status monitor or some estimate of when the user can expect the request to be fulfilled.

In essence, if a POST is made that returns a status code of 202 Accepted the data can be acted upon at some indeterminate time in the future. That time in the future might just so happen to be right before the GET is processed. In this way, the GET is both safe and idempotent since the state change is only tied to the GET in that it's used as a trigger for processing some previously POSTed data.

Sunday, March 15, 2009

Chrome: The Downside of Process Isolation

When Google Chrome first came out it was apparent that they had thought long and hard about pretty much everything that goes into a browser. One thing that really stood out to me was that each tab ran in its own process. For most surfers this doesn't mean anything, but the caliber of user that Chrome appeals to, at least when it first came out, wasn't your average surfer. Typically a surfer that would use Chrome was a power-surfer. They had many tabs open at any one time, typically one sites that are very resource intensive. For this type of surfer the one-process-per-tab idea was a boon in the event that any one site misbehaves.

If each tab is a process that means that the operating system is free to work with them as independent processes. Since each tab is a separate process the operating system is free to swap the whole tab out of memory if another process needs memory. This is an interesting side benefit since tabs that aren't being used can be completely removed from memory until they are needed. Contrast this with the all-tabs-in-one-process approach taken by every other browser where the operating system simply swaps out pages of memory that haven't been used recently. In essence, the one-process-per-tab approach gives the operating system a hint as to how best to swap the application.

With all of these positives, there has to be a trade-off somewhere doesn't there? In my experience: yes. As a developer I'm typically running a lot of different applications at any one time, this means lots of memory usage. It seems that when switching to a tab that isn't in memory the whole browser locks up. I don't mean simply that the browser doesn't respond to anything you try to do I mean literally it locks up, I can't switch to another application while I wait.

I'm hoping that there is a fix for this issue in later builds because I've switched to using Chrome when I'm on Windows for all of my normal browsing.

Tuesday, March 10, 2009

Tell Me Why!

Whenever I start trying to learn a new codebase, one of the first things I do is try to get an understanding of how the code works at a high level. Generally this isn't too hard, I just find out where the program starts, which is usually pretty obvious, and work through the code from there. But there's a problem I always run into the code only tells me what it does, it doesn't tell me the most important thing: why. Unfortunately, most projects don't maintain a good set of code-level documentation. Instead all documentation is locked away inside of heads of its developers as tribal knowledge.

So if documentation is needed where's the best place to keep it? In my opinion, the the documentation needs to be as close to the code as possible, so put your documentation in the code. The further away it is, the more likely it is that the documentation will get out of date, and the only thing worse than no documentation, is wrong documentation.

Now, what should be in those comments? Well, as I eluded to previously, it should tell me the why. If someone is reading through the code they surely have enough knowledge to be able to tell what's happening to which objects, so you can safely leave that out.

Wednesday, January 28, 2009

Java's Got it All Wrong

When I first started working on computers I was sold that Windows was the only way to go. However as time went on I found that there was a lot that I was missing out on. One of those things was Unix. I've learned a lot about in the time since I was a hard-core Windows user. The one thing in Unix that has really stuck with me is the elegance of its design. In particular the approach of favouring processes over threads. It has huge implications that you never really understand until you run into a system that does things the other way around.

Recently I've been spending a lot of time thinking about web applications, and I keep coming back to the thought that the current design of application servers in Java are flawed. Typically application servers are designed to run as a single process with many threads servicing requests. While this approach has been proven to work, I'm not convinced its the right approach. The real problem as I see it is that there is no process isolation, and it's a real problem when working with many applications deployed to the same server. To illustrate my point, lets look at an analog: operating systems and processes.

One of the things operating systems do very well is manage processes. Each process gets its own little sandbox to play in so that it can keep track of everything the process is doing: what files it has open, how much memory it has allocated, etc. Additionally, the information available to the operating system is also made available to the users of the system so they can monitor each process and terminate any that aren't working correctly. By allowing the user to access the process information the operating system essentially saying "I'm a stupid machine and I only know how to handle obvious problems". An intelligent user can determine if one process is using too much memory or CPU and kill it so that all the other processes can keep on working away.

Java application servers on the other hand only presents a single opaque process. There's no way of telling which application is consuming all of the CPU cycles, sucking up all of the memory available to the VM, etc. And if one of the applications crashes it takes down the entire server with it. All of the applications within a server run under the same process and as such aren't really isolated from each other in any meaningful way -- there's no process isolation.

A better approach might be to follow the lead of the operating system. Each application runs as a separate process or tree of processes tracked independently by the operating system. The web server runs isolated from the applications that it's serving. The operating system already provides great tools for managing processes, so why not use them? This is by no means a new concept. If the application process speaks HTTP, then the web server can setup a reverse proxy to map the application into its URL address space. Alternatively, the application could just as easily speak FastCGI, a protocol that allows applications to respond to requests from a web server - similar to CGI, but without the overhead of starting up a process to service each request.

Unfortunately, I don't see anything changing anytime soon.

Saturday, January 17, 2009

The Logitech Wave

Well, I've had my Logitech Wave keyboard for a while now and I suppose I owe you a review. So without any further ado, here we go.

I haven't spent too much time with the Wave since I bought it, but the time I have spent with it has been pretty good. The keys have really good feedback and aside from the weirdo layout for the "6-pack" I haven't had too much trouble adapting to it.

One of the things I really wanted in a keyboard was a scroll wheel. Unfortunately this one doesn't have that feature, but neither do any of the other ones I've seen. What it does have, which is fairly common is a zoom control. On the Mac the zoom control can be reconfigured to act as a scroll wheel. I was a little skeptical at first about how well it would work but I was pleasantly surprised.

Windows however is a completely different story. In order to treat the zoom control as a scroll wheel I had to install modifications to the drivers called uberOptions. It certainly gets the job done but not without its own problem. The software had some weird quirk where it would hold on to the mouse cursor position and restore it when you stop scrolling. It was really frustrating because I tend to like to use the mouse at the same time as scrolling, i.e. scroll on a page and click links, but this software just kept jumping the cursor back. Argh! I really don't like having to install extra software to get what seems like some trivial functionality, but if it actually worked I probably wouldn't complain. The fact that it doesn't work as I would expect it just frustrating.

Since my use of the zoom control is slightly esoteric, I wouldn't hesitate recommending the Logitech Wave to anyone looking for a new keyboard. But if you're looking for a keyboard with a scroll feature and are running Windows, stick with what you've got, or wait for the software to get an upgrade.

Friday, December 26, 2008

Keyboards, the Neverending Saga

If you're anything like me, you're very specific about your requirements for a keyboard. I've been searching for a keyboard for about a year and a half, and so far I haven't been able to find anything that fits the requirements. Maybe I'm just sentimental, but I really like the Logitech Elite keyboard that is no longer being made. I bought one years ago and it's perfect for me. One of the things I really like about it, and what I haven't been able to find in any other keyboard is the scroll wheel. A keyboard with a scroll wheel? Yeah, it may seem odd, but considering that I use a trackball that doesn't have one it works really well.

So what am I looking for in a keyboard? Well, I'd like a keyboard, preferably black with a scroll wheel. It has to be really comfortable but it doesn't have to be ergonomic. It absolutely must have good, solid feedback. I find it really awkward to type on something that's too spongey, and it hurts to wrists to use something that too stiff. As much as I love the feel of the Das Keyboard it's too loud, so another requirement is that it has to be pretty quiet. Lastly, the layout of the 6-pack (home, end ...) has to be just that: a 6 pack. I'm really getting sick of seeing all these otherwise decent keyboards having a really screwy layout for the keys that as a programmer I use all the time.

In short:

  • Scroll wheel
  • Comfortable
  • Quiet
  • Good Feedback
  • Non-screwy 6-pack
  • Mac compatible

I almost forgot, as I use a Mac it needs to be Mac compatible.

As I mentioned earlier, I've not been able to find a keyboard that fits these requirements other than the Logitech Elite. So where does that leave me? Well, certainly without a keyboard that meets my requirements without looking on ebay. I guess I'll have to relax my requirements a bit, the only problem is that my search for keyboards hasn't been very fruitful. Maybe that's because I only have 3 objective requirements, and I've only seen an answer to 2. The others, I can only determine by using it.

The only keyboard that comes close is the Logitech Wave keyboard. Granted it only meets one of my objective requirements, but my hope is that its answer to the subjective ones will far make up for the what it's missing. I think I'll pick it up and see what happens.