January 24, 2007

Business Programming in 2007

From Raganwald: Business programming standards have become higher in 2007. Learn to love it.:
But in 2007, you do need to let go of the idea that all we're doing with “business programming” is building web applications that are replacing the client-server applications of the eighties and nineties that themselves replaced the green screen terminal applications of the seventies and eighties.

The “leading edge” interface and ideas employed by Google, Amazon, eBay, and Yahoo! are suffusing our culture to become the standard user interface of web applications. And programming the standard user interface is a basic job requirement. Learn to love it.

Posted by ronlusk at 04:10 PM

January 17, 2007

Magic numbers for testing

Karen writes in Testing by the Numbers that she has a special relationship with…
The numbers: 3, 7, 10, 2038, 32767, 65535, -9, 1.7, and 0. These are numbers I like to test with. There's a reason I use each of these numbers. Each number has a story of its own.

Well worth the reading.

Posted by ronlusk at 11:41 AM

January 10, 2007

Dynamic Programming Languages

In an interview with the JRuby developers, Thomas Enebo—one of the developers—is talking about the difficulty in getting the computer to support refactoring (making the code "better" without changing the code's behavior). He says,
Perhaps it's why dynlang programming starts to feel so right...it's putting trust and control back in our hands.

You might say that dyntyped languages trust the programmer to do the right thing where static typed languages force the programmer to do the right thing. That trust opens up a world of possibilities, but it also takes some responsibility out of the computer's hands—namely, responsibility for exactly that information that's needed to refactor.

It does "feel so right"….
Posted by ronlusk at 03:12 PM

May 12, 2006

Love them^H^H^H^H us cowboy coders

O'Reilly Ruby:

What's the worst-case scenario? Well, I used to have this friend who worked at a tech company we'll call "FooCorp". This is a true story: at FooCorp, the HR department decided to hire a lone cowboy programmer to write a new performance-evaluation tool for the company. The programmer they hired—who had no interaction with the rest of engineering—went ahead and decided to write it in Ruby. With much ado and fanfare, they rolled it out, and with even more ado, a thousand people spent hours entering in their performance reviews. And then, with a truly enormous amount of ado—I mean enough ado to fill several football stadiums—the shiny new Ruby-based perf tool went on a rampage and ate up everyone's performance reviews. Forever.

Was that Ruby's fault? Of course not. In fact I, er, that is, my friend met with the cowboy afterwards to figure out whether the disaster could be undone, and the cowboy announced: “WELL, YOU KNOW, WHEN THE SYSTEM GETS ENUFF CHAOS GOIN' IN THERE, PRETTY MUCH ANYTHING COULD GO WRONG.” And I can't say he was wrong, either.

Needless to say, Ruby got a bad rap at FooCorp for a little while.

Sorry. I just liked the story.

Posted by ronlusk at 04:41 PM

March 16, 2006

Development, via 37signals

Fly on the wall (week of March 16) - Signal vs. Noise (by 37signals)
Sam found this approach “very useful in arriving at a solution”:
  1. write down the problem
  2. write down why it's hard to solve
  3. write down what would make it easier
  4. write down possible ways to implement things that would make it easier
  5. write down why those ways suck
  6. then make it not suck
Ryan's response: “yeah. in early Christopher Alexander-speak, that process pulls the forces apart so you can see the dependencies…you can evaluate all the forces that push on the problem and solution.”
Posted by ronlusk at 05:19 PM

February 16, 2006

Tinkering with Code

I used to write a lot of code—for a solo programmer in “the old days”, perhaps, a hundred-thousand-line program was a lot—in C, C++, and (more recently) Java. This passage from an essay by Trevor Blackwell just rang true.
The best qualities of high- and low-level languages

A well-written program in an abstract language like Ocaml or Lisp has the quality of an elegant mathematical proof: beautiful and concise, but you can't change anything without breaking it. Most programs in C++ are more like an elaborate model train layout, supporting endless tinkering without actually stopping the train from going 'round.

Of course, these days the tinkering can be more intentional, and we call it “refactoring” (“I'm sorry, I can't attend that meeting, this code has some bad smells, and really needs refactoring” might buy you more time than, “Sorry, I'd rather tinker with this old program; have a good meeting.”).

Since I started writing in Ruby (and also, less skillfully, in Python), I've had much less tinkering to do: getting some things done in Java, or in (old-style: I haven't worked a lot with the C++ STL, so things may be different) C++ just needed a lot more little helper classes here and there to sort or iterate or whatever, and they could all use a little polish and dusting from time to time.

On the other hand, there always seems to be more to do, so turning out fewer lines of code for any one task is a good thing, and lingering over it (when it does what it's supposed to and is relatively clear) just doesn't appeal as much as it used to.

Posted by ronlusk at 07:50 AM

December 06, 2005

list_for class method

In a Rails application, I often need to display the child objects belonging to a parent object. For instance, a Community may have a number of Locations within it. If my communities_controller produces a list of Communities, I'd like to have a Locations link for each entry which will ask the locations_controller to list only the Locations for that Community. Thus, I want the LocationsController to have a list_for_community method. Coding this for each level of a structure grows wearisome.

Therefore, I took advantage of the flexibility of Ruby to create a list_for class method, below:

class ApplicationController < ActionController::Base
  # Generate a controller method to list _children_ (of this class) for
  # a given _parent_ of some other class.  
  # @parent@::       name of parent entity, as string
  #                  or symbol: @:community@
  # @order_clause@:: order for listed children: defaults to 'id ASC'
  # @children@::     plural name for collection passed to 'list' view.
  #                  Will default to the prefix of the controller name,
  #                  thus, foo_bars_controller will
  #                  yield a collection named @foo_bars.  For
  #                  that matter, product_controller will yield
  #                  a collection named @products, because
  #                  we pluralize the name anyway.
  #
  def self.list_for(parent,order_clause='id ASC',children=nil)
    unless children
      children = self.name.underscore.gsub(/_controller$/,'').pluralize
    end
    parvar = parent.to_s.underscore
    parcls = parent.to_s.camelize.constantize
    child_qual = children.to_s.singularize.underscore
    child_var = children.to_s
    pages = "@#{child_qual}_pages"
    code = %Q{
    def list_for_#{parvar}
      #{parvar} = #{parcls}.find(params[:id])
      #{pages} = Paginator.new self,
        #{parvar}.#{children}.count, 10, @params['page']
      @#{children} = #{parvar}.#{children}.find(:all,
      :order => '#{order_clause}',
      :limit => #{pages}.items_per_page,
        :offset => #{pages}.current.offset)
        @title = "#{children.humanize} for #{parvar.humanize} '\#{#{parvar}}'"
      render :action => :list
    end
  }
    module_eval code
  end
end

So, if in my locations_controller.rb file I have the line

  ...
  list_for :community, 'Service_Location ASC'
  ...
the class method will generate a list_for_community method that expects the id parameter to identify a community. It will then pass to the default 'list' view an instance variable @locations (it takes the name from the controller class) which contains only the locations for the selected community.
Posted by ronlusk at 12:32 PM

November 06, 2005

Switch early, late, and often?

In a discussion of the average programming language, and Beating the Averages, Paul Graham goes on to write:
But once you've admitted that [Perl 5 is more powerful than Perl 4], you've admitted that one high level language can be more powerful than another. And it follows inexorably that, except in special cases, you ought to use the most powerful you can get.

This idea is rarely followed to its conclusion, though. After a certain age, programmers rarely switch languages voluntarily. Whatever language people happen to be used to, they tend to consider just good enough.

Maybe always looking for a new language is a good idea.

Update:I fixed a typo above.

Posted by ronlusk at 09:23 PM

October 29, 2005

Speeding up Rails testing

In Faster Testing with Rails 1.0, Mike Clark talks about the changes to testing default in Rails 1.0.
Herewith, an overview of the new testing stuff, a how-to for upgrading your existing tests (though you don't have to), an obligatory math formula or two, and a performance comparison that's worth about as much as you paid to read this.
So I gave it a try...and was more than pleasantly surprised: the total test time was reduced (in one set of runs) from seven minutes down to about 40 seconds: the optimized tests run in just about 10% of the original test time.
Test Suite Run Times for Rails Testing

The following table shows the run times (in seconds) for my Culinary Census test suite. There are maybe 260 to 300 rows of data generated by the fixtures in 15 or so tables. Some 250 rows are static, the rest dynamically generated.

Type of Test No Optimization Non-instantiated Transactional NI
and
Transactional
Unit Tests
96 tests, 474 assertions
370 86 325 35
Functional Tests
47 tests, 170 assertions
60 15 47 6
Total 430 101 372 41

Legend

Use
Transactional
Fixtures
Use
Instantiated
Fixtures
No Optimization false true
Non-instantiated false false
Transactional true true
NI
and Transactional
true false
Posted by ronlusk at 05:47 PM