Monday, July 21, 2008

Object Creation in Ext JS

Ext JS has a useful object creation pattern. Most constructors can be passed a hash of configuration parameters. This can be used instead of the prototype creation pattern (not to be confused with Javascript's prototypical inheritance). Rather than create new objects that are copies of an existing object, you create objects based on a set of configuration data.

You want an example? OK. Today, I was creating context menus for items in a tree. There is a global pool of possible actions, and each node responds to a different subset of them. When the user right-clicks on a node, I need to

  1. Create a Menu instance
  2. Add all of the appropriate menu items to it
  3. Show the menu
I had hoped that I could create one menu item instance per possible action (20 or so), and then re-use them in different Menu instances.
var actionMenuMap = {
addChild: new Ext.menu.Item({text:"Add child", icon:"add.png"}),
delete: new Ext.menu.Item({text:"Delete", icon:"delete.png"}),
fireZeMissiles: new Ext.menu.Item({text:"Fire ze Missiles!", icon:"fire.png"})
}

var nodeActions = ["addChild", "delete"]; //in practice, this would come from the node itself

//dangerous nesting ahead!
new Menu({
items: nodeActions.map(function(a) {
return actionMenuMap[a];
})
}).showAt(event.getXY());

That didn't work - it seemed like I couldn't share a menu item instance between menu instances. I might be able to get it to work by removing menu items after the menu is dismissed, but I don't actually need to. I can simply hold on to the configuration information.

var actionMenuMap = {
addChild: {text:"Add child", icon:"add.png"},
delete: {text:"Delete", icon:"delete.png"},
fireZeMissiles: {text:"Fire ze Missiles!", icon:"fire.png"}
}

var nodeActions = ["addChild", "delete"]; //in practice, this would come from the node itself

//now we're cooking with functional programming!
new Menu({
items: nodeActions.map(function(a) {
return new Ext.menu.Item(actionMenuMap[a]);
})
}).showAt(event.getXY());

In case you are not familiar, map is a function that is present in every functional language and many dynamic languages. It does not exist in Javascript natively, but is added by Prototype, jQuery, dojo, Mochikit, and probably every other Javascript framework. Here's a sample implementation for reference:

Array.prototype.map = function(f) {
if (typeof(f) !== "function") {
throw new Error("map takes a function");
}

var result = new Array(this.length);
for (var i = 0; i < this.length; ++i) {
result[i] = f(this[i]);
}
return result;
}

What could possibly make this better? In addition to taking a hash, allow the constructor to take a function. That function manipulates the object after the rest of the construction runs, allowing you to add children or manipulate settings or calculate values. This would be pure icing, of course. Factory functions also feel a lot more lightweight to me than factory objects. See also Rails' version of the K combinator.

Saturday, July 12, 2008

Please encode the patterns that you see

As my software career has advanced, I've steadily become more cynical and bitter. This isn't good, and it's something that I'm trying to work on. It's hard to go a day without having one of those "you've got to be kidding me" moments. "I can't believe they did it like that." "What were they thinking?" "Hasn't anybody ever tried to do this before?" "There has to be an easier way."

Case in point: I recently read that SWFObject was THE way to embed swf files in your HTML. Fine, I though. I'll give it a try. Within minutes, I ran into something simple that it couldn't do. When you call the function that embeds the swf, it might not actually do the operation immediately - it might wait until the page initialization has progressed beyond a certain point, and then inject the code. I needed to run some code AFTER the swf had been embedded in the page (for sure). There's no way that I could see to do this with the stock SWFobject. Despite the fact that SWFObject inherently depends on event dispatch to work, it doesn't dispatch enough of its own events to be useful to me.

As I started to look at the code to see if I could work it in, I stumbled across the following snippet:

var att = {};
if (attObj && typeof attObj === OBJECT) {
for (var i in attObj) {
if (attObj[i] != Object.prototype[i]) { // Filter out prototype additions from other potential libraries
att[i] = attObj[i];
}
}
}

"Wow!" I thought. "That looks like it would be useful to lots of people." As it turns out, it is very useful - even to the SWFObject developers, who used the same pattern twice more in the same 58-line function:

var par = {}; 
if (parObj && typeof parObj === OBJECT) {
for (var j in parObj) {
if (parObj[j] != Object.prototype[j]) { // Filter out prototype additions from other potential libraries
par[j] = parObj[j];
}
}
}
if (flashvarsObj && typeof flashvarsObj === OBJECT) {
for (var k in flashvarsObj) {
if (flashvarsObj[k] != Object.prototype[k]) { // Filter out prototype additions from other potential libraries
if (typeof par.flashvars != UNDEF) {
par.flashvars += "&" + k + "=" + flashvarsObj[k];
}
else {
par.flashvars = k + "=" + flashvarsObj[k];
}
}
}
}
That general pattern appears at least 9 times in the code. It's a good thing they put it in a reusable functio... oh wait, they didn't. Instead, they dutifully pasted the code (comment and all) 8 times.

OK, something's going on. Maybe I've become a much better programmer in the past year; maybe everybody else is getting worse; maybe I'm off my rocker; maybe there's some strange performance or compatibility tweak that prevented them from doing what seems plainly obvious to me. Removing the obvious duplication would have simplified their code, making it more readable (and possibly obviating the need for the accompanying comment).

It's the little things like this that make me wonder if we're actually moving the state-of-the-art forward at all. If we can't see (or don't care about) the duplication at the micro scale, how will we re-use software at any broader level?

