Please join me at my new location bryankyle.com

Saturday, October 31, 2009

The Polyglot Programmer

Those that know me know that I'm a real programming language geek. I'm always reading about programming languages. Why am I constantly seeking out new language while most other developers are happy knowing one or two languages? I think it comes down to not being satisfied with the status quo. When you code in a language for a long enough period of time you think in terms of the constructs that the language provides you.

This is certainly a good thing in terms of productivity. Thinking in a language is akin to speaking it as your native tongue. Your brain becomes hard wired to think in that way. The time from concept to implementation is shortened because you don't have to do any mental translation to convert a solution from one language to another. While this is all well and good, thinking only in the constructs of one language prevents you from seeing . As the old saying goes: when all you have is a hammer, every problem looks like a nail.

But while this is great in some respects, learning more languages has certain benefits. Each language is different, exposing you to different ways of approaching problems and different tools for solving them. As you step further and further away from the comfortable object oriented Aglol descendants you'll notice that the languages you used to use to solve every problem is woefully inadequate at solving certain classes of problems.

This comes from the fact that not all languages are created equal. Each language has a certain level of friction for a given problem domain. It's true that you can solve a problem in any turing complete language, but that doesn't mean that the solution will be easy to read, write, or maintain. By learning a variety of languages you'll be able to see which language are better suited to a particular problem.

Also, since each language tends of offer a different set of tools, you'll expand your mind. There is more to programming than what blub languages give you. For example, JavaScript gives you a language with dynamic typing, first class functions, closure, and prototypal inheritance. None of those features are available in a language like Java.

Features aren't the only thing that new languages expose you to either. As you venture further off of the beaten path you'll find some very interesting languages that look strange and alien. Take Factor for example. Factor is a concatenative language which is a language that is based around the idea of a mutable stack. Concatenative languages are just one class of languages and there are many others, all of which have interesting properties.

As you become exposed to more and more language concepts you'll be able to pick up new languages much more easily. Having been exposed to the concepts of a new language before, you will have flattened the learning curve of that language.

The most effective languages tend to be called Domain Specific Languages. A domain specific language is a language that is tailor made for solving problems in a specific domain. A great example of a domain specific language that most of us have dealt with is CSS. CSS provides a language to specifying styling of HTML elements. It doesn't have loops, it doesn't have conditionals, just pure unadulterated declarations that can be combined. Certainly there are problems with implementations of the language, but that isn't my point. My point is that CSS fills a void. You could probably do what CSS does with a general purpose language, but why? CSS is tailored to the problem it's trying to solve.

I'll leave you with an interesting thing I've noticed as more applications are moved into the web realm: if you want to stay relevant, you need to become a polyglot. Most applications aren't simply constrained to one language anymore. Modern web applications use at least 4 distinct languages between the server side, client side, build scripts, and configuration. If you can't be effective with all of them then you've got some learning to do.

Thursday, August 20, 2009

Exception in thread "main" java.lang.NullPointerException

I've learned over my years of programming in object oriented languages is that null values can be really painful. Due to poor decisions by API designers code has to be littered with null checks to ensure that values returned from API calls return something other than null. Failing to make these kind of checks while oftentimes harmless, can cause problems once you start testing code off of the happy-path.

There are few things a consumer of a poorly designed class can do other than simply read the documentation, add null checks and test thoroughly. So, if you're designing a new class it's really important that you get it right the first time. While I can't give much advice about the design of your specific class, I can give some hints nulls and when it's appropriate to use them.

These rules aren't hard and fast, there are times when these rules are completely wrong. But it's been my experience that these rules are applicable in almost all cases.

Return null when you mean null.

A common mistake that programmers make (myself included) is to simply default values to null. I attribute this to laziness. It's much easier to simply use null as a default value instead of some sensible value. Certainly there are times when null is a good choice, but I think as programmers we tend to fall into the trap of using null because its convenient.

The first thing to understand about null is that it means the absence of a value. It means there's nothing to see here, move on. It doesn't mean empty string, it doesn't mean 0, it doesn't mean empty instance of a class it means that there is nothing to refer to, no value. Unless your program needs to distinguish between an empty value and no value provided there is little need to use null.

Return an empty list or collection instead of null.

If you have a method that is supposed to return a list of something, you should always return a list regardless of whether there is anything to put in the list. Typically, when a caller asks for a list they are usually going to loop over its contents performing some operation. Since a loop over an empty collection is effectively a no-op returning an empty collection simplifies the calling code by removing the need to check for null.

Return a safe instance instead of null.

When possible, return a do-nothing instance of a class instead of null. This is really useful for classes that contain other objects that are used frequently. This allows callers chain method calls together without having to worry about null return values. Typically this is useful for classes that are treated as services.

An example of this might be an a getXPathEngine() method of a Document class. If there is no implementation of XPathEngine available, then Document.getXPathEngine() should return a safe implementation of XPathEngine instead of null that way callers don't have to constantly check for the presence of the engine, they can assume that it exists.

Tuesday, July 14, 2009

The Tailor

This is the story of two developers, Curtis and Dean. Both happily work on the same project, and have strikingly similar experience. In almost every aspect Curtis and Dean are exactly the same. The only place where the differ is in development pace. Curtis tends to take slightly longer to accomplish his tasks when compared to Dean. On a task that takes Dean 7 hours, it would take Curtis 8.

Things remained this way for a few months, but as time went on Curtis began to close the gap with Dean. Before long, Curtis was doing his tasks much faster than Dean. On the task that was taking Dean 7 hours, Curtis was completing it in 4 with the same degree of quality. Curtis and his manager were happy with the improved pace. Dean couldn't figure out how Curtis was doing it.

One day, Dean and Curtis were working together trying to solve a particular bug. After a few minutes of watching it was apparent to Dean how Curtis was able to outpace him. That extra time that Curtis had spent earlier wasn't going to waste. He had been busy writing scripts to automate the routine micro-tasks he had to perform. And the scripts were just the beginning of it.

Curtis had taken his attitude towards automating further than just scripts. Any time he noticed himself doing something repeatedly he spent some time to make sure he was doing it in the most optimum way. He had memorized the key bindings the commands in his IDE he used the most. He extended his editor of choice, Emacs, with functions and triggers to automate almost every micro-task he did on a routine basis.

Curtis had tailored his environment perfectly to suit how he works and how he thinks. Curtis' customization allowed him to get more done in a shorter amount of time than his peers. Tailoring being what it is, the customizations to his environment were useless for anyone other than himself so he never bothered to share them. To Curtis, this didn't matter. He didn't make these customizations for anyone but himself.

----

Obviously the above story is fiction but it serves to outline a point: you need to optimize your environment for the way you think and work. If you don't, you're wasting time. That doesn't give you a license to impose your thought patterns on anyone else, it simply means that your personal work bubble needs to be optimized.

To put it into object oriented terms: Everyone must adhere to a common interface when working with one another. The interface provides an abstraction, or facade for how the tasks are performed. How the work is done is an implementation detail.

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.