This Blog Has Moved

It was only here, for like, two days, but somehow it is showing up in search results and people are visiting. The real blog is here: http://dev.zeraweb.com/blog/mousetrap-2 Thanks! 

Leave a Comment

Site And Blog Reorg

We are moving our open source projects to Google Code, the Web site and blog to WordPress, and preparing for the release of and / or updates to several major open source initiatives. Expect an initial announcement later this week on the first of these projects.

Our Web publishing service is not going away – it is still under active development and, in fact, we are more excited than ever about the next release. However,  our own requirements are better met by existing services (like Google Code), which also help to reduce the load on our servers.

Some (almost all) of the blog entries have disappeared. I plan to revise and re-post some of them; others will become wiki articles on Google Code; still others will disappear forever. In the end, nothing of interest will be lost and we will have a better foundation for future releases and announcements.

Leave a Comment

Top 10 Reasons To Avoid Component Libraries

An interesting commentary over at Ajaxian concerning the proliferation of component libraries (YUI, TIBCO, etc. ):

Sometimes I feel a little bad when people enjoy a new component here or there, when there are tools such as TIBCO, Backbase, and Oracle ADF that have hundreds of them :)

Well, here are 10 reasons why Dion shouldn’t feel bad. :)

  1. HTML is better than proprietary markup. That is especially true when the proprietary markup is in XML, which it almost always is … some of us want markup that describes the interface with libraries that just “hook” into it via CSS and / or some well-defined structure.
  2. My handpicked components load and run faster. Some of these libraries include, as Dion says, hundreds of components. It isn’t always easy to “trim the fat” and get rid of what you don’t need. In addition, the quality of the implementation may vary, particularly in terms of performance. Sorry, I need my page to load fast even over a shaky DSL connection.
  3. Desktop UIs are so 90s. We don’t need to keep trying to make the Web look like the desktop apps. Many of the Web UI idioms that are emerging are far superior to those on the desktop anyway. Let’s keep moving forwards, not trying to go back to the past.
  4. I don’t want your IDE. I have my own already. Thanks for using Eclipse, that’s better than making us use some completely proprietary IDE, but not all of us use Eclipse, either (TextMate, anyone?). Sorry. Bottom line: if using your libraries successfully depends on an IDE, that’s a problem.
  5. I don’t need a drag-and-drop GUI builder. That’s overkill. I’ve been doing HTML for years. It’s relatively simple and I generate most of it anyway from templates. I just want to describe my UI and let your library step in where its needed (see above). It’s called being nonintrusive.
  6. KISS still applies to Web apps. Some Web apps really do need a super auto sorting filtering live editing grid. Most don’t. Sometimes it is better to provide a simple list with a couple of obvious options for editing it. Note how successful Web apps (see Flickr, YouTube, et al) usually follow this approach.
  7. Web development idioms aren’t baked yet. Sometimes I think actually we’re just getting started. Some libraries have a great design that follows current best practices (see Prototype), while others are already outdated before they’re even released. Selectors are a great example of this. Selectors have become a powerful way to bind objects and events to HTML with the (quite recent) availability of fast CSS3 implementations. That dramatically changes the best practices for interacting with the DOM.
  8. ”It’s very nice, but we already got one.” I not only don’t need all of your components, but I may not want some of your “core” code. Selectors are again a great example. I’m quite happy with Prototype’s selector implementation. I don’t want to load a second one, but I can’t take yours out without breaking everything.
  9. Standards-based is good. Thanks for wanting to save me from HTML, CSS, and JavaScript, but I kind of like the fact that the code I write depends only on the community’s continued support of widely adopted standards. For all I know, you may decide that Web apps aren’t quite so important to you anymore a year or two down the road. Sure, maybe you’ve open-sourced the code, but without you, who keeps the platform moving forward?
  10. You still don’t have a WYSIWYG HTML editor. Pretty much anything you can do, I can do better (with the help of the many talented open source component authors out there). But there are a few things you probably could do better, but you don’t. So why do I care?

Is there any component library out there that can say that even seven out of ten of these don’t apply? I’d like to know. I admit, I haven’t looked at each one in detail. After awhile, you get a bit cynical. And you never know when a new release might take a quantum leap. But, for now, I think I’m on pretty sure ground.

Leave a Comment

Ruby Meta-Programming Gotchas

One of the neat features of Ruby is its support for meta-programming. That is code that, essentially, writes code. For example, my Rails ApplicationController has a method called instance, which uses the model name to return an instance variable using instance_variable_get, like this:

def instance  instance_variable_get "@#{model_name}"end

Another powerful technique is the use of method_missing (which I always want to call missing_method for some reason). Rails itself uses this to implicitly add getters and setters for model instance’s attributes.

Danger, Will Robinson!