Thursday, June 26, 2008

Planescape: Effortless

I was amazed to learn that Planescape: Torment, a game released in 1999, is still playable under Vista. I installed it the other night (intending to finish it this time), patched it (using the most recent official patch, which is probably 8 years old), and started it without a hitch. I'm sure some combination of Microsoft's fervent dedication to backwards compatibility, nVidia's seemingly rock-solid drivers, and Black Isle's crack team of developers made this possible.

Recently, Scott Hanselman interviewed Steven Frank of Panic (a Mac software developer). In the interview, it was revealed that Mac users are less worried about backwards compatibility. Apple has completely axed support for Classic mode, which pretty much kills any software more than 8 years old. As a Mac user, I agree. I'm not that worried about old applications not working. But that's because I'm talking about applications. If an old application stops working, there's a good chance that somebody has written a more recent, and probably better, replacement.

Games are a different beast, though. Games are closer to movies or novels. How would people feel if they couldn't read Les Misérables anymore? Or if somebody went and mucked with Star Wars, and then threatened to not publish the theatrical release anymore? Well, we know what happens then: thousands of fans get really really angry. People crave old stuff. Really great content is timeless. Games should be treated the same way. Ever since "game designer" has become an official title, games have been steadily becoming more than children's amusements. There's often some great narrative buried in there, wrapped up tight inside a husk of decaying code. Eventually, that code won't run on new computers, and the narrative will be lost forever.

Of course, now we have virtualization, so maybe it's not such a big problem.

On Succinctness

One of the reasons that I've been blogging has been to help me communicate succinctly. I've been trying to keep my posts small without being lifeless. I want to balance terseness with expressiveness. If you read this blog, how am I doing? What could I do better?

On Usability

I've been slowly learning that, in my heart, I'm a usability guy. I'm always concerned for the experience that end users will have with software. I care about making it easier for people to do what they want to do. When it comes to user interfaces, I like bling, but only when it helps the user accomplish a task or understand an interaction. I love Expose. It's such a simple but powerful concept. It's also made for a great demo. I hate Flip 3D. It's pretty, but also pretty pointless.

I've been interested in API design for a long time, too. As a developer, I have used some libraries that were an absolute joy, and other libraries that were a total mess. My recent foray into Flex (specifically, getting the Tree control to lazily load its data) reminded me what it's like to use a bad API.

I mentioned to a coworker the other day that, if you're developing a library, you should be at last as good a developer as the people that will end up using it. To me, it looked like Adobe (or Macromedia - I don't really know who's responsible) put all of their junior developers on the component library project. As a result, we're blessed with the interface IDataDescriptor, whose methods include isBranch() and hasChildren(). What's the difference? Should they ever be different? Who knows?!

I realize that I misspoke to my coworker. I should have said that people developing libraries should have a code aesthetic sense. I don't mean code aesthetics in terms of indentation or brace style or what have you. I mean that API designers need to consider the people that will end up using the library. Just as the hallmark of an Apple Design Award winner is that users "just get it", a good API should also be so easy to understand that it seems obvious to you. As in, "why would anybody make this API any different?"

Design is hard. It takes a conscious effort (well, for most of us). That's why it's important to do. If you're a developer, ask yourself: is this easy enough to understand. Remember, you're writing for an audience - your code does not exist for your eyes only. Even if it did, you're liable to forget everything before you come back to work on it again. If you're a manager, make sure there's enough space for developers to focus on this. If it looks like you're going to miss a deadline, that doesn't give you carte blanche to pressure developers out of finishing their work. Just because the code works doesn't mean it's done.

If you can't make an API grokkable, at least document it well. The standard Java and MSDN docs are full of nonsense.

setFoo(IFurple f) - sets foo to f

Really? I wouldn't have guessed. This tells me nothing. What is foo and why do I care. Why is foo a furple? If anybody ever asks a question about your API, it's a sign that something needs to change. Maybe you just need to add some documentation. Maybe you need a high-level wiki page explaining what the library is trying to do. Maybe you need to rename a method. Maybe you really do need to change the API. Or maybe you just need to smack the developer on the head and tell them to read the Javadocs first. But if you don't change anything, the problem is just going to repeat itself. Who knows - maybe you'll discover a bug or race condition along the way.

