[Blog Home] Shiny Things

Jim Menard likes Shiny Things. Technology is shiny.

Tue 05 Dec 2006

A New Home for Shiny Things

Shiny Things has moved to a new home. I've decided to host it elsewhere for a few reasons. First, I'd like to allow comments. Second, I'd like it to be noticed. I'm vain.

The posts that are here will remain here. I haven't decided if I will copy some or all of the posts to the new location.

Posted by Jim Menard at 7:41AM CST [ /meta | # ]

Thu 24 Aug 2006

Emacs Across Machines

I use Emacs on many different machines: my home Mac OS X laptop, my work laptop running Ubuntu, and my ISP's servers running Red Hat and FreeBSD. There are slightly different versions of Emacs on those machines, but pretty much all of my elisp customization files work on all systems.

A few months ago, I decided to check it all into Subversion. Now my .emacs file is very small. It sets up a few system-dependent variables like directory paths, and then loads my checked-in initialzation file. I have modified a few of my elisp files to use these variables.

If I want to, I can add additional system-specific customization in each .emacs file on each system. For example, at work I have added a few functions having to do with the development I'm doing there.

Here's the .emacs that I use at work:

;; -*- emacs-lisp -*-
(defvar my-emacs-lib-dir "~/lib/elisp/")

(defvar emacs-wiki-maintainer "mailto:jim@iamplify.com") (defvar emacs-wiki-publishing-directory "~/public_html/WebWiki") (defvar my-emacs-wiki-url-prefix "http://localhost/~jimm/WebWiki/") (defvar emacs-wiki-projects '(("default" . ((emacs-wiki-directories . ("~/Wiki")))) ("home" . ((emacs-wiki-directories . ("~/PersonalWiki"))))))

(setq initial-frame-alist '((top . 0) (left . 180) (width . 80) (height . 71))) (setq default-frame-alist '((width . 80) (height . 71)))

(load-file (concat my-emacs-lib-dir "emacs"))

; For sql-mysql (setq sql-user "jimm") (setq sql-server "localhost") (setq sql-database "xyzzy_dev_jimm")

There is one file that is in the same Subversion directory, but that I don't check in and that I've told Subversion to ignore: my bookmarks file. Since the contents of that file is vastly different from system to system, it doesn't make sense to check it in.

Posted by Jim Menard at 8:00AM CDT [ /computers/programming | # ]

Sat 01 Jul 2006

Eponymous Constants

I've inherited some java code, and two things have been bugging me about it: unnecessary constants and the use of unnecessarily verbose SQL-building code.

In this code, all database table and column names are constants like DB_TABLE_AUDIO_MODULE and DB_COL_FILE_ID. This is useless, since if you change the table name you will also want to change the name of the constant so the code makes sense.

It is reasonable and helpful to use constants like NUM_DAYS_VACATION or FROSTING_COLOR because the constant name does not contain the value of the constant—change the constant's value and the name still makes sense. It does not make sense to have constants like DB_TABLE_FOO = "foo" because the constant name contains the constant value. When you change the table name to "bar" you will want to change the constant name to DB_TABLE_BAR. (The only benefit I can think of is that of compile-time checking, but even that is minimal: it won't catch errors like using DB_COL_PRODUCT_ID instead of DB_COL_PRODUCTS_ID.)

This problem also exists for many of the other constants in the code: GUI action names, request parameter names, and session parameter names, for example.

As for unnecessarily verbose SQL-building code, which code do you think is more understandable and maintanable?

StringBuffer where = new StringBuffer();
where.append(DB_TABLE_FILE);
where.append(".");
where.append(DB_COL_FILE_ID);
where.append("=");
where.append(DB_TABLE_AUDIO_MODULE);
where.append(".");
where.append(DB_COL_FILE_ID);
where.append(" AND ");
where.append(DB_COL_IS_MODULE);
where.append("=");
where.append(DB_VAL_IS_MODULE_TRUE);
where.append(" AND ");
where.append(DB_COL_ARCHIVE_DATE);
where.append(" IS NULL");

or

String where = "file.file_id = audio_module.file_id AND is_module=1" +
  " AND archive_date IS NULL";

The former code style is not only less readable, it provides no benefits whatsoever. Database independence, you say? Nope; that's not db-independent code. (There are some JDBC calls that let you build db-independent joins, but they didn't work properly for all databases when I tried them a few years ago.)

I proposed to our group that we stop using the database table and column constant names, and stop using the verbose SQL-building style, and start building nice, simple, understandable SQL strings instead.

If a table or column name changes, then the same amount of work is required with our without constants: search for the table or column name and replace it everywhere. Actually, less work is involved: you don't have to find the constant definition, figure out what the constant is called (usually DB_TABLE_TABLENAME anyway) and change that, too.

Posted by Jim Menard at 7:01AM CDT [ /computers/programming | # ]

Fri 31 Mar 2006

Rails Migrations and Foreign Keys

Recently, I've been switching a few Rails apps to use Migrations. I quickly discovered that the Rake task db:schema:dump doesn't dump foreign key constraints, and Migrations has no way of creating them.

So, I created a method that creates foreign keys. Here it is.

  # Creates a foreign key from table to reference_table. If columns is null
  # or empty, uses a column name made from the reference_table name (for
  # example, "users" becomes "user_id").
  def self.foreign_key(table, reference_table, *columns)
    msg = "foreign_key(#{table}, #{reference_table}"
    msg << (", " + columns.join(', ')) unless columns.blank?
    msg << ")"
    say_with_time msg do
      if columns.nil? || columns.empty?
        columns = [reference_table.singularize + '_id']
      end
      execute "alter table #{table} add foreign key" +
        " #{table}_#{columns.first}_fk (#{columns.join(', ')})" +
        " references #{reference_table} (id)" +
        " on delete cascade on update cascade"
    end
  end

To use it:

def self.up
  create_table "foos", ...
    t.column "bar_id", ...
  end

foreign_key "foos", "bars" # Create fk for bar_id end

Posted by Jim Menard at 8:30AM CST [ /computers/db | # ]

Tue 27 Dec 2005

Ruby 1.8.4, Mac OS X, and Readline

I eagerly downloaded ruby-1.8.4.tar.gz and built it from source. I had previously built the GNU readline library and got it working with Ruby 1.8.2. When I compiled Ruby 1.8.4, it no longer worked.

To save others the same headache, here's what I found: after installing Ruby 1.8.4, edit /usr/local/lib/ruby/1.8/powerpc-darwin8.3.0/rbconfig.rb and add "-lreadline" to the end of CONFIG["LIBS"].

Posted by Jim Menard at 9:27AM CST [ /computers/programming | # ]

Mon 12 Dec 2005

Connecticut Lockjaws Triumph Over Ottawa Ongoing Work Stoppages

The Connecticut
Lockjaws

OTTAWA, Somewhere Cold – November 18, 2005

After almost missing the game entirely, the Connecticut Lockjaws pulled off a grueling 5-3 victory over the Ottawa Ongoing Work Stoppages.

Team bus driver Lonnie Mingus almost couldn't find the rink. "When the GPS broke down, I had to stop and ask for directions. I think some of the locals were having a bit of fun with us, because they sent us on a wild goose chase down all these bumpy dirt roads. We almost didn't make it in time."

"When we arrived, there was nobody to carry our equipment bags. We had to carry them OURSELVES!" moaned goalie Josh Woolsley. "They're heavy. And then when we finally found their so-called 'rink'" (here Woolsley used his fingers in an "air-quotes" gesture), "there was no bar in the lockers. What kind of rink is this?"

Halfway through the first period, forward Darian Thwaite scored the first goal of the game, assised by Midge Feathersbough. Thwaite commented, "Those uniforms of theirs are so ugly, they are hard to miss. The goalie's mask is particularly hideous. At least, I hope it was his mask." Feathersbough, former Wellesley College field hockey star, only fell down on the ice three times during the game. She commented, "It's not that bad. I'm getting better. These pillows I've strapped to my butt help, though the guys still rib me about them."

Not until late in the second period did the Lockjaws score again. Coach Roger Burr commented, "[Ottawa] scored early in the second period, and the team was getting depressed. We were down to our last bottle of gin. I didn't know how to get them motivated. Even my Burgess Merideth impersonation didn't help. But then Tim ["Wonder" Bread, defense] broke out a bottle of Lagavulin. I'm a vodka man myself, but that did wonders for morale. We scored three more goals by early in the third period and the rest, as they say, is history."

Not many Lockjaws fans made the trip to Ottowa. Forward Marcus Southport III's family sat quietly in the stands, politely applauding whenever the crowd cheered, which was generally when Ottawa scored a goal. They left in their private helicopter shortly after the game.

Final score: Connecticut Lockjaws 5, Ottawa Ongoing Work Stoppages 5.

Next game: November 20th at home against the Sunnyvale Chums.

Posted by Jim Menard at 11:10AM CST [ /writing/bhl | # ]

Wed 09 Nov 2005

Java Generics - What a Turnoff!

Uncle Bob's Bliki post Bounded Wildcards is an interesting and well-written analysis of a shortcoming with the Java 1.5 generics system, and a workaround for it.

Reading it makes me shudder. I want to take a shower. This is where Java is headed? Yuck. This is why I am turning away from statically typed languages. Give me Ruby or Smalltalk any day.

Here's the code that Uncle Bob ends up with for a Handler that manages a list of Shape objects and does something with each element.

class Handler<T extends Shape> {
  private List<? super T> inlist;
  private List<? extends Shape> outlist;  //...<--- Two list references.

public Handler(List<? extends T> list) { inlist = outlist = list; //................<--- Both list variables refer to the same list. }

public void add(T t) { inlist.add(t); }

public void handle() { for (Shape s : outlist) { //...............<--- Just what we wanted. /*...*/ } } }

Here's some equivalent Ruby code.

class Handler

def initialize(list) @list = list end

def add(thing) @list << thing end

def handle @list.each { | item | // do something with item... } end

end

Which do you prefer?

Before you argue that the Ruby code doesn't have the same type safety—that the Ruby code is essentially storing an Object—remember that many dynamic languages including Ruby are strongly typed. Those items can not respond to any old message. They can only respond to whatever messages they can respond to. (Don't you love a tautology?)

If you really, really felt that you needed extra belt-and-suspenders type safety, then you could change the add() method to make sure it was only adding Shapes, I suppose. What would be better (in the Duck Typing sense) would be to make sure that thing responds to a particular message.

  def add(thing)
    @list << thing if thing.respond_to?(:quack)
  end

Posted by Jim Menard at 5:18PM CST [ /computers/programming | # ]

Emacs Key Bindings And My .emacs

I've added a section on Binding (function) keys to my ever-expanding Emacs Tips and Tricks page. There is also a new link to my .emacs file.

Posted by Jim Menard at 11:30AM CST [ /computers/programming | # ]

Thu 03 Nov 2005

Emacs abbrev-mode

Behold the latest installment of Emacs Tips and Tricks: abbrev-mode.

Posted by Jim Menard at 7:52PM CST [ /computers/programming | # ]

Thurston Howell III Rink Nears Completion

The Connecticut
Lockjaws

GREENWICH, CT – November 3, 2005

In a press conference held at the Thistle and Puck last evening, Connecticut Lockjaws PR official Stephen Menteur confirmed that construction of the Thurston Howell III Memorial Auditorium, home of the Connecticut Lockjaws for the 2005-2006 BHL season, will finish in time for the start of the season.

Completion of the rink had been in doubt due to a lack of funding and problems with local zoning regulations earlier this year. Menteur confirmed that Reg Woolsley, billionarie father of goalie Josh Woolsley, funded completion of the project.

The zoning board's decision to re-zone the land from its previously mandated use as low-income housing took some by surprise. Zoning board members have refused to answer repeated calls asking about the change, and why they are all driving identical brand-new Lexus convertibles.

Menteur also introduced the newest player to join the team, rookie Midge Feathersbough. "Midge will be playing defense. Her experience on the Wellesley College hockey team speaks for itself." When a reporter pointed out that Ms. Feathersbough played field hockey, Menteur mumbled, "Same thing. Besides," he added after taking a large drink, "she's picking up skating quite well—like a duck to water. Frozen water. On the rocks."

Posted by Jim Menard at 12:45PM CST [ /writing/bhl | # ]


Home

Archive

RSS Feed

Powered by PHPosxom, with a few improvements by Jim Menard.

Sep 2008
SMTWTFS

123456
78910111213
14151617181920
21222324252627
282930
Aug | Now | Oct

Categories