However, like any powerful feature, there are some dangers that go along with using these techniques. A couple of the more obvious ones:

  • Bypassing private and protected. Ruby has an interesting approach when it comes to meta-programming: it assumes that if you know enough to use these kind of features, you don’t need the programming language to protect you from yourself. By definition, instance_variable_get gives you access to private data. Another method, send gives you access to private methods. This can have some interesting side-effects, as we’ll see below.
  • Unexpected invocation of method_missing. Defining method_missing means that erroneous method invocations will now simply invoke your method_missing. This can lead to strange bugs and infinite loops. For example, from within the class that defines method_missing, even a reference to an undefined local variable can invoke method_missing, since Ruby thinks it might be a method invocation.

But Dan, What Can I Do?

The number one rule about these methods is probably don’t use them unless you have to! However, that’s not much fun, since arguably you never really have to. I coded in C++ for years and did just fine for the most part, and C++ could not play these kinds of tricks – and least not easily. But one of the things that the Rails folks have reminded us about is that there is nothing wrong with wanting to enjoy what you do. And meta-programming is fun.So, having decided that we will use missing_method or method_missing or whatever it is, what can we do to keep from hurting ourselves? Here are a couple of handy little rules:Don’t use meta-programming to access private or protected data. Generally, if you are doing this, you are breaking the interface to the class. If you want to add to the interface, re-open the class definition and add the necessary accessors or whatever. At least that way you aren’t violating the encapsulation of the class.

    In the example above, instance is defined on the controller. The instance_variable_get method is being used entirely because it provides a simple way to access the “instance” of the controller without knowing what the instance variable name is, since it varies from controller to controller. Notice that this, in turn, makes it possible for other methods to access the instance variable for the controller without using instance_variable_get.Save method_missing for last. There is nothing wrong with implementing a method like get_dynamic_attribute or something like that, and then later, once you have the kinks worked out, changing it to method_missing. That way, while you are debugging, you don’t accidentally invoke method_missing and confuse things. Also, you might find that it actually makes more sense to have an explicit interface for such a method. And, after all that, if you still feel like method_missing improves your interface, you can add it quite easily, like this:

      def method_missing(method,*args)  get_dynamic_attribute(method,*args)end

      Use super in method_missing. method_missing allows you to implicitly define methods on a class. However, it also gets invoked even for methods you didn’t intend to define. In those cases, you need to pass along method_missing to the superclass. For example, Rails does this in ActiveRecord objects if you invoke a method that is not actually an attribute of the class. That way, the programmer still gets a missing method exception if they attempt to access a method that you never wanted to define, instead of some mysterious error that might not even make sense to you.

        Which means the above wrapper code should really look like this:

        def method_missing(method,*args)  get_dynamic_attribute(method,*args) rescue superend

        Don’t use send and missing_method together. More on this below.

          Send Buddhism

          Let’s examine one of the mysteries of send. Actually, it isn’t really a mystery of send so much as Object. As I mentioned above, send bypasses private / protected distinctions – you can invoke any method on an object using send. This is very consistent with other meta-programming methods in Ruby. What makes this interesting is that there are a lot of methods defined on Object as private methods. They get pulled in from Kernel and, because they are private, they are easy to overlook. In fact, it is this bit of magic that allows you to use Kernel methods, like puts without referencing an Object.Here is a quick irb session that demonstrates what I’m talking about here:

          irb(main):002:0> class Foo ; end=> nilirb(main):003:0> Foo.new.puts "hello"NoMethodError: private method `puts' called for #        from (irb):3irb(main):004:0> Foo.new.send :puts, "hello"hello=> nil

          However, what this means is that when you use send, you have to remember that all these methods become part of the interface. There are a lot of these and so the interface may not be what you expect it to be when using send. In combination with other meta-programming techniques, including the use of missing_method, this can lead to very unexpected results.

          method_not_missing

          This can come up quite naturally. For example, suppose you want to parse a template that gives you access to an ActiveRecord attribute. You get the name of the attribute and naturally decide to use send to invoke the accessor. However, the accessor happens to be named “display”. Guess what? Instead of the ActiveRecord object’s missing_method (as he corrects himself for the 17th time in this blog entry after writing method_missing), you will get Object#display, which will quietly print the object on standard out and return nil.To your template parsing code, it looks as though the value of the display attribute is nil, when in fact, you have no idea what the value might be. There is no error or exception, either, and you’d have to look closely at your logs to see that anything at all was happening out of the ordinary. This is the kind of bug you can have nightmares about years later.This is another benefit to having an explicit interface for the implicit methods. Then, instead of using send, you can use that method. This is a flaw, in my opinion, of the current ActiveRecord implementation. An improved version would explicitly provide an accessor function in place of the current method_missing, and then simply have method_missing invoke that function, catching any exceptions and calling super.

          Leave a Comment

          Follow

          Get every new post delivered to your Inbox.