Computers, Open-source, Personal, Ruby, Software, Thoughts, Web

Another Helping of Abstraction, Please

Rails 3.1 is soon to be released, and with it comes two new abstraction libraries – CoffeeScript, and S(ass)CSS. These libraries are used to generate Javascript code, and CSS definitions respectively. While abstraction libraries are nothing new to Rails, the inclusion of two more got me thinking about the direction that Rails stack is heading.

CoffeeScript’s syntax seems to be to make Javascript as Ruby-ish as possible. It describes Javascript’s curly braces and semicolons asĀ embarrassing.

SCSS aims to address some of the repetitive elements of CSS through the use of variables, nesting, and mixins. This feels more acceptable to me than CoffeeScript, but my first encounter left me burned.

A few other abstraction libraries of relevance: Haml aims to generate HTML without the use of HTML tags. Additionally, Squeel‘s (MetaWhere 2.0) aim is to remove all SQL from your projects.

So what am I bitching about? Abstraction is a good thing right? I see two categories of abstraction. The first being the “good” kind, that allow you to be completely ignorant of the underpinnings. For example, Ruby converting down into machine code.

The “bad” kind of abstraction are the substitution of a language with a DSL. This creates a lot of issues starting with development and debugging. In the case of CoffeeScript and SASS, you have to compile the DSL files into Javascript, and CSS files. I feel like this compile step is a step back from what we gain working with dynamic languages like Ruby, and Javascript to begin with.

Development in these libraries also requires that you understand both the DSL of the library, as well as being familiar with the language of the generated code. This additional skill requirement adds time to a project, and raises the entry bar for new developers. Its difficult to be proficient at a language, and a DSL that generates that language at the same time. A Ruby developer told me yesterday that he was surprised at how rusty his knowledge of SQL had gotten. Its shocking to me that a web developer would struggle with SQL, but I think its an accurate sentiment on which many Rails developers would agree.

Another casualty of abstraction is performance. Not only is the generated code sub-optimized relative to coding it by hand, it is also being run through through more system calls to get there. You can either compile up front (CoffeeScript, SASS), or you can incur this penalty on-the-fly (Haml, Squeel).

While none of the libraries are a requirement of web development, when working on a team that uses these technologies you are expected to produce consistent code. Even though these libraries let you execute “native” code, doing so is discouraged because of the availability of the DSL. The syntax for embedding native code (if its even allowed) is often cumbersome, and loses editor functionality such as syntax highlighting and parsing.

Since when did Ruby on Rails web developers stop working with SQL, CSS, HTML, and Javascript? I am beginning to feel like the Ruby camp is becoming the far left extremists of the web development world. The web is built on these core technologies, and the benefits of abstracting them doesn’t seem to outweigh the costs.

Computers, Open-source, Personal, Ruby, Software, Thoughts, Web

Action-Packed ActionView Helpers

The Rails ActionView Helpers class es seems to be a gift and a curse. While its sub-classes provide a incredible amount of flexibility, its overlapping and inconsistent naming conventions and fragile parameter passing are a constant headache for me when working with forms. The sub-classes seem to have significant overlap, and if I knew enough to propose a code-change, it may just be worth taking a shot at cleaning up some of this confusion.

I think that I have yet to achieve the simple goal of having successfully constructed a form in the “first-go”. The first part (after constructing your controller and model) to constructing a form opening tag is to use one of the following methods:

form(record_name, options)
form_for(record_or_name_or_array, *args, &proc)
remote_form_for(record_or_name_or_array, *args, &proc)
form_tag(url_for_options, options, *parameters_for_url, &block)

The easiest is form where you pass it the name of a model, and it auto-magically generates your form for you. Not too shabby, but it is pretty inflexible – mostly used for prototyping so I tend to avoid it.

Next is form_for – the method I most commonly use. You can optionally pass it a block, which I will *discuss* in a moment. It is important to note that this is the recommend method per the docs if you are working with a form that represents a model in your code.

remote_form_for is the AJAXish version of form_for, however its naming convention is inconsistent with its cousins link_to_remote and button_to_remote. How about form_for_remote so I don’t pull out my hair when I get a method not found error?

form_tag is intended to help create a form when there is no model defined to represent the form data. In other words, this does very little in the way of magic (*sigh*)

Using form_for, I begin coding my form, and the next step for me is to look at the other helper methods. In part:

text_field(object_name, method, options)
text_field_tag(name, value, options)

These two methods may initially look like there is quite a bit of duplication going on inside the Rails helpers. A closer inspection reveals that the non-“tag” method is geared towards representing a model in the form_for context, whereas the other method text_field_tag is our model-less counterpart. More magic occurs here when the text_field helper method automatically includes the current objects value when constructing the tag. This is useful for sharing the same form (in a partial view) for both the create and edit views:


  

This would create a form for the User model, and generate a textbox for the username method. This is weird to me – that the method text_field would be aware of anything passed to form_for.

To make it even more terse, this can be refactored in DRYer way as:


  

Here we are using the block argument of the form_for tag. This block variable then has methods such as text_field (I assume this is an identically named method and not some other block magic). Also, note form_for assumes that our instance of a User class is contained inside an instance variable named @user – so we can omit that.