Monday, June 23, 2008

Vista Usabaility... It's Got Issues

I bought a Dell with Vista on it a few months ago. I figured that it was high time that I upgraded to Microsoft's newfangled operating system. It hasn't been too bad. There are some hiccups, but every complex piece of software has its share of those. I'm sure Microsoft will try its hardest to fix those with time.

On the other hand, Aero is pretty much terrible. Sure, it's pretty (at least at first). My impression is that the rendering infrastructure is also quite good. But holy cow, Microsoft needs to hire some actual UI designers. Not just artists, but people who understand user interfaces. There are some reasonably amateurish mistakes in Aero. Even if they seemed like good ideas at the time, after using Vista for about a week, you really start to notice them.


I was first surprised to see how mousovers have invaded Explorer. Look at the following picture. Which icon is selected, and which icon am I pointing my mouse at?
Can you believe that it's easy to delete the wrong file?


The new, unified look for the windows isn't too bad. The window titlebars are translucent, with a frosted glass appearance. At first I though that the effect would be distracting. You know what, I was right.


Explorer windows look a little bare, but the whole top of the window is available for your dragging pleasure. Well, almost all of it. If you manage to click in the upper-left of the window's title-less-bar, you get your friendly system menu.


Finally, my absolute least favorite thing. For whatever reason, the rollovers that cause me to shred the wrong file have also made it into the standard tree control. Here, when your mouse leaves the tree control's bounds, the tree "fades away..." It literally disappears. Which can leave the following unfortunate situation:

Wait, I think maybe there's a bit more to it...

Ah, I bet we can expand that.

There we go!
Now, you might be asking yourself "who cares?" It doesn't seem like it's that big of a problem. True, in Explorer, the only inconvenience is that I don't know at a glance if my folder contains any items. It's a problem, but not a huge one. So, let's take a look at the Java programmer's friend, Eclipse.

Search results, you say. Search results, indeed. And people are trying to emulate it! Little hint: just because Microsoft does it, doesn't mean it's a good idea.

Even the Windows Classic theme isn't safe. The "expandos" in the classic TreeView fade out too.


If only Microsoft supported third-party themes... oh wait, you need to replace system DLLs to do that. Still, I don't know if I can stand the horrible usability of the stock UI. Hey Microsoft: ever wonder why so many themes and theming tools exist for your platform? I can think of a reason.

Even with all my bitching, I think Microsoft's heart was in the right place here. They realized that they needed a better rendering infrastructure (with features like compositing on the video card) and a more slick UI. Apple had been stealing the show on this issue for the past seven twenty-three years. Microsoft needs to go back to the drawing board. They need a fresher UI in the next version of Windows. And they need fewer people working on it. I think Windows is going to buckle under its own weight within 10 years. Apple continues to embellish their own UI, but it's often both functional and pretty. That's why people go ga-ga over it. Expose is a great demo, but I use it daily. Same with Dashboard.

I can only imagine what it must have been like to have seen this live:

... especially when this is what people were used to...

Wednesday, June 18, 2008

Flex Builder 3 Debugger on Mac OSX

I was having a hard time getting Flex Builder on my Mac to behave. I came across a post at Big Spaceship Labs that put me on the right path. I tried things, and came up with a reasonable solution, which I added as a comment to the original post.

This technique is useful for keeping several Flash Players on your system (or anything, really). I think I read that MultiSafari uses this trick. The trick is to change an application's bundle identifier. You may have noticed that Mac OSX seems to magically know about all the applications on your system, even though you didn't use an installer for most of them. It uses the bundle identifier (and I believe the bundle version) to keep track of them. I believe that Max OSX treats all applications with the same bundle identifier and version as the same. Internally, they probably form a composite key in a map. Furthermore, most associations (such as "Open With") are made to the bundle identifier, not the application's path. This is so that you can move an application to a new directory without breaking anything. It also means that, if you have 2 applications with the same bundle identifier and version, there is no way to choose which one will launch.

It's surprising how well the whole application list works on Mac OSX. I still had some problems in 10.4, but 10.5 seems to be rock solid in this area. And, when application developers know what they're doing, it works pretty well.

Sunday, June 08, 2008

Exceptions in Multithreaded Programming

