Wednesday, January 31, 2007

Rails migrations and model changes

On our current project we use Rails migrations for table creation, table modification, and data initialization. Our migrations worked well enough when they were run incrementally through the course of normal development, but failed (seemingly intermittently) when running rake migrate against an empty database. However, running rake migrate again (picking up from where the failure occurred) seemed to magically solve the problem.

Magic in software is not a good thing. It indicates either ignorance in the programmer or bugs in the software. Fortunately this was just a case of ignorance. Our problems were:
  1. Failure to use ActiveRecord's reset_column_information after a migration modifies a table (or before a model is used in a migration).
  2. Failure to periodically test migrations from scratch.
Have you tested your migrations on an empty database? Do it now, rather than when you're trying to deploy your system for the first time.

For details, see the migration documentation here.

Wednesday, January 17, 2007

Brain Repair: Thinking in Ruby instead of BASIC

Brain Damaged

When I see an IF statement in any programming language, it still comes with a THEN. A FOR statement still comes with a NEXT. My first language was BASIC (learned on a Commodore PET in Junior High), and it's still in my head. As Edsger Dijkstra said "It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration." I believe that most of my mental mutilation has been repaired, but some residual damage is apparently there.

In the same essay, Dijkstra also says "The tools we use have a profound (and devious!) influence on our thinking habits, and, therefore, on our thinking abilities." Since switching to Ruby and Rails for the majority of my programming work, I have repeatedly found this statement to be true. Other than some long-ago assembly language programming, my past work has been done in a relatively similar family of languages (C#, Delphi, VB, etc.), causing me to settle into predictable and comfortable thought patterns.

Brain Repair

To dive deeper into Ruby and change some old habits I've been exloring the following with satisfying results:
  • Array and Ennumerable methods: (in the Pickaxe book or here). Arrays include the methods of Ennumerable, so both are worth knowing. Since ActiveRecord returns arrays for multiple record searches, it is good to know more than for and .each to work with the models.
  • Ruby modules: It's beautiful to have something other than inheritance to share behavior between classes.
  • Method parameters: Default parameters, hashes as parameters, variable length argument lists, using a code block as a parameter, using a code block at the end of the method call.
  • Dynamically adding methods to classes and objects.
It is productive to examine the Rails source code, scaffold-generated code, code from plugins and engines, etc. line by line. When I pick someone elses code apart, making sure I understand every method, operator, etc. used, I learn a lot -- fast. It is painful but effective.

Wednesday, January 3, 2007

Ruby now at number 10 on the TIOBE Programming Community Index

Ruby has moved up to position number 10 on the January 2007 TIOBE Programming Community Index (with a rating of 2.519%).

The next 3 positions on the list above Ruby are Javascript (at 2.845%), Python (at 3.502%), and C# (at 3.521%). Interestingly enough, the only language on the list in the top 10 that moved down compared to a year ago was PHP, having dropped from position 4 to position 5.

Tuesday, December 26, 2006

Attacking Ruby on Rails

[Note added 12/28/2006: Caution - this posting was a holidays fogged, sugar-high induced feeble attempt at satire and humor that apparently rubbed many people the wrong way. Don't take it too seriously......]

The Swiss Army Knife

The Swiss Army Knife is a cool tool. It slices. It dices. It has scissors. A long knife blade. A corkscrew. A short knife blade. A file. A saw. Pliers and a screwdriver. If I'm stuck out in the wilderness with just one tool, I want one of these, or a Leatherman, or some similar tool. But I don't use a Swiss Army knife to gut a deer or a fish - it's too big and not something I want coated in blood and entrails. I don't use its screwdriver or pliers when I'm working on a car - it's too small and doesn't fit in tight spots. I don't use its saw to cut wood for the fireplace.

Using the right tool for the right job is a pretty simple concept. So why do so many people forget this when discussing programming languages and software frameworks? They're just tools, and can be selected in the same way. Are people really so stupid as to think that Java, or .NET, or PHP, or Python, or PHP, or LISP, or (insert your favorite language here) is the best tool for every job? I don't think so. So what's really going on when otherwise smart people go ballistic and become zealous warriors for their favorite technology when the topic of Ruby or Rails comes up? Here are some characers I've encountered that shed some light on the subject:

The One Trick Pony

"I've created dozens of kick-ass web sites in PHP. I can do anything in PHP that you can do in Rails. There's more lines of code in PHP than in Rails. There's more PHP job postings than for Rails. No way am I learning anything new, dude. It would cut into my partying and napping time..."

"Ruby is just a degenerate form of LISP. Rails is just an over-hyped Lambda expression."

Python is demonstratably better than Ruby
We have infinite frameworks to choose from
Our superior intellects will make you weep
Take your upstart toy and be gone
The Wise Wizard

"Bow down to my Enterpriseyness! How dare you think you can apply your puny little framework to Serious Business Stuff! You foolish mortals know nothing of the dangers you will encounter. Inflexible DBA's! WSDL, BPEL and Enterprise Buses! Evil database API's! Message Queues! Enterprise Application Integration and Business Process Orchestration! Technology Stacks containing complexities which your feeble minds can't begin to comprehend! Now take your stupid little dog and go back home before someone gets hurt."

The Corporate Framework Guru:
Keep Your Filthy Problem Domains Away From Me

"We have a well-established seniority structure here. The new programmers work on customer-facing code: printed output, reports, user-interfaces. The intermediate programmers work on the business logic that the customers care about - they build classes and business rules that make the system work. The senior programmers work on the fun things that the customer doesn't care about - presentation layers, message processing, persistence engines, process orchestration rules engines. The smarter you are, the better you insulate yourself from boring customer problems. I don't want a fancy framework coming in here and messing up this my nice ivory tower..."

The Drone

"I got my Visual Basic certification just 10 years ago. 3 years ago the company made me go to a training class to learn VB.Net. Now I have a jerk of a new manager that wants me to use C#. My head hurts just thinking about it. No way am I going to experiment with Ruby or Rails. The company won't even let me install it on my machine at work, and I'm too busy to learn anything at home...."


"Open source - isn't that something only commies use? Who provides your support contract? What does Gartner have to say about it? I can't possibly tell the CEO this is a good idea! Blah! Blah blah! BLAH!!! Now get out of my office - I have lots of magazine reading to catch up on and a golfing --er I mean a technology conference trip I have to schedule."

The Chicken

"I'll prototype it in Rails, then build the real app in X."

(This is how I got sucked into using Rails full time. Prototyping is a dangerous gateway drug...)

The Best Tool for the Job

If I was thrown out into the wilderness and forced to pick one toolset without knowing what kind of problem would come along I'd want the .NET Swiss Army Knife. If I was integrating with a rich corporate infrastructure rife riddled with legacy applications, pre-established database schemas, message queues, with some WS- sauce thrown on top, I might want the Java Leatherman. (OK, I'm lying. Actually I'd want to quit, run away, and start my own company with a fresh slate, but that's a different story....)

But if I'm working on a new web-based application, backed by an application database, Rails is the best tool for me, whether the job is large or small.

Thursday, December 21, 2006

Rails Web Service Gotcha: Use Separate Server for Client Testing

Today's painful lesson: If you are developing a web service, and also writing the "client" code that will utilize the web service, don't develop and test both on the same server instance.

In our case, we are exposing some controller code (call it the "server" controller) via a web service, and have a separate controller (call it the "client" controller) that will invoke the service. In the production world, these controllers will be running on separate web servers.

During development, it seemed perfectly reasonable to test both controllers on a single machine. The client code successfully invokes the server code via the web service, but also times out in a bizarre fashion. This occurs under Mongrel and Webrick, and occurs whether the call is made via SOAP, XML-RPC, or REST.

The solution: When on a development machine, start up two Mongrel or Webrick instances on separate ports (say 3000 and 3001). Point your browser at the client controller on port 3000, and be sure the client controller talks to the server controller on port 3001. This requires a bit of environment-specific code, but solves the problem.

Thursday, December 14, 2006

More Ruby / Rails trend indicators

After learning of the TIOBE Programming Community index mentioned in this post a few days ago, I've kept my eyes open for other trend indicators showing trends related to Ruby and Rails. Here are a few more:
  • Google trends, showing a trend history for the search term "Ruby on Rails".
  • A book sale graph comparing trends between various languages.
  • shows a nice graph of the Trend of Ruby on Rails jobs postings.
  • currently shows 135 postings for Rails jobs, 335 postings for Ruby jobs. By way of comparison, Delphi shows 329, Python shows 906, and C#, Java, PHP, and Perl all show 1000 or more.
  • (filterd for the U.S.A.) shows 181 postings for Rails jobs, 286 for Ruby. By way of comparison, Delphi shows 171, Python shows 853, C# shows 6,045, .Net shows 8,347, Java shows 15,122, and J2EE shows 7,674.
Today, my own observation of shelf space allocated to any given programming language at the local mega bookstore showed the following:
  • 6 shelves of books on .NET languages (C#, ASP.NET, VB).
  • 3 shelves of books on Java and J2EE.
  • 1 shelf of PHP books.
  • 1/2 shelf of Ruby/Rails books (a nice increase from the 2-3 books available earlier this year).
  • 1/2 shelf of Python books.
These are all crude indicators, but in combination provide a good view of the emerging Ruby/Rails development community. I'll revisit these numbers in the future to monitor the trend.

Tuesday, December 12, 2006

The Software Complexity Triangle

On recent projects, while drinking the koolaid of delivering simpler, more usable software, I have noticed a Software Complexity Triangle similar to the well known Project Management Triangle. The points on the Software Complexity Triangle are Simplicity, Power, and Design:

On this diagram, Simplicity represents the ease of using a system, both for end users as well as for operational support or back-office staff. Power represents the overall capability and depth of functionality of the system. Design represents the expertise of your software development team, particularly the depth and breadth of their technical skills as well as their knowledge of the problem domain in which they are working.

It is possible to fix in place or optimize for one or two points of the triangle, but the third point must compensate accordingly and cannot be held constant:
  • Most development teams can create unpowerful software that is simple to use.
  • Most development teams can create powerful software that is difficult to use.
  • It takes a highly skilled team to create software that is both powerful and simple to use.
The last item is of key interest. As an example, on our primary project it is critical that our software be simple to use, yet the operations it must perform are unavoidably complex. Our design team has spent many long hours searching for the right balance between power and simplicity on various portions of the system. Often, the end result of our requirement and design discussions results in something like this:

Usually (after recovering for an evening or a weekend) we are able to grind through the issue and eventually create a good solution. But it takes considerable time and effort. Other implications when developing a simple+powerful system are:
  • Planning: Be prepared to spend a lot more time on requirements, designing, prototyping, and reviewing until the combination is right.
  • Hiring: Your team must contain a great depth of domain knowledge - it will not be sufficient to attack the problem with technical wizardry only. Working by rote against a typical listing of functional requirements, use cases, etc. will not deliver a solution of any great value. A true understanding of the real business problems and opportunities to which the system will be applied is critical.
  • Back Office software: "Back end" processing software may need a higher degree of sophistication than the typical mishmash of scripted processing routines.
  • User Interface: It takes an open mind and considerable time and attention to detail to look at your system with the eyes of a new user.
It many cases it is inappropriate to force simplicity and power into the same system (or portion of a system). A reduction in complexity, or less emphasis on simplicity, may be appropriate. Keep in mind the alternate paths this potentially puts you on:
  • Less simplicity results in more user training and documentation. This is not acceptable if your audience is the general public, but may be appropriate if user staff is relatively small.
  • Less simplicity may cause the need for a "Man Behind the Curtain" to make the system work. This might be OK for small systems, but typically does not scale well.
  • Less power: Be certain that your requirements for high end functionality are really necessary - it is often surprising and rewarding to examine requirements through the lens of ROI, schedule impact, and alternative solutions.