Its pretty cool to be able to manipulate forms with this amount of flexibility – three ways that are increasingly terse and assumptious. However, this mechanism of choosing your level of “integration” with a model comes at the cost of confusion to users (or at least me). Looking at the problem and trying to come up with a solution, I decided a possible alternate approach would have been to have one text_field , and and one form_for helper method (that does the work of any other similar methods) that could take in a hash of options to modify its behavior. (like ActiveRecord). A possible usage example might be:

# This will not actually work
 :user, :instance => @user. :html => {}, :url => {}, :errors => flash[:error] do |f|  %>
  # As a block method
   :username}) %>
  
  # Outside the block - passing model and attribute
   :user, :attribute=> :username}) %>
  
  # Without being associated with a model at all 
   :username, :value => '', :html => {}}) %>
  
  # As its own block
  
    
  

The hole goes deeper as we get into more advanced form helper methods such as the select:

select(object, method, choices, options, html_options)

This method is beautifully terse – but approaches being unreadable. The choices parameter (which I think would be better passed along with the other options in one argument as a hash) is typically an iteration of an ActiveRecord find, building an array each pass. For example:

select(:user, :role, Role.all.map {|r| [r.name, r.id], {:include_blank => true}})

This seems awkward to me. Perhaps if the select could be a block instead? For the block, you could indicate the population of values intended to be generated as option tags. You could then write something similar to:

 :user, :options => Role.all} do |s| %>
  
  

If this is done in a generic way, you could potentially eliminate the methods of collection_select, grouped_options_for_select, and options_for_select.

Resources:
ActionView::Helpers::FormHelper
ActionView::Helpers::FormTagHelper
ActionView::Helpers::FormOptionsHelper
ActionView::Helpers::ActiveRecordHelper
ActionView::Helpers::PrototypeHelper

Next week, I will tackle the naming discrepancies between javascript_include_tag and stylesheet_link_tag – arrgh!

Apple, Computers, Linux, Open-source, Software, Thoughts, Web, Windows

The Rich-Internet-Application Bubble

It doesn’t seem to be a question of if, but when we will see the Rich-Internet Application (RIA) bubble burst. Adobe’s Flex platform, and Microsoft’s Silverlight platform promise the world, but their implementation seems to be flawed. The entire discussion seems to always remind me of the story of Java. Consider the following advantages and disadvantages of an RIA system over traditional HTML / Javascript / CSS:

Advantages:

  • RIA platforms promise “rapid application development” (so cliche in the development world). A developer can create a visually rich and interactive application inside the comfort and power of an IDE.
  • RIA platforms can consume data at a level that is not currently possible with current existing web technologies. SOAP, XML and other services can be consumed in a stateless web application.
  • Web applications are treated like traditional applications, offering added benefits like running offline

Disadvantages:

  • RIA platforms are specific to an IDE – in short controlled. Adobe’s Flex promises to be open source, but only on the client end. The “black box” will probably remain just that.
  • If open-source specifications are achieved (unlikely with Microsoft Silverlight) It will take years for alternate IDEs, and editors to support its functionality on a level comparible to what is currently offered
  • RIA platforms add another layer of complexity to an increasingly growing software stack with the need for web services to interact with database sources as the RIAs ironically are not able to.
  • HTML, Javascript and CSS are all free, standardized, open-source, cross platform, and ubiquitous. Microsoft’s Silverlight and Adobe’s Flex are both controlled and shaped by a single company.
  • RIA platforms require a browser plugin, since the technologies generate data that is not directly consumed by any current browser.

Hopefully we remember the failed promises of Sun’s Java VM. The marketing term “write once, deploy everywhere” has become something of an inside joke in the technology industry, as this is hardly ever the case. It should be more appropriately named “write once, deploy anywhere that supports platform ‘x’. This is made worse by the fact that as closed-spec platforms, the RIA browser plugin development is left to the companies pushing the platform. How well do you think Microsoft will support a Silverlight client on Linux, or iPhone?

Performance in RIA platforms has also historically been a sore subject. Java code runs by creating a host-specific virtual machine that abstracts all of an operating system’s details. This works against performance, as the virtual machine will always be the limiting factor – there is simply too much overhead involved.

What each of these companies are pitching to developers is the idea that HTML, Javascript, and CSS are old, and cumbersome to work with. Further, browser inconsistencies make truly agnostic client-side scripting, or styling very limited in implementation. Solutions like Prototype.js, or the CSS browser reset are needed to write agnostic code.

I just don’t buy into it.

First, HTML, Javascript, and CSS are made cumbersome by the fact that no browser (except possibly Safari) adhere to the standards agreed upon by the W3C consortium. Microsoft in particular is selling a tool to abstract browser development, while their browser consistently remains one of the least compliant available.

Second, I think that the success (undeniable when looking at their ubiquity) of HTML, Javascript, and CSS are due to the fact they are free, accessible, open-source, and standardized. Anyone who wants to be a web developer can start right now without ever spending a penny. Developers wishing to use RIA platforms must purchase a developer license to use the IDEs to generate the code.

I hope that the developers of the Internet don’t fall prey to the seduction of RIA offerings. RIA is simply a product being pushed soley on the basis of profit – not with the promise to make the web a better place tomorrow. Instead, I encourage everyone to ride out this wave, and let the technology’s bubble burst.