Jul 062006
 

My buddy Dave Thomas has an interesting blog entry concerning convention vs. configuration. I’ve given it a considerable amount of thought today because it is something that hits you square in the face when switching between frameworks and languages (i.e. WebWork to Rails and back each day).

Both have upsides and downsides and nothing seems to really bring one out as a front runner. Dave’s point about ramp up time is completely accurate. But those configuration nightmares also have that same issue right? No one is really going to memorize what a WebWork validator XML file looks like. Who wants to do that? But they also suffer from double work. The work of coding and the work of configuring, which makes it difficult to compare with convention based programming where configuration is removed.

The major problem I see with convention based programming is always constraints. Of course Rails and Ruby allow you a lot of freedom to modify classes and intercept method calls and stuff like that, which alleviate some of the constraints, but there are constraints. For example, in Rails it is difficult to externalize an action chain and reuse actions for multiple events. Something like this:

If each of the steps are atomic units of work and simply state their outcome as success or failure, this makes sense. You can reuse three because it doesn’t know who it chains to. The chaining is externalized into some XML configuration somewhere. You can pull this off in Rails using YAML and some hacking around inside your controllers, but it can get ugly quick. In something like WebWork, this can be handled entirely in the XML configuration without the code changing at all.

Dave’s second point about maintenance seems to me to be an issue with language rather than framework. Creating crazy method-missing handlers and classes that are defined in 15 files are features of languages and this is where I see the cost of maintenance is incurred. Rails itself doesn’t really let you tweak too much. It seems to me that Ruby let’s you tweak just about anything. Of course, not being an expert in either, I won’t speak definitively about that.

Dave’s last point about Perl I’ve kinda covered already. This happens with configuration and convention. However, with IntelliJ and configuration, you get some pretty good help and code completion that can really make the re-learning much faster. You still have to recall how to code on the configuration side as well as the convention side and nothing can really make that less teadeous and error prone except documentation and good exception messages.

I’m not certain that I fully grok meta-frameworks per se. But I will say this, I have developed systems that are both configuration and convention and they always seem to make me happy. To this day I’m still floored at how few frameworks do this and even more floored and how few people have used mine even if they realize that it supports both styles. The JavaLobby link on Dave’s blog entry covers this a little bit but I think folks still lack the understanding of configurable/overridable conventions.

Take for example the Savant 2.0 alpha I released. This system I love for its use of convention and configuration. If you want to get up and running fast, you can run Savant to create a project layout for you (or just follow the convention for layouts and build one yourself) and that’s it. You can now build, clean, jar, deploy, whatever. The standard layout (the convention) is like this:

Its simple, straight-forward and works with absolutely NO configuration. This is where it gets good though (and personally I feel really Savant excels past Maven and Ant). Let’s say you can’t use the convention or need to tweak it. Let’s say you have this project layout:

Now the Maven folks will say, “that’s three projects with separate JARs” and perhaps it is, but you can’t change it right now or you can’t change it ever and really would like a nice build system to help you out. Well, Savant to the rescue:

This configuration overrides the default project structure and allows you to define as many source directories, build directories, test directories and JAR files as necessary. It even lets you define which JDK to use to compile each one if you want.

The moral of my story is that I think frameworks should always work based on convention right out of the box with as little configuration as humanly possible. Then if you want to tweak, slap down some configuration and go to town! Perhaps this is the meta-framework that Dave is talking about or perhaps not. Either way, this to me seems like a good solution that reduces the overhead as much as possible while still allowing the flexibility to tackle tough situations and problems.

Jul 062006
 

I’ve finished launching my latest Inversoft product – The Inversoft Bad Word Database. The website is written entirely in Ruby on Rails and uses PayPal for purchases. All and all the coding was extremely straight forward and simple. Here’s the address:

http://badwords.inversoft.com

The product idea essentially sprouted from my work on https://www.naymz.com where I need to add some filtering logic to the site so that folks could not enter any restricted words (cuss, slang, swear, superlatives, derogatory, etc.) when constructing their ad for the search engines. Google, Yahoo and the others reject advertisements whose content is not valid or contains restricted words. As I built out the functionality for Naymz, I wanted to test it with some data. Unfortunately there was no data to be found.