Exceptions are great. I've used them since C++. It's even sweeter that more modern languages (Java, C#, Ruby, etc.) have enhanced them with information like stack traces and nested exceptions. Procedural programming will never go back to error codes.

However, exceptions are increasingly insufficient for the work that I do. I suspect that this is true of everyone. Anybody who has done multithreaded programming in Java knows this problem:

class WorkItem implements Runnable {
@Override
public void run() {
try {
//do some work
} catch (SomeException e) {
//WHAT DO WE DO HERE?
}
}
}

Exceptions fall apart in a multithreaded environment. Take the example. What are our choices? We could silently swallow the exception (bad style, and also probably wrong). We could write an error to stderr and quit (bad for users). We could throw a RuntimeException (which will forcefully terminate the thread, which might not be too bad). In practice, we should probably notify somebody. But whom? Exceptions fit so nicely into the framework of the call stack - simply unwind the stack until you find an appropriate exception handler. In a multithreaded environment, you have several independent call stacks. It's likely that the code which will respond to the error is running in a different thread. It's insufficient to unwind one thread's call stack - you need a cross-thread error handling mechanism.

What's the solution in Java? I don't know. Erlang's approach is interesting. In Erlang, you can link processes together. By default, any error in one process will kill every linked process. That sounds bad, but it's a reasonable default. You can instead register yourself as a "system" process. Rather than being outright killed by friendly fire, system processes are informed of their comrades' fate. They are able to decide what to do about it. They could restart the failed process, or send a notification, or log it, or whatever. The important thing is that it's automatic. Once you've linked the processes together, the Erlang runtime takes care of notifying other processes about fatal errors and so forth. It's pretty neat

Maybe I'll eventually get to write something in Erlang. I don't know how easy it is to use in day-to-day life, but it seems pretty awesome in theory.

Wednesday, June 04, 2008

Aspect Oriented Programming in Javascript

Working with YUI today, I found that I wanted to augment a built-in method. I am using a custom subclass of TreeView. My TreeView registers some mouse callbacks for the generated HTML elements that compose the tree. My TreeView needs to know whenever a Node is refreshed (i.e. whenever a Node regenerates its HTML) so that I can re-register all of my callbacks. The standard YUI Node base class doesn't do this.

This sounded like the sort of thing that could be solved using Aspect Oriented Programming. I wanted to run some of my own code after every invocation of some predefined method. It turns out that AOP in Javascript is pretty trivial. There might be a framework out there, but it wasn't even worth looking. My first implementation simply replaced the existing method with one of my own design, which delegated to the original method. After doing this in a few other places, I clobbered together the following function, whose name sucks, to simplify the whole mess.

function augment(obj, fn, options) {
var original = obj[fn];

//make copies of the fields in options in case it changes
//between now and when the generated method is called
//(which may be a long time).
var before = options.before;
var replace = options.replace;
var after = options.after;

obj[fn] = function() {
if (before) {
before.apply(this, arguments);
}

if (replace) {
//TODO: we should probably send original along with
//this call, possibly embedded in arguments
replace.apply(this, arguments);
} else {
original.apply(this, arguments);
}

if (after) {
after.apply(this, arguments);
}
}
}


//samples:
augment(YAHOO.widget.TreeView.prototype, "draw", {
after:function() {
this.nodeRefreshed(this.getRoot());
}
});

augment(YAHOO.widget.Node.prototype, "refresh", {
after:function() {
this.tree.nodeRefreshed(this);
}
});

//also needed (for those playing along at home):
YAHOO.widget.TreeView.prototype.nodeRefreshed = function() { };

It's actually pretty simple. I grab a reference to the original function. We create a new, closed function. It can refer to the original function and the augmentations, but they are not visible outside the closure. That was the primary driver for me - my previous implementation was storing the original functions in global variables, which polluted the global namespace. And we use Function's handy apply(), which allows us to be ignorant of the parameters that the original function takes. In the sample, I also register a dummy implementation of nodeRefreshed() so that I don't need to perform a null check in my augmented refresh().

One improvement that I would like to make, but is probably impossible, is to make the environment for replace() be identical to the environment for the original function. As it is, any variables that are closed by the original function are unreferenceable by the new function. This is particularly problematic when you only want to make minor changes to a function. You copy the original function's source code into replace, and make the minor changes that you need, but it doesn't work because the variable bindings are different. I think you can do this in Lua. I know you can do it in Ruby. I don't think Javascript has the necessary support yet (and, since we always need to support IE, the necessary support will likely never be available).

So, it's good to know that AOP is so easy in Javascript. I've never really used AOP before, though I work with people who have, and who seem to like it. However, AOP's utility here is only because of YUI's heavy use of inheritance. I've ranted against that before. If YUI's TreeControl didn't try to do everything itself, there would be a lot of natural seams that I could use to inject my own logic.

I hope to post soon about my experiences with YUI's TreeControl, Drag and Drop library, and other components.

Sunday, May 25, 2008

Swing Does Components Better Than Component Libraries Do

I'm currently trying to get a handle on Macromedia Adobe Flex using the free, open-source Flex SDK. Flex is a set of tools to create flash-based "applications" using XML UI definition and Actionscript for everything else.

It seems that Adobe has adopted some Microsoft conventions for programmatic UI creation and management. In particular, components in Flex have a long and convoluted lifecycle. In Web Forms, I never understood why I shouldn't create child controls in my Control's constructor; Flex's UIComponent has a createChildren() method. I still don't know why I shouldn't create child controls in the constructor.

In my Swing programming, on the other hand, I don't seem to run across these problems. As far as I know, a Swing component has one and only one step in its initialization process - the constructor. That certainly makes things simpler. I don't have to wonder "What happens if I put this here?" or, more commonly, "Why does this thing not work? Oh, somebody messed up the initialization code."

Actually, most of my frustration here is directed to ASP.NET 1.1. Things may have gotten better in later versions (though I doubt it), and I don't really know how good or bad it is in Flex land. Still, this dredged up bad memories for me. Thick base classes suck!

Wednesday, May 14, 2008

Why Inheritance Is Bad

3D graphics programmers, if there are any that read this blog, are familiar with gimbal lock. The Wikipedia article makes an analogy to compass directions. If you tell somebody at the north pole to face south, which direction are they facing? You have no way of knowing, because south loses its meaning at the north pole. At any other place on the planet, your location and direction are completely independent. At the poles, direction has no meaning in the cartographic coordinate system. Two previously independent variables have now become linked.

In programming, when you derive from a base class, the classes are in a state of gimbal lock. We can vary the subclass as much as we want without affecting the base class. However, a change to the base class will not only affect our subclass, but every other subclass out there. Suppose that our base class provides some core data processing functionality, and its various subclasses encapsulate different data sources. So far, so good. We've managed to avoid duplication. If we come up with a new data source, we can simply create a new subclass. However, what happens if we want an existing data source to send data to a different set of processing rules? A class would need to have more than one base class, except in a way different from normal multiple inheritance. No programming language that I've seen can support this scenario.

A hallmark of good object-oriented design is that classes have one and only one responsibility. Why is this important? It makes the code simple, it makes the code testable, it decreases coupling, it might increase cohesion, and it's just plain nicer to read. When you derive from a base class, your class has all of its explicit responsibilities, and the responsibilities of each of its ancestor classes. In our example, each subclass is itself responsible for knowing the ins and outs of a particular data source. Since they all derive from a common base class, they are also responsible for knowing how to process the data. This example only deals with 2 responsibilities, but real systems deal with hundreds.

Remember that inheritance is often used to represent taxonomies. You might have classes such as Animal > Mammal > Giraffe or Widget > Button > Pushbutton. You might say that things on the right are defined in terms of things on the left, but that's not exactly true. A giraffe doesn't have lungs because it's a mammal; we call it a mammal because it has lungs. Using inheritance to describe something (using, for example, interface inheritance) makes a lot of sense. Using inheritance to define something doesn't.

Adventures with the Scriptaculous Ajax.Autocompleter

I had a chance to use the Scriptaculous autocompleter control at work the other day. Since we are using Ruby on Rails, it was easy enough to use text_field_with_auto_complete() to generate the relevant HTML.

The client noted that it was difficult to enter a new word if it was too close to an existing word. For example, he would type "expensive", and the system would suggest "not expensive". When he would hit Enter, it would replace what he had typed with "not expensive". This is because the Scriptaculous control doesn't support the case where no item is selected - one item is always selected, and it defaults to being the first item.

I decided to have a peek at the source code. In maybe 15 minutes, I had managed to convince it that "nothing selected" is a valid case. Unfortunately, I didn't refactor the code in any way - now every autocompleter behaves this way.

Scriptaculous uses prototype's Class.create() to generate 2 classes: Autocompleter.Base and its sole subclass: Ajax.Autocompleter. From the source code:

Autocompleter.Base handles all the autocompletion functionality that's independent of the data source for autocompletion. This includes drawing the autocompletion menu, observing keyboard and mouse events, and similar.

I appreciate their desire to re-use code. Unfortunately, the use of inheritance has caused the whole mess to suffer some sort of object-oriented gimbal lock. It's easy to create a new Autocompleter that gets its data from a different source; it's much more work to create an Ajax autocompleter with different behavior.

If I have some time (that is, when I'm not busy complaining about something), I might see if I can refactor the scriptaculous source to further separate the data source of an autocompleter from its interaction controller, using some method other than inheritance.

Tuesday, May 06, 2008

Ruby in LISP clothing

As it turns out, Ruby's syntax is somewhat flexible. As an example, parentheses are sometimes optional when calling a method.
puts "Oh hai!"
puts("Oh hai!")

link_to_remote "Go there", :url => { :controller => :there, :action => :go }
link_to_remote("Go there", { :url => { :controller => :there, :action => :go } })
The only time the parentheses are needed is when the invocation would otherwise be ambiguous:
link_to_remote h text, :url => { ... }
(h is the HTML escaping function. link_to_remote may actually automatically escape the HTML, but I'm not sure.)

Ruby can't tell what the user is trying to do. The normal way to fix this is to add some parentheses to the call:
link_to_remote(h(text), :url => { ... })
link_to_remote(h text, :url => { ... })
however, it is also possible to use LISP-like parentheses with the same result:
link_to_remote (h text), :url => {...}
(link_to_remote (h text), :url => {...})
Which is better? Certainly one of the first pair is more conventional. For some reason, though, I found myself migrating to the second pair. I suspect it's a combination of
  • I try to avoid using parentheses in method calls in Ruby as much as possible
  • LISP is awesome
  • I have done some Objective-C programming, in which you [object send:message]

Thursday, May 01, 2008

Consistency on Rails

The Ruby on Rails crowd makes a big deal about consistency. They claim that Rails is easy and fast for development partially because it favors convention over configuration. I guess the thought is that you don't need to write any configuration. Plus, once you've worked on a few Rails apps, you pretty much know where everything is.

So far, I've found a lot of that to be pretty much true. Migrations, routes, controllers, views, database configuration - there's a place for all of them, and they're pretty much exactly where I would expect them. However, I've often found myself struggling when actually writing the code. I'm either going to the documentation constantly, or even peeking in the Rails source. (It turns out that some options to methods aren't documented, and the rails plugins that we are using have poorer documentation than the core).

I only have 2 small examples at hand, but I could write about many more annoyances.
  • link_to and link_to_remote both seem similar on the surface. One will generate a normal hyperlink that will navigate the browser; the other will generate an AJAX link that will interpret the resultant response as either HTML to be embedded or Javascript to be executed.

    Both allow you to specify the url using :controller and :action. However, they have very different signatures, and it trips me up everytime.
    link_to "Help", { :controller => :help, :action => :sample }
    link_to_remote "Help", :url => { :action => :help, :action => :sample }
    Did you see that? The only difference between the two is that one requires the URL-related options to be packaged in a hash named :url, while the other disallows the hash
  • When using the form helper methods such as text_field and text_field_tag, you must be careful. Here is an example:
    text_field :post, :name <input id="foo_bar" name="foo[bar]" size="30" type="text" />
    text_field_tag 'post[name]' <input id="foo[bar]" name="foo[bar]" type="text" />
    As you can see, if you change from one to the other, you might need to also update you RJS files (or remember to set an explicit ID). This would have all been avoided if text_field had simply generated id and name attributes with the same value.
Rails certainly has its good points, but the small details are sometimes infuriating.

Thursday, April 10, 2008

Dream Programming Language: Optional Interface Methods

Yet again, I find myself disliking abstract classes. I was creating a subclass of Java's OutputStream called PathalogicallyBufferedOutputStream (for testing purposes). I wanted to implement flush, which Eclipse nicely autocompleted to look like this:
@Override
public void flush() throws IOException {
// TODO Auto-generated method stub
super.flush();
}
That gave me enough pause to wonder... do I actually need to call the super method. It seems that I have 2 choices:
  1. Check the documentation
  2. Read the source code
Fortunately, Eclipse makes it easy to browse the JDK source code. It only took 2 seconds to verify that the base implementation, in fact, does nothing. Without Eclipse, I probably would have ignored it.

The no-op method stub is in the base class so that consumers of any OutputStream can indicate when the bytes that they have written so far form a semantically meaningful chunk. Somebody might be waiting for some data; this allows you to get it to her. The problem that I have as a deriver of OutputStream is that, without source code or good documentation, I have no idea whether I should or should not call the base method. This is not a problem with JDK-provided classes, but it could be a real bear with a third party library.

Some people might claim that you should "always call the base method". If course, that raises the question of at what point one should call the base method. Should you call it before or after your code? Perhaps you call it in the middle. I prefer to assume that I never have to call the base method, because I shouldn't be deriving from concrete classes, and I like to assume that method that I am overriding is simply a stub that I am free to customize.

If I were designing a language, I would want some notion of "optional interface methods." I want methods that I can declare on an interface (or perhaps an abstract base class) which implicitly have a no-op implementation. If I choose to implement one in a subclass or interface implementor (because I want to be notified when something happens), I would get the benefit of code completion. The caller is not burdened with the need to check to see if I've implemented the method, and the implementor is not burdened with the uncertainty of whether or not to call the base method.

Why Message Passing?

Back at the end of March, I was starting some work on Ruby on Rails. I thought that a good April Fool's Day joke would be to release "Lua on a Luge" or "Lua on Skiis" (somebody came up with something even better). As the people that I work with know, I'm a big fan of Lua. I appreciate the things that it does well (prototype-based programming, and having very simple, consistent syntax). Even more interesting, though, are the things that it doesn't try to do:
Lua does not try to help you write programs with hundreds of thousands of lines. Instead, Lua tries to help you solve your problem with only hundreds of lines, or even less. - Programming in Lua - Preface
In any case, Lua doesn't directly support multithreaded programming. Normally, this would be fine. However, I've worked on some .NET and Java web apps that:
  1. Spawn a background thread to do some work
  2. Handle multiple requests at once
  3. Share some object / data between all of the request-handling threads
What kinds of things might we share? We might share configuration information, we might share connection pools (of connections, or threads, or whatever), we might share session information. Anything that is shared must be concurrency-safe.
Java and .NET provide synchronization mechanisms. Lua does not.

I started to think about various ways to solve this problem. One could expose a C threading library to Lua. You could expose both the thread management and synchronization primitives. Then, you could only share objects that are specifically written to use that threading library. You might also be able to inject metatables into arbitrary objects, but that would only go so far.

Then I realized that I already knew a better approach. If we relied on simple message passing between Lua processes, we could avoid the need to synchronize every shared objects - no objects would actually be shared (we might copy all values that get sent along on a message, or restrict the kinds of values that may be sent on a message).

It would probably not be as efficient as Erlang's message passing.  Also, I don't know of any Lua implementations other than the reference implementation and World of Warcraft's implementation, but I doubt that either support lightweight processes (instead, both implementations provide coroutines).  Incidentally, Ruby on Rails is currently not thread-safe (other Ruby web frameworks apparently are, according to the Mongrel FAQ). At least one Rails guy thinks that it should remain that way (see slide 115).

Dream Programming Language: No Static Fields

If I were to implement my own OO programming language, static data would be the first thing to go. I can't find any compelling reason to keep it around.

Something that people may or may not undestand is that static really means "global". Seriously, I wish that languages like Java and C# simply used global as the keyword instead. Static methods are simply global methods that have a long name with a period in the middle (well, I suppose they are also scoped and are subject to access control). Static, final references to immutable objects are just that - they're global constants. Keeping a single definition of PI around is generally a good thing. And, you guessed it, static fields are simply global variables in disguise.

"But!" I hear you say. "But I need static fields to implement singletons!" Why do you want singletons? Sure, you might think that you will only ever want a single instance of a class. I think you're wrong. What happens when you want to do some unit testing? What happens when the requirements change.

At one point, I'm sure that Windows assumed that it had exactly one display. If singletons had been widely used then, I would not have been surprised if there were some singleton which kept the display's information (in actuality, it may have simply been a global variable). Today, we might not only have several physical displays, but we might also have multiple active windowing sessions on a single Windows server. How about mice? Surely, a system has no more than one pointer. Well, that's kinda true, but my coworkers and I wish that we could get a second pointer on the screen for our pairing sessions. What about my Wacom tablet? And my friend prototyped a game that was controlled by using two mice. Singletons are the antithesis of what the Dependency Injection folks have been telling us.

If I were designing a language, I would want the programming language to encourage good programming practice. Since I'm the one designing this language, I get to choose what is good and bad. And I say, "down with singletons!"

Sunday, April 06, 2008

Message Passing

Anybody who has tried to do multithreaded programming in Java, C#, or most any C-based language finds that it can quickly become nightmarish. Deadlocks, race conditions, lock management - all of these issues will occur. In Java, all threads are able to share objects. As a result, the programmer is responsible for ensuring that his objects can't be put into an invalid state. Java provides per-object monitors to enable this. However, working with such monitors can be a nightmare. Using notifyall when you should have used notify, or forgetting to add the synchronized keyword to a method declaration, or incorrectly assuming that a class was thread-safe when it wasn't; these are all examples of simple problems that can cause your application to fail (perhaps only sometimes).

Erlang, on the other hand, does not suffer the same problems. Instead of sharing things, Erlang processes (which are the Erlang unit of concurrency) do not share anything. As a result, the need for synchronization goes away. Erlang processes send messages to each other. Each process has a mailbox. Each process can retrieve and process messages from its mailbox. You can imagine that a message is copied when it is put into another process' mailbox, but in actuality, since data in Erlang is immutable, the system is probably able optimize that away.

One of Java's founding principles was that manual memory management is complex, and thus easy to get wrong. Far simpler was to provide a system where the programmer didn't need to worry about such things. Erlang does for concurrency what garbage collection did for memory management - it removes that responsibility from the developer. Instead of asking every developer to handle any threading issues that might arise, it provides an abstraction that hides all of them. Behind the scenes, Erlang's mailbox system does whatever synchronization it needs to do in order to be completely thread safe.

Of course, Erlang's approach isn't perfect. Just as Java's garbage collection can sometimes allow memory to leak (when you are holding onto a reference longer than you need to), Erlang's system could still be susceptible to problems such as deadlocks. However, it is less likely to occur, and should be more obviously solvable when it happens.

Erlang's approach is so radical, yet so simple, that it's definitely worth learning more about. I hope to see Java and C# projects adopt Erlang's philosophy when appropriate. In performance-critical applications, manual concurrency management might be the way to go. For most purposes, though, the safety provided by Erlang's approach outweighs any negative side effects.

Wednesday, April 02, 2008

GameStop culture

Unlike some people, I actually have a decent GameStop nearby. The people who work there are intelligent, useful, and just generally pleasent. I was there tonight, picking up a copy of Condemned, which I have heard good things about.

In any case, the clerk was telling me that its sequel is also good, and noted that it is more of a horror game (Condemned being more of a thriller). As I was leaving, he suggested that, if I beat it in less than a week, I could trade it in towards its big brother. I thought he said something about full credit.

This struck me as odd. Here was a Gamestop employee essentially offering to loan me a game for a week, with no risk to me. Well, I suppose I would be turning $17 of hard currency in GameStop store credit, which is good for them, but it still seems odd. Then again, their whole business model is odd.

On the other hand, perhaps I simply misheard him.

Monday, March 31, 2008

Ruby on Rails after 3 days

I've been learning Ruby on Rails at work for the past 3 days. I had never really worked with Rails before, though I had certainly read enough to form misguided opinions about what was good and what was bad. After some hands-on experience, I have a better idea of what I do and don't like.

Routes

Routes are Rails' way to find the handler for a given request. You can establish routes by editing routes.rb. I don't know whether this is common practice, but an advantage of using a Ruby source file over XML is that you can use Ruby language and library features. This makes it easier to add conditional or generated routes, something that the Rails REST support does with abandon.

Routes are also 2-way. They are also used when you want to know the URL to a particular controller/action. This makes virtually impossible for your URL recognition and URL creation code to get out of sync.

RJS

RJS is Ruby's javascript-generation library. It's used as part of infrastructure for AJAX applications. Most of the Ruby AJAX tutorials that I've seen do something that I consider to be very bad practice - they run code on the server that doesn't need to be. The typical pattern seems to be to use an RJS helper method to emit Javascript that attaches a listener to some other HTML element. This listener then issues an XmlHttpRequest to the server, which produces Javascript code. This code is then sent to the client, where it is eval()'d. While there is nothing wrong with that pattern per se, imagine doing that for something as simple as clearing a text box. Imagine thousands of clients contacting the server just so that they can clear their text boxes.

Of course, in typical Rails fashion, there are many ways to use RJS. Rather than use it in response to a lightweight request to the server, you can also use it when you are building up the original HTML page. This can both simplify your application and also increase its perceived performance. Of course, you need to know that you are able to do this.

Unfortunately, the Javascript that is generated isn't that much different from the original Ruby. Compare this RJS Ruby code:
page['query_results'].value = ''
to this hand-crafted Javascript:
window['query_results'].value = '';
I'm generally against code-which-generates-code, and especially when used to avoid learning a new programming language. Web developers usually end up developing a reasonable understanding of HTML, and those in the Ruby community seem to also be reasonably proficient with CSS. I would hate for them to miss out on a fantastic language like Javascript.

Ruby Itself

Finally, Ruby as a language creates some interesting situations. I find its dynamism to be both a blessing and a curse. It's pretty amazing that Aptana Studio seems to be able to "go to declaration" reasonably well. Of course, this only works for methods which are defined statically, in the source code. Some methods are added dynamically (via method_missing or some other black magic of which I am unaware). I believe that it is impossible to even find out what these are - you simply have to know what methods ActiveRecord may have added to your model objects. I'm sure that this gets easier with exposure.

Incidentally, this very dynamism has spawned some very interesting workarounds. Since the routing tables are stored as data, it's hard if not impossible to see the set of routes by looking at the code. However, there is a rake target to see the contents of the routing table:
rake routes
Similarly, the migration nature of Rails database management makes it quite hard to quickly grok the structure of the database. However, Rails generates a schema.rb file which theoretically mirrors the current state of your database schema. Perhaps not strictly necessary, but awfully convenient.

Conclusion

In all, I'm reasonably happy with Rails so far. It's quite different from previous experiences that I've had developing web applications. In a way, it hearkens back to when I was first learning HTML. It was trivially easy to write some HTML and then see what it looked like in a web browser. The code/test cycle was very small. Rails brings the same sort of simplicity to web application development. Rather than spend time writing code, you spend time learning how to write the code in the correct Rails mindset.

I don't know if Rails will scale well. I don't know if Ruby will be able to keep up. I don't know if ActiveRecord will strangle us or liberate us. However, I do know myself, and I know that I will stay skeptical for quite some time. Hopefully, one day I will realize that I've been happily writing Ruby code for years and find that neither it nor Rails have failed me.