I did quite a bit of searching and found that there were services out there who offered a web service you would sent the content to and they would validate it. This just didn’t make sense to me since I wanted to have as few external dependencies as possible and most of these sites could not guarentee reliability, up-time or accuracy of the content filtering. I also found a few other sites that had lists of words, but they were not in a database friendly form. These websites also suffered from the fact that some words I would not consider “restricted” at all and yet again the data would need major scrubbing. Another site I found offered hundreds of thousands of words entered completely by its users. This was probably the worst considering that I had no way of making a determination of which words I wanted to load and which I didn’t because as we all know users will add anything when there aren’t any checks and balances.

What I really wanted was a list of words, with definitions, ratings and categories. So, in my spare time I started building this out. I surfed the web and found all the words I could. I started adding definitions to them as well as a ranking system that would allow applications to adjust the level of leniency they wanted to allow. I also found that many times a list of alternate spellings was need because folks are smart and can beat filters by typing something like sh7t.

After quite a bit of data scrubbing, tweaking and coding, I finished the website and did an initial data load. The initial load contained approximately 500 words and another 500+ misspellings (or something close). The website is live and I’ll be adding words to the database each day and also be building out an multi-language version that contains bad words from as many languages as possible. Check it out and feedback is much appreciated.

Jul 052006
 

Just figured out something very humerous. I’ve just launched a new website that is written in Rails and I got it working with FCGID and Apache2. Works really well. During development I made use of print, puts, p and the other stdout printing functions to output to the console windows that WebBrick runs in. This works great considering that I haven’t really gotten too far into Ruby debugging and unit tests just can’t cover everything.

Needless to say, I should have been using the logger that is available to all ActiveController classes, but the amount of logging in the development.log file gets really excessive. Anyways, there’s is a slight issue with using the stdout methods when you convert over to use Apache and FastCGI or FCGID instead of WebBrick. The issue is that stdout seems to be redirected to the apache mod, which directly feeds back into Apache and then back to the browser. So, what could happen is that your print statements look like HTTP headers to Apache. This of course explodes violently in the Apache error.log file. Quite humerous. Perhaps a better solution is to redirect stdout to the logger or capture stdout in production mode and log errors to the logs or something.

Anyways, just something to watch out for.

Jul 032006
 

Most folks who have coded in Java understand somewhat how to protect your application for the logging performance sink-hole. The sink occurs when you have turned off debugging, but for some reason your application still runs horribly slow. After much research and sout-ing you figure out that your logging statements are being evaluated, just not logged. This occurs because the String expression is evaluated, which might call a number of toString methods on Objects, and the result is passed to the debug method of the logger. This evaluation is what slows everything down. The same applies to Ruby as well and Ruby in fact has a number of cool tricks to help out and make the code a bit easier.

Java folks will remember this as the standard way to ensure that logging statements that create a lot of Objects or call toString won’t be executed unless the logging level is set correctly:

In Ruby there are two forms of logging statements:

These a very similar but drastically different. The first version evaluates the String and passes the String to the debug method on the logger. The second uses a code block and passes a pointer to the code block to the debug method. The second ensures that the block is not evaluated until the logger has determined that all levels are set correctly and that it should print the logging message. This is really key because in Ruby we can build complex logging statements that would take a bit of time to construct, but ensure they won’t be evaluated unless the correct logging level is set, simply by changing our parens to curlies. Pretty slick. In Java you have to wrap the statement in an if block in order to achieve the same goal.

Here’s another cool trick:

This statement is nearly identical to our Ruby logging statement that uses the curly braces instead of parens. The reason is that Ruby will check the if statement at the end of the line before it evaluates the statement itself. Therefore, we can ensure that the string concatenation and conversion of the Object to a string will not occur unless the logger is set to debugging level.

Personally, I prefer the curlies approach as it reduces the overall code.