Use with caution:
That said, with is discouraged in JavaScript. If you can, its better to have methods return self so you can chain like so: people.get_dressed.put_on_music.and_party!
Looks like Joe O’Brien tagged me for answers to the following questions. He, in turn, was tagged by Josh Owens, who in turn was tagged by Jeff Blankenburg. It looks like Sarah Dutkiewicz and Micheal Eaton started this.
OK, sounds like fun. Here goes.
I was introduced to programming in high school by reading a book on the topic. The book taught me how to write machine code for a strange decimal-based machine. Unfortunately, there was no actual computer involved in the process. Shoot, who had computers back then? Certainly not our high school (the personal computers? not invented yet!)
In college, I learned a smattering of FORTRAN. Just enough to drive a Calcomp plotter to plot data from my undergraduate physics courses. But didn’t really get into programming until my junior year in college. (Story continued in next question)
So, I was planning out the courses for my junior year in college and I had a hole in my math courses. The math class I needed was not offered that semester, so my adviser suggested taking a computer programming course. He said it would be useful and, who knows, I might enjoy it.
So I signed up for an introduction to FORTRAN course, figuring it would be easy because I already knew a little bit of FORTRAN. I show up on the first day of class and after a few preliminaries the instructor jumps right into some code, that looked like this:
(de member (pip deck) (cond
((null deck) nil)
((eq pip (car deck)) t)
(t (member pip (cdr deck)))))
I remember scratching my head and thinking this was the strangest FORTRAN I had ever seen. I was totally confused for about three days, then something clicked on the third day of class. I suddenly “got” what the instructor was trying to get across and it all made perfect sense.
If you haven’t figured it out yet, the instructor taught us Lisp as part of an introduction to FORTRAN. The instructor turned out to be Daniel Friedman, the author of The Little Lisper, and was well known in the Lisp community. That small exposure to Lisp hooked me on programming from that point on. I took as many CompSci courses as I could in my remaining year and a half in college. I eventually graudated with a BS in Physics, but had a strong background in Computer Science as well.
Technically, FORTRAN was my first language. But Lisp is the language I fell in love with and is what got me hooked on programming.
I have a very clear memory of the very first program I wrote professionally. The reason it is so clear is that this was the first program I wrote that was intended for actual use by someone who wanted it. Everything else up to that time was done for my own personal enjoyment or to satisfy some course requirement.
The program calculated the “critical angles” of “pieces”. I was given the requirements by Anne Exline, a senior programmer, and proceeded to write the program to spec. It took a few days, but when I was done I showed the result to Anne and she was pleased with the result.
The funny thing is that I had no idea what a “piece” was nor what was so critical about the angles I was calculating. I was so excited about writing an actual program that I did not ask until the software was done. When asked, Anne just looked at me funny and said “Rocket Pieces”. When Cape Canaveral lauches a rocket, they track it very carefully to make sure it stays on course. If it strays, the range safety officer is required to activate the self destruct. The critical angles are those angles that would cause the “rocket pieces” to land outside the safety area of the flight path.
So, my very first professional program was not only useful, it might actually save lives.
Languages I have used as part of my professional career (in roughly chronological order) include FORTRAN, various assembly languages, FORTH, C, PL/M, C++, Java, Ruby.
Languages I have used in addition to those mentioned above: Pascal, Perl, Eiffel, and Lisp/Scheme.
Languages I can read, but never wrote anything significant in them: Ada, Python, Erlang, Smalltalk, SNOBOL, Algol, Pascal.
I was hired by the RCA Missile Test project in Cape Canaveral, Florida as a Near Real Time Analyst. Duties included programming various launch related software (e.g. the critical angle program mentioned above) and working launch support.
The launch support was the “Near Real Time” part of the job description. From the moment a rocket is launched until it reaches orbital velocity, any malfunction could cause it to fall back to earth. During this initial portion of the launch, the launch is monitored in “real-time” so that we know exactly where it would land if the engines were to cut off NOW. Trajectory calculations had to be done in fractions of a second and updated constantly in real time.
After the rocket reaches oribital velocity (usually somewhere between 8 and 14 minutes into its flight), it won’t fall back to earth. At this point the real time trajectory program is shut down and the near real time program is started. The near real time program can take a few minutes to calculate a more exact orbital prediction and then send that prediction to downrange radars (e.g. the the Ascension Island station) that won’t see the rocket until about 20 minutes after launch. It was the job of the Near Real Time analyst to run that program and provide oribital predictions for downrange station.
Find something that you enjoy and do that. Life is too short to work in a job that you dislike.
Oh, the fun I have had. This story still makes me smile.
My first computer was a single board Z80 microcomputer with 4 KB of memory. I wrote a small FORTH-like interpreter for it and hacked a version of the animal game in FORTH. The animal game is a program that plays 20 questions to figure out what animal you are thinking of. It constructs a binary tree where each node is a question and the subtrees are the yes and no answers to the question. To play the game, all the program does is walk the tree, ask the question at the current node and follow either the YES branch or the NO branch as appropriate.
If the program guesses wrong, it will ask you for your animal and a question that will distinguish your animal from the one it guessed. It then adds your question to the tree. By this extremely simple mechanism, it is able to expand its knowledge base. (see Ruby Quiz #15 for more details).
I had just finished the program and had seeded it with a single animal, a mouse. I turned to my wife and asked her to play the game. She thinks of an animal and starts the program, which immediately asked her “Is it a mouse?”. She turned to me with surprise and said “How did it know?”. Of course, the animal she picked was a mouse.
I don’t think I have ever impressed anyone with my programming skills as much as she was impressed with that game.
I’m tagging the following people. Remember, this is entirely voluntary so don’t feel obligated to answer. But I’m betting the answers are interesting:
Wow, what a great conference! There was a lot of energy flowing at RailsConf this year. Overall I’d rate this year as head and shoulders above last year. I’m not going cover much here, but will direct you attention to a Rails Envy VideoCase that Greg Pollack put together. The video is a series of very short interviews with a number of presenters giving summaries of their own talks. The only downside with the video is that I wish it was available before the conference. I see there were a number of interesting talks that I missed.
Joe O’Brien, Chris Nelson and myself did a dialogue style presentation on the difference between object modelling and data modelling. The most common question I got after the talk was requests for book titles to learn more about object oriented modelling. Here are the books that Joe, Chris and I have recommended:
The Musician’s Birds of a Feather gathering at RailsConf was great. We had a room full people, two guitars, a ukulele, a flute, several harmonicas and an improvised drum set. Unfortunately, one of the guitars was an electric travel guitar which had a dead battery, therefore no way to really hear it.
However, the other guitar was a nice Epiphone accoustic which was passed from player to player. It became the quickly became the basis for most of the music performed that night.
I want to thank Artichoke Community Music for supplying the guitar. Travelling with a guitar by plane is a big pain, so I arrived with nothing to bring to the music BOF. I called several local music stores looking for a guitar that I could rent for an evening. Artichoke music said they had a “not-for-profit” guitar that they would let me borrow for a day. Not many stores would do that for an out-of-town stranger.
So, if you’re in Portland looking for a good guitar store, check out the great people at Artichoke Community Music.
Joe O’Brien and I will be leading another Test Driven Studio in Denver, June 9-11.
About 8 years ago I come upon a technique that radically changed the way I developed code. I was reading Martin Fowler’s “Refactoring” book and came across this paragraph:
“Whenever I do refactoring, the first step is always the same. I need to build a solid set of tests for that section of code. The test are essential because even though I follow refactorings structured to avoid most of the opportunities for introducing bugs, I’m still human and still make mistakes. Thus I need solid tests.” —Martin Fowler
Chapter 4 of “Refactoring” was my first introduction to JUnit and got me interested in “Test First Design” (what we now tend to call “Test Driven Development”). Although I wrote good code before, the confidence I had in my code took a dramatic leap forward after I started adopting TDD practices.
On June 9 through 11, Joe O’Brien and I will have the pleasure of leading the next Pragmatic Programmer’s Test-Driven Development with Rails Studio. in Denver. We will have an opportunity to share with you some of our experiences in using TDD with Ruby and Rails.
There are still seats available, so its not too late to sign up. More information is available here.
I stumbled across this and it got me thinking …
I’ve updated the Textile formatter on the site and the code for this entry is now displaying correctly. The previous version was swalling the == operators in the code.
I stumbled across this in Bill Clementson’s blog and remembered using the Lisp 1.5 Prgrammers manual from the college years. I have strong memories of pouring over that particular page in the manual and attempting to understand all the nuances.
If you’ve never read the Lisp 1.5 Programamers Manual, page 13 is the guts of a Lisp Interpreter, the “eval” and “apply” functions. It is written in Lisp, although the notation used is a bit funky. The entire interpreter (minus two utility functions) is presented on a single page of the book. Talk about a concise language definition!
I had often thought about implementing a Lisp interpreter, but back in the “old days”, the thought of implementing garbage collection and the whole runtime thing was a bit daunting. This was in the day before C, so my implementation language would have been assembler … yech.
But as I was reviewing the page, I realized that with today’s modern languages, I could problably just convert the funky M-Expressions used on page 13 directly into code. So … why not?
Here is the complete Ruby source code for the Lisp interpreter from page 13 of the Lisp Programmers manual:
# Kernel Extensions to support Lisp
class Object
def lisp_string
to_s
end
end
class NilClass
def lisp_string
"nil"
end
end
class Array
# Convert an Array into an S-expression (i.e. linked list).
# Subarrays are converted as well.
def sexp
result = nil
reverse.each do |item|
item = item.sexp if item.respond_to?(:sexp)
result = cons(item, result)
end
result
end
end
# The Basic Lisp Cons cell data structures. Cons cells consist of a
# head and a tail.
class Cons
attr_reader :head, :tail
def initialize(head, tail)
@head, @tail = head, tail
end
def ==(other)
return false unless other.class == Cons
return true if self.object_id == other.object_id
return car(self) == car(other) && cdr(self) == cdr(other)
end
# Convert the lisp expression to a string.
def lisp_string
e = self
result = "("
while e
if e.class != Cons
result << ". " << e.lisp_string
e = nil
else
result << car(e).lisp_string
e = cdr(e)
result << " " if e
end
end
result << ")"
result
end
end
# Lisp Primitive Functions.
# It is an atom if it is not a cons cell.
def atom?(a)
a.class != Cons
end
# Get the head of a list.
def car(e)
e.head
end
# Get the tail of a list.
def cdr(e)
e.tail
end
# Construct a new list from a head and a tail.
def cons(h,t)
Cons.new(h,t)
end
# Here is the guts of the Lisp interpreter. Apply and eval work
# together to interpret the S-expression. These definitions are taken
# directly from page 13 of the Lisp 1.5 Programmer's Manual.
def apply(fn, x, a)
if atom?(fn)
case fn
when :car then caar(x)
when :cdr then cdar(x)
when :cons then cons(car(x), cadr(x))
when :atom then atom?(car(x))
when :eq then car(x) == cadr(x)
else
apply(eval(fn,a), x, a)
end
elsif car(fn) == :lambda
eval(caddr(fn), pairlis(cadr(fn), x, a))
elsif car(fn) == :label
apply(caddr(fn), x, cons(cons(cadr(fn), caddr(fn)), a))
end
end
def eval(e,a)
if atom?(e)
cdr(assoc(e,a))
elsif atom?(car(e))
if car(e) == :quote
cadr(e)
elsif car(e) == :cond
evcon(cdr(e),a)
else
apply(car(e), evlis(cdr(e), a), a)
end
else
apply(car(e), evlis(cdr(e), a), a)
end
end
# And now some utility functions used by apply and eval. These are
# also given in the Lisp 1.5 Programmer's Manual.
def evcon(c,a)
if eval(caar(c), a)
eval(cadar(c), a)
else
evcon(cdr(c), a)
end
end
def evlis(m, a)
if m.nil?
nil
else
cons(eval(car(m),a), evlis(cdr(m), a))
end
end
def assoc(a, e)
if e.nil?
fail "#{a.inspect} not bound"
elsif a == caar(e)
car(e)
else
assoc(a, cdr(e))
end
end
def pairlis(vars, vals, a)
while vars && vals
a = cons(cons(car(vars), car(vals)), a)
vars = cdr(vars)
vals = cdr(vals)
end
a
end
# Handy lisp utility functions built on car and cdr.
def caar(e)
car(car(e))
end
def cadr(e)
car(cdr(e))
end
def caddr(e)
car(cdr(cdr(e)))
end
def cdar(e)
cdr(car(e))
end
def cadar(e)
car(cdr(car(e)))
end
And to prove it, here’s an example program using Lisp. I didn’t bother to write a Lisp parser, so I need to express the lists in standard Ruby Array notation (which is converted to a linked list via the “sexp” method).
Here’s the ruby program using the lisp interpreter. The Lisp system is very primitive. The only way to define the function needed is to put them in the environment structure, which is simply an association list of keys and values.
require 'lisp'
# Create an environment where the reverse, rev_shift and null
# functions are bound to an appropriate identifier.
env = [
cons(:rev_shift,
[:lambda, [:list, :result],
[:cond,
[[:null, :list], :result],
[:t, [:rev_shift, [:cdr, :list],
[:cons, [:car, :list], :result]]]]].sexp),
cons(:reverse,
[:lambda, [:list], [:rev_shift, :list, nil]].sexp),
cons(:null, [:lambda, [:e], [:eq, :e, nil]].sexp),
cons(:t, true),
cons(nil, nil)
].sexp
# Evaluate an S-Expression and print the result
exp = [:reverse, [:quote, [:a, :b, :c, :d, :e]]].sexp
puts "EVAL: #{exp.lisp_string}"
puts " => #{eval(exp,env).lisp_string}"
The program will print:
$ ruby reverse.rb
EVAL: (reverse (quote (a b c d e)))
=> (e d c b a)
All I need to do is write a Lisp parser and a REPL, and I’m in business!
If you found the Ruby-ized Lisp code hard to read, here is the reverse funtions written in a more Lisp-like manner.
(defun reverse (list)
(rev-shift list nil))
(defun rev-shift (list result)
(cond ((null list) result)
(t (rev-shift (cdr list) (cons (car list) result))) ))
I received some feedback on the ‘Presenting Code’ post from yesterday.
I got lots of feedback on the “Presenting Code” post. In addition to Cédric Beust’s initial comments, the following people had something to say on the topic:
John Wilger asked on Twitter why I didn’t use “file:” (rather than “http:” and a local web server). Unfortunately, Keynote will not do a web view from a “file:” style URL.
Luke Kanies reports that he does something similar. He uses Vim (rather than Ruby + the Syntax gem) to generate the highlighted HTML. He also adds:
In general, this method works out great, but the one thing I would say is that you should always uncheck “automatic update”. Otherwise, you’ll find that it tries to update 10 seconds before your presentation starts and your web server isn’t available.
Ok, that’s good advice. BTW, I would be very interested in a script (AppleScript or Ruby+OSA) that would iterate over the pages in a Keynote presentation and refresh all the WebViews. Any takers?
James Edward Gray II and Mike Clark mentioned the HTML output bundle. James gives the following details:
Mike (who credits Bruce Williams as his source for this tip) also provided a video.
Couple of items on the above:
Dr. Nic also mentions a “Copy as RTF” TextMate bundle. (I’m not sure if this is the same as James and Mike’s hint above or something different).
Finally, Chris Nelson confirms (via Twitter): “AFAIK there is no equivalent of web views in OpenOffice :(“
This exchange on twitter got me thinking…
I noticed the following twitter conversation this evening between objo and superchris:
superchris: any good recommendations on showing code samples in OpenOffice Impress?
objo: @superchris yeah, get a mac and use Keynote
objo: otherwise, I would screenshot emacs
superchris: @objo.. ya know, i almost added “And I’ll smack anyone who says get a Mac” but ran out of space
superchris: @objo… but actually your idea of using NetBeans screenshots is pretty good
objo: @superchris you never listen …. EMACS not netbeans. Come on man.
superchris: @objo just being helpful by translating for you.. :)
superchris: planning to code with NetBeans on linux forever for no other reason but to annoy @objo
The problem Chris is trying to solve is putting code snippets into a presentation. There just isn’t a good way to do this in modern presentation programs.
In the old days, I would generate my presentation completely in HTML from a simple text markup file. The generation process was controlled by rake. This allowed me to changed the code, run the unit tests and rebuild the presentation all with a simple rake command. Eventually, I got up to speed with CSS and could make some really nice looking presentations, all from HTML.
Although I could get nice looking slides with CSS, it was a lot of work getting it to work just so. Eventually, I abandoned that approach and swithed to a modern slide presentation program (Keynote in my case).
Although generating the slides is a bit easier in Keynote (or PowerPoint, or Open Office Impress), reproducing code for technical talks is much harder. You generally have two choices:
Neither option is pleasant. The former punishes the audience by making the code harder to read, the latter punishes you making the presentation hard to change. (I once saw Dave Thomas giving a Ruby talk and he noticed that he had a minor typo in the code. He switched to edit mode in Keynote with the intent of fixing it on the spot, then he realized that the code was in a graphic image and was uneditable).
Of the two options, I’ve been using the text cut’n’paste technique for most things. In the twitter conversation above, Chris is considering the edit snapshot technique.
I’ve heard rumors of someone working on a script that will insert code snippets into the Keynote data file directly. Unfortunately, as far as I know, they are still rumors at this time.
But here’s another idea. I’ve prototyped this, and think it will work. But be warned I haven’t tried this on a really presentation yet.
While perusing the options in Keynote, I noticed an insert option called “Web View”

It turns out that this option allows you to include a web page in your presentation. For example, here is my blog inserted directly into the presentation. Clicking on the “web view” object will show an “update” button that will refresh that page from the web.

So, all I have to do is get the code onto a web page, formatted nicely with syntax highlighting, and Keynote will suck it into the presentation, more or less automatically for me. Cool.
Getting it formatted is easy. That’s just a small little Rake task
with a good syntax highlighting library. I used Syntax (its a gem,
docs on Rubyforge), but there are other options out there.
Here’s the rakefile:
#!/usr/bin/env ruby
require "rake/clean"
CLOBBER.include('*.html')
task :default => :extract
task :extract => "hello.html"
file "hello.html" => "hello.rb" do
extract "hello.html", "hello.rb"
end
and here is the rakelib/extract.rake library:
#!/usr/bin/env ruby
require 'syntax/convertors/html'
def extract(outfile, infile)
open(outfile, "w") do |out|
out.puts "<html>"
out.puts " <head>"
out.puts " <style type=\"text/css\">"
out.puts %(
.ruby { font-size: 24pt; font-weight: bold; }
.ruby .normal {}
.ruby .comment { color: #888; font-style: italic; }
.ruby .keyword { color: #A00; font-weight: bold; }
.ruby .method { color: #077; }
.ruby .class { color: #074; }
.ruby .module { color: #050; }
.ruby .punct { color: #447; font-weight: bold; }
.ruby .symbol { color: #099; }
.ruby .string { color: #944; }
.ruby .char { color: #F07; }
.ruby .ident { color: #004; }
.ruby .constant { color: #07F; }
.ruby .regex { color: #B66; }
.ruby .number { color: #D55; }
.ruby .attribute { color: #377; }
.ruby .global { color: #3B7; }
.ruby .expr { color: #227; })
out.puts " </style>"
out.puts " </head>"
out.puts " <body>"
out.puts " <pre class=\"ruby\">"
code = open(infile) { |f| f.read }
convertor = Syntax::Convertors::HTML.for_syntax("ruby")
html = convertor.convert(code)
out.puts html
out.puts " </pre>"
out.puts " </body>"
out.puts "</html>"
end
end
Edit the CSS styles above to tweek the output to exactly the colors you want. I’ve added a large font-size line to make the code big enough for teh presentation (I hate small code fonts in presentations, you can ask objo about my rants on that topic.)
Now we need to get the code on a web page. No need to get fancy here.
I have a script called servefiles that will start a webrick process
that serves files from the current directory. Just start it up with
“servefiles 3333” (the 3333 is the port to use). Servefiles will
display its URL in its startup message, like so:
$ servefiles 3333 URL: http://tardis.local:3333 [2008-03-23 00:47:37] INFO WEBrick 1.3.1 [2008-03-23 00:47:37] INFO ruby 1.8.6 (2008-03-03) [i686-darwin9.2.0] [2008-03-23 00:47:37] INFO WEBrick::HTTPServer#start: pid=874 port=3333
Here’s the code for servefiles:
#!/usr/bin/env ruby
require 'webrick'
include WEBrick
dir = Dir::pwd
port = (ARGV.first || (12000 + (dir.hash % 1000))).to_i
puts "URL: http://#{Socket.gethostname}:#{port}"
s = HTTPServer.new(
:Port => port,
:DocumentRoot => dir
)
trap("INT"){ s.shutdown }
s.start
Now all we have to do is cut and paste the URL given by servefiles
into keynote and append the HTML file name we wish to add to our
presentation:

Now, to update the code in the presentation, I need to:
Not bad.
Just be warned, I haven’t tried this in a real presentation yet. I’ve just spent an hour or so seeing if all the pieces would work together. There are some obvious things to explore.
I will probably experiment some more with then in my next code heavy presentation. Let me know if you try this and how it work for you.
Cédric Beust points out that cutting and pasting from Eclipse to PowerPoint does preserve syntax highlighting. I verified the same is true for Eclipse and Keynote. However all the other IDEs and editors I tried (NetBeans, Coda, TextMate, Emacs) will paste as plain, uncolored text in Keynote. So, if you are going the cut and paste route, you might want to consider using Eclipse for the cut source.
Just for kicks I tried the presentation software in OpenOffice with the same result. Eclipse copies will preserve highlighting, none of the others will.
So, there you have it.
Ryan Tomayko has pointed out, my blog title does not conform to standard Ruby coding conventions. We need to fix this.
Ryan Tomayko has done a review of blogs using code snippets as there title and has pointed out that mine does not conform to generally accepted Ruby coding standards. You see, in “{ | one, step, back | }” I use spaces between the vertical bars and the argument names. Proper Ruby code would never be written that way.
He’s right. So in order to promote better Ruby coding practices, I’m renaming the blog to “{ |one, step, back| }”.
Let it never be said that I ignore standards.
An aside: The use of {||} in the title was inspired by a Smalltalk logo that used [|]. See the powered by banner at the bottom of the sidebar in James Robertson’s blog for an example.
Most Unwanted Scrobbles - Last.fm aggregates the tracks and artists that people don't want the internet-at-large to know they listen to. Britney Spears appears twice in the top five songs, along with Nelly Furtado, Amy Winehouse and Avril Lavigne. The top artists are The Beatles, Radiohead, Britney Spears and Avril Lavigne are the top 5 arists (along with Unknown.)
So I guess Last.fm users are just too damn cool to admit to some of their tastes. Me, I'm fine with letting you know I listened to Sir Mix-A-Lot's Mack Daddy in its entirety this week.
Thanks to Aaron's continued efforts to make us ever more security conscious, I've been encrypting client data on my laptop. This came up in conversation during erubycon (thanks EdgeCase for a fun conference with engaging evening events). A couple of people asked me to get them started on encrypting their data too.
Here are instructions. They're written for Mac users, but they'd be nearly identical for Linux and Windows users since TrueCrypt is available there too.
client_data./Volumes/client_data. This is by far the slowest part of the process. Watch The Enemies of Reason (48 minutes -- everything else should take 5 minutes or less).As mentioned in my previous blog entry, I use a script to automatically create aliases to allow easy switching to project directories. All I had to do was switch that entry to point to /Volumes/client_data instead of the old ~/work/client_data. Now, when I want to work on client projects or contracts, I launch TrueCrypt, mount the container and open a new terminal window. All my old aliases work just like they used to.
Mac users: if you don't care about the cross-platform compatibility that TrueCrypt offers, and trust Apple to encrypt your data, you could use Disk Utility to create encrypted partitions instead. Some people insist it's more convenient (You know who you are!).
Designing software is a tricky thing. It's tempting to front-load it on a project. That won't work because the start of a project is when you know the least about it. So some folks try to do as little design as possible. I'm guilty of this. However, that can lead to software that doesn't adequately express the problem it's trying to solve. Further, there is often a temptation to over-design software with lots of ceremony and architecture. Contrary to this is the temptation to not design it at all, which again leads to software that doesn't express itself.
There's a book that draws a reasonable compromise between these forces. I've been meaning to read Eric Evans' Domain Driven Design for a while now. The emphasis of the book is in collaborating with domain experts and other developers to find the essence of the problem space and then express that in software (as objects). I've often pointed out the utility of building applications from the language up and the problem domain down. DDD focuses precisely on the latter.
One of the core concepts in the book is the ubiquitous language that is used to describe the problem at hand. This language is used by the domain experts (customers) and the developers. The language is then woven into the design of the system. This leads to software that is more likely to succeed, both in business terms and in terms of development effort. Evans spends the first part of the book describing the particulars of this language.
He then moves on to describing the technical side of the software. Entities, value objects, services, factories, modules and repositories are terms I was already somewhat familiar with that Evans gave a more crisp and satisfying definition to. For most people, this is probably the tasty meat of the book, illuminating the way from a competent developer to an outstanding developer.
The last part of the book focuses on the larger scale issues of deep design. I was particularly pleased that he covers how software design is affected by various good and bad social issues. It also gives a strategic view of the forest, where most books on software development focus on a more tactical view of each tree.
I'm fond of pointing out books that are inflection points in my way of thinking about software development. Code Complete, The Pragmatic Programmer, The Dragon Book and My Job Went To India all fall under this category. Domain Driven Design is certainly the latest edition. It makes sense of trends I see in great software and illuminates a path to make software like it myself.
If reading this review didn't make you want to vomit, you should probably read the book posthaste.
Another call to tech upport. I’ve spoken to more people in India this week than Kipling in his lifetime.
The second part of my interview with David Flanagan is online. This time around we talk about the craft of programming in general. Its good stuff.
I didn't manage to touch on this in What Has Ruby Done For You Lately, but Io is a really impressive language. Mostly in the minimal number of concepts one needs to grasp in order to deeply understand the language.
To pick on Java (sorry), a list of concepts you need in order to grasp Java:
I'm sure I'm missing some. Further, that's just what you need to write a program with one class. To build a realistic system you need to know about class paths, packages and all sorts of arcane details.
In comparison, to build a simplistic Io program, you need to understand:
That list ended up about twice as long as I thought it would, actually. Really, all the average practicing programmer needs to learn is prototypes and lazy evaluation.
Io's guiding design principle is simplicity and power through conceptual unification.
That quote, from the Io Programming Guide, pulls it all together and summarizes why the language nerd in me is quite interested in Io.
I’ve been following various blog posts and tweets concerning last night’s Ignite Phoenix, and quite a few people (myself included) have expressed excitement of the next one.
Here’s the thing: Lots of people want a next one, but a next one only happens if people step up and make it so. Jeff and Rodger did a kick-ass job, and a mighty Thanks! to jobing.com (BTW, where’s the second ‘b’ in there? job -> jobbing; jobe -> jobing) for providing the space. But they’re not going to doing this as a regular gig, and it’s unfair to expect that of them.
There’s a special satisfaction in pulling of an event like this, but it’s also work. I run two monthly user groups (Ruby AZ and Refactor Phoenix), used to help organize Refresh, and have instigated two local BarCamps, so I know the drill.
If you think you’re up for this, and want to help drive the next Ignite Phoenix, drop a line to IgnitePhoenix [AT] gmail.com and start asking questions.
If you can offer some sort of sponsorship, speak up. If you can help arrange a good location to host the next event, step up.
Drivers wanted!
OK, here's the deal. If you're not watching 30 Rock, you're not watching the best show on TV. There I said it. Fortunately, you've got time to catch up; the show doesn't come back until October 30th. To whet your appetite, I give you clips summarizing the “lives” of the two main characters, played by Alec Baldwin and Tina Fey.
The first-ever Ignite Phoenix ruled. 16 talks, each ~5 minutes, zip zip zip things moved along and the crowd of 100+ was never bored.
I’ve posted my pictures to PicasaWeb.
I had a great time (I was the the click-bot driving the slides, trying to watch a stopwatch while paying attention to the talks) and look forward to the next one, whenever and however that happens.
The is now a RedMine setup for Rake, FlexMock and Builder.
As part of an effort to get better control of changes to the my open source projects, I’ve setup a RedMine issue tracking site for Rake, FlexMock and Builder. You can find it at http://onestepback.org/redmine.
Google Calendar CalDAV support - instructions for setting up Google Calendar accounts with iCal. Makes Google Calendar a lot more useful to me. Conversely, CalDAV accounts don't appear to sync with MobileMe. Bummer.
I am changing host for the One Step Back blog.
This is just a quick little post to let you know that the One Step Back blog is moving. In fact, it has already moved. But don’t worry, we aren’t going far.
Originally this blog was hosted on a shared co-op system run by N2Net. It was dirt cheap and easy to maintain. The down side was that support was sporadic. As the hardware has aged, the Co-op has decided to let the current system run until the hardware dies, and then disolve the co-op.
Today there are tons more hosting opportunities available than there were when the co-op was first formed. I’m now leasing a Linode node and running the blog and other associated software from there. Its almost as inexpensive and the co-op and uptime should be better.
Write now the blog has been moved. As time passes I’ll move the article archive as well. Let me know if anything looks amiss.
— Jim Weirich
I'm a fan of TaskPaper, the todo-list app that makes sense and doesn't throw huge amounts of UI at me. Ergo, I'm pleased to see a Ruby library for syncing your TaskPaper documents to what will soon become the web version of TaskPaper. Rawesome.
[Robert C.] Martin criticised both Scrum and XP for becoming “too meta”. Scrum was criticised for unrealistically expecting everything to be ideal and for promoting certifications as a way to confirm someone’s professionalism. On the other hand, XP was criticised for being too strict. As an interesting demonstration, he asked everyone in the audience to raise their hands and then started listing original XP practices, asking people that do not use a particular practice to put their hands down. My estimate is that there were about one and a half thousand attendees, but only a few hands remained raised after the fifth or sixth practice being listed. When he asked who in the audience has unit test coverage larger than 90%, most people simply laughed.
(Emphasis mine)
From The fifth element of the Agile Manifesto
Interesting; this was at the Agile 2008 conference, so one might expect higher-than-average adoption of Agile practices.
Not sure what this means. Flaws in Agile methodology? Lack of will power? Unrealistic expectations? Some Agile is still better than no Agile?
Last week I interviewed the author of The Ruby Programming Langauge, David Flanagan. We posted the first part of it today - Five Questions with David Flanagan, Part 1. The second part will go up next week. Enjoy!
In the past three decades, Chicago has undergone changes that are routinely described as gentrification, but are in fact more complicated and more profound than the process that term suggests. A better description would be “demographic inversion.” Chicago is gradually coming to resemble a traditional European city — Vienna or Paris in the nineteenth century, or, for that matter, Paris today. The poor and the newcomers are living on the outskirts. The people who live near the center — some of them black or Hispanic but most of them white — are those who can afford to do so.
A fascinating read for those who like to think about how our cities evolve.
Refactor my code is a neat site where you can post your code and watch others refactor it. I saw an interesting bit of code whiz past and thought I'd take a crack at it.
Removing conditionals from code is one of the little games I sometimes play while coding. Here, I've extracted the logic of the conditional into another class. The resulting class is much more code than the original. So why do that?
Well, I say you get a few benefits:
While I delight in deleting code and writing as little as possible, refactoring this to more code seems the right way. What say you?
Its retro, its cool. It'll come in handy when I need slides on the sameness of code and data in good programming languages.

Via Square America.
beyond rest - if publishing data in realtime, XMPP, Comet and scaling HTTP services pique your interest, this thread is an excellent read. Lots of smart people disagreeing here.
Please to enjoy, Grieg's Piano Concerto in A minor. Brought to you by Artur Rubinstein and the London Symphony.
The rest of the first movement, the second movement and third movement, also for your enjoyment.
Watching Thor at his agility classes is really interesting. It's fun to see the dogs constantly looking up to their person to see what jump or obstacle to go to next. Of course, the class is half dog training and half people training.
I've noticed a distinct change in Thor's obediance since he started taking the classes. He's more receptive to good boy/bad boy commands now. And, of course, he'll do anything for food!
Here's some video I took of Courtney and Thor doing their agility thing.
One thing that seems often to come up in discussion of OO development is the size and number of your methods. I’m a fan of having small methods with matter-of-fact names, even if it means my class may seem to have “too many” of them.
Of course, “too many” is a fluffy concept. How many methods are enough? How many are too many? Abe Lincoln was once asked how long a man’s legs should be; “Long enough to reach the ground” was his answer. I’d argue that the right number of methods for your class is that amount needed for the class to get its job done.
That’s still not a satisfactory answer; one can inline code and drop methods, and the class will still work. But that comes at a cost; methods then tend to get larger, harder to read, and less cohesive.
A plausible approach is that if you think your class has too many methods, maybe your class is doing too much, and you need to refactor to more classes. Seems, though, that people resistant to a plethora of methods also abhor “too many” classes, and the reasoning in each case is roughly parallel.
In looking around for some opinions on this, I came across this remarkable ruby-talk thread from 2002: Small Methods – a ramble
(Side note: such threads are now extremely few and far between on ruby-talk. Reasons and consequences of that are a topic for another day.)
What’s interesting is that much of the argument for or against having many small methods is based on tools. Smalltalkers, using their code browser, found it easy to navigate among method implementation; those against the many-methods approach seem to find themselves manually scrolling through text files, and argue this is disruptive and tedious. This is fairly specious, given what any decent code editor can do, (Vim users: go check out rtags if you are not already using it. I imagine TextMate can do the same thing.)
In reading through the thread I found myself nodding along with Mike Thomas (msg #31114 ; “In my opinion, the editor is no ‘excuse’ for not factoring code properly.”) and Albert Wagner (#31115, “it is an attempt to reduce the visual complexity, so as to be able to grasp quickly what is going on in a method; i.e. , condense a snippet that is not duplicated anywhere else into a sort of language shorthand.”) And I like the “Watership Down” syndrome idea.
Naturally, one could argue that having large numbers of methods and classes just gives you more, not less, to track . Except you aren’t going to be storing all those methods in your head; a big win for OO design is that you don’t have to keep everything in your brain, you need to track a limited scope at some particular level of abstraction or detail. One should be able to get a clear, reliable high-level view of an app by looking at the high-level code; when you need detail, you jump to where this or that is implemented.
It isn’t until message #31214 that testing is mentioned. This is from 2002, before TDD and BDD really took hold in Rubyland. Smaller methods seem naturally to come from TDD. Or, conversely, if you have large, busy, methods they are almost certainly hard to test, or test correctly.
Interestingly, Brian Marick, who knows better than most about testing, comes out in favor of (somewhat) larger methods (#31170). His reasons are quite interesting, following earlier observations on communication, expressing intent, and how different tools influence thought. (And now I really want to know more about Stanley Fish’s “affective stylistics”.)
David A. Black follows with this observation:
Clarity is such a vexed thing. I believe people who say that they find Perl code clear. (I used to find it reasonably clear – I’m a little out of the loop right now :-) I also believe people who say they find it opaque, and I believe those people when they say they find code in some other language clear. (Which is to say, if a non-programmer said Perl was opaque, that wouldn’t “count” in the same way.) Clarity is annoyingly relative; it seems that what you find clear is what you’ve learned to find clear, and/or perhaps are cognitively predisposed to find clear.
I’m curious as to what others do, what heuristics Rubyists (or not) have for determining method size, number of methods, size and number of classes, and so on. What are some good resources for this?
What’s the method for clarity?
httparty looks really cool. It's a little library for making writing tiny REST clients easier. From the examples (edited for length):
Great job, John!
You'll have to pardon me for linking to Ted Leung twice in short order, but the man is good peoples. This time I'd like to draw your attention to his presentation from OSCON on Open Source Community Antipatterns.
Ted's talk is full of great observations from his time at OSAF and his ongoing work with the Apache project. Keep in mind that the presentation is on anti-patterns, so most of the slides describe what you don't want to do.
IDEâ??s and Dynamic Languages. Ted Leung's got some useful and insightful things to say about dynamic languages, history, IDEs and the people who use them. While I still think many of the features in a modern IDE are crutches, I hope that what Ted is alluding to becomes a reality.
Since I've become so familiar with my shots drifting off to the right, I figured I'd finally figure out the correct term for these sorts of shots. Thusly, an illustration to teach myself:

Handsome penance, isn't it?
Why Analytical Applications Fail. Ostensibly, this article is about analytics applications that expect users to know exactly what they want before they start. But to me, the underlying story is of developers who get caught up in their domain and build an application for themselves instead of for their users.
We've all fallen into this trap. Whenever a new person joins my team, I always try not to squander their beginner's mind. Fresh team members can often point out places where the interaction design or domain model need to soften up for those who haven't lived in the project for months. That said, it requires patience and humility on the part of the existing team.
Introducing Functor - another library for implementing multiple dispatch/pattern matching in Ruby. This is a great example of what I talked about at OSCON: stealing ideas and applying them to your daily work. I'm particularly impressed with how Dan has applied it to something that isn't a recursive mathematical function - check out the example of using in a view class.
I keep getting a flow of positive feedback about the presentation I delivered at Startup School in the Spring. Since it was never linked up here, I thought I'd made sure it made it into the archives: The secret to making money online.
There’s this reFresh
but there’s also this reFRESH
The latter is apparently celebrating their 50th anniversary. Perhaps the “creatives” should try a little harder to find a more creative name.
The deadline looms for submitting proposal for an Ignite Phoenix presentation.
I confess I’ve not yet submitted mine. Party that’s because I’m in NYC more preoccupied with my friends and family than the usual geekitude, but also because I want to be sure I pick something I can cover in a crisp, informative, entertaining manner.
I have some ideas, and one in particular that is leading the pack, but I thought perhaps I should do some crowdstorming (or maybe it’s braincrowding or outbraining or socialcrowding or …) and ask whomever may be reading this:
Note that the talk needs to be short, as in ~5 minutes.
Wednesday, July 23, 2008
Social stuff: 6:15pm
Presentations: 7:00pm
Boulders on Broadway
530 W Broadway Road
Tempe, AZ 85282
Google map: http://rubyurl.com/SKAU
See http://www.refactorphoenix.com for details
This months general topic:
Find out how technology like Amazon EC2, Django, and Ruby On Rails are pushing the performance of semantic link relevance past basic popularity ranking.
Paul Kenjora will explain how the Arkayne.com widget is leveraging these technologies to deliver a 2% – 80% click-through on suggested links for blog posts.
It’s going to change the way bloggers promote articles and its all getting started right here in Phoenix.
Refactor Phoenix is a monthly non-denominational gathering of desert geeks, dedicated to the open exchange of information in a casual environment.
We meet on the 4th Wednesday of each month.
If you’re a (coder|programmer|software engineer|hacker|developer), Refactor Phoenix is for you.
For more information, please see
http://www.refactorphoenix.com
or contact me at
james@happycamperstudios.com
(602) 714-1148
class User < ActiveRecord::Base validates_presence_of :login, :message => 'Please enter a login.' validates_uniqueness_of :login, :case_sensitive => false validates_format_of :login, :with => /\A\w*\Z/ validates_length_of :login, :within => 4..15 endSo, we wrote validates_with_block, a Rails plugin that allows you to write a more readable set of validations for one model.
class User < ActiveRecord::Base
validates_login do |login|
login.present :message => 'Please enter a login.'
login.unique :case_sensitive => false
login.formatted :with => /\A\w*\Z/
login.length :within => 4..15
end
end
These methods just call the same old validates_* methods; they don't do anything interesting with ActiveRecord beyond that. It's just for keeping things readable, but sometimes readability takes a little extra work.Scott McConnell, editor of The American Conservative, in “High Noon for the Republican Party”, Harper’s Magazine:
If the next president orders the military to invade or bomb Iran or some other country, I would probably welcome it if some key generals said, “No Mr. (or Madam) President, not this time,” and went over the head of the president for congressional and popular support. At this point I’d put as much trust in the judgment and patriotism of a high-ranking military officer as in that of a politician who has spent decades catering to the fabulously rich men who finance both major parties.
The $451.24 Denon AKDL1 Dedicated Link Cable
Right up there with the BiC Kugelschreiber Cristal Kugelschreiber Cristal schwarz review
Sam Anderson of New York Magazine, writing on Barack Obama as rhetorician:
The signature project of his candidacy—before health care or housing or Iraq—seems to be the reuniting of presidential discourse with actual, visible thought. It is not a trivial achievement. ... If you can think your way through a sentence, through the algorithms involved in condensing information verbally and pitching it to an audience, through the complexities of animating historical details into narrative, then you can think your way through a policy paper, or a diplomatic discussion, or a 3 A.M. phone call. Bush's difficulty with basic units of syntax has not been trivial: It signals a wider habit of mind that has extended to every corner of governance. Hillary's tendency to express herself in distant clichés very likely lost her the nomination—and, one might argue, rightfully so. Style tells us, in a second, what substance couldn't tell us in a year. It's silly to downplay the importance of verbal intelligence to a job that makes you the mouthpiece of arguably the most influential nation in the world. As Ezra Pound once wrote, “The mot juste is of public utility … We are governed by words, the laws are graven in words, and literature is the sole means of keeping these words living and accurate.”
Next Thursday, July 10, there will be the first Web Design & Development Meetup, at the Coffee Bean & Tea Leaf (16211 N Scottsdale Rd, Scottsdale, AZ 85254. That’s a block south of FLW.)
This might be especially interesting for those Refresher who liked the original Scottsdale location.
Plus, unlike Refresh, this gathering may actually focus on Web design and development instead of Web marketing, branding, and networking. (The latter are still all useful topics, just not the things I had hoped would be core to Refresh when I, with several others, got it rolling.)
I’ve noticed an increase in the use of folks adding a leading ’@’ character to user names (and even real names) in threaded discussion boards, mailing lists, and E-mail.
I don’t think any of the uses I’ve seen were meant to aid any sort of automated text processing; it appears to be a bad habit that perhaps makes sense on Twitter, but is merely line noise elsewhere.
“Hey, you got your hipster-nerd meme in my security hysteria!”
“No, you got your security hysteria in my hipster-nerd meme!”
School locked down after ‘ninja’ sighted in woods
(via Schneier)
~/.bash_profile.
This one iterates through the one or more directories and creates aliases to the subdirectories so I don't have to. Here's the scenario: I've got a directory ~/work/ where I keep work projects, a ~/writings/ where I keep all the writing projects and so on. I used to have aliases to each subdirectory. e.g. alias project1="cd /Users/muness/work/project1". With shame, I admit that I maintained each of these manually. No more!
Install instructions:
curl http://github.com/relevance/etc/tree/master%2Fbash%2Fproject_aliases.sh?raw=true?raw=true > ~/.project_aliases.sh
echo "source ~/. project_aliases.sh" >> ~/.bash_profile
Usage instructions:
~/work.source ~/. project_aliases.sh add PROJECT_PARENT_DIRS[0]="$HOME/work".
You may be interested in my blog post over at PragMactic OS-Xer where I describe my motivation for these recent shell scripts.
Wednesday’s Refactor was great. I want to thank Ray Niemeir and Brian Shaler for their terrific presentations.
Ray’s talk was filled with special insights; I was really struck by his observations on bubbles, and looking for The Fizz.
Brian did a great job explaining how to work with CS3 and AIR, and there was a ton of useful info on getting rolling, and especially with using a local database. Check out the code for the talk here.
At the end of the meeting we did another round of Lean Introductions, and this time the tag was to offer up a current trend and a topic for future Refactor.
Here’s what came up (trends and topics mixed together):
Mike Wolfson has offered to give a talk on mobile computing; that’s slated for August. Thanks, Mike!
If you have something you can give a talk or demo on, please step up. It needn’t be long; 10-15 minutes works fine. It needn’t be formal; a walk through of a project or some code would be great.
And be sure to keep the last Wednesday of each month free to catch the Valley’s tech talent sharing their insights and know-how.
Unfortunately for Microsoft, this is a headline from a genuine newspaper site, and not from The Onion:
“Man gets Windows Vista to work with printer”
(Thanks to Albert for the pointer.)
The pessimist in me has qualms with the way in which gay marriage is becoming legalized piecemeal in this country. I worry that having a California court legalize gay marriage instead of having it voted on by the citizens of the state is going to cause a lot of trouble in the long-term. I wonder how this will affect the Presidential election, and if it’s no surprise that Obama won’t (or can’t) come out pro-gay-marriage, then it’s nothing to be happy about either. And I find William Saletan’s arguments that gay marriage will pave the way for polygamy and adult incest fairly convincing, too.
But that’s the nitpicking, and now is probably not the time for that. Better to gaze happily on a couple like Shelly Bailes and Ellen Pontac—together for 34 years, and only just married this Monday.
I love pictures like this. When you turn away from the cartoonish depictions of queer life on TV and in movies, of bulletproof drag queens and untouchable lipstick lesbians, you see that gays and lesbians are as boring and pedestrian as everyone else. And that’s why they deserve the right of marriage: not because they’re perfect, but because they’re not. Because their lives will bear as much disappointment and malaise as those of anyone else, and having a devoted mate, straight or otherwise, can help sweeten even the worst of moments.
Best wishes, Shelly and Ellen. Today California, tomorrow the country?
Last week I figured out a way to make my life a little bit easier by abstracting the scm I was using and having the prompt indicate whether I was in a Subversion or Git. Thanks to Mike Hommey whose script I tweaked for my needs.
For a long time, I've wanted my iTerm tab title to be more useful. I started by having it display the last process I executed in that tab (this also shows the full path in iTerm's window title bar):
PS1='\[\e]2;\h::\]${PWD/$HOME/~}\[\a\]\[\e]1;\]$(history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g")\a\]\$ '
Next up I wanted to show the currently running command. Google showed me how:
trap 'echo -e "\e]1;$BASH_COMMAND\007\c"' DEBUG
Instead of trying to explain this code I'll quote the Bash man page:
BASH_COMMAND
The command currently being executed or about to be executed, unless the shell is executing a command as the result of a trap, in which case it is the command executing at the time of the trap.
Some more tweaks followed:
[ls] and >vi<).
- Show the context of the executing command in the tab. This is just the repository where I executed the command.
- Make this coexist with TextMate.
And a screenshot to summarize:
The code is in github/relevance/etc/tree/master/bash/bash_vcs.sh.
Install instructions:
$ curl http://github.com/relevance/etc/tree/master%2Fbash%2Fbash_vcs.sh?raw=true > ~/.bash_dont_think.sh
$ echo "source ~/.bash_dont_think.sh" >> ~/.bash_profile
Enjoy! Tested with iTerm on Leopard.
In 2006, I stumbled across a YouTube video of Stevie Wonder playing “Superstition” on Sesame Street. It’s a sprawling, searing funk performance of the hit single, more insistent and grotty than the original recording on Talking Book. It’s funny to think of how you can get introduced to a musician: I first became aware of Stevie Wonder in the 1980s when he lapsed into easy-listening ditties like “I Just Called to Say I Love You”. It took me more than a decade to dig back into the history and understand his contribution to pop music. I can’t remember having watched this on Sesame Street when I was young, but if I did, I was obviously too young for it to take.
Anyway, I watched the clip once or twice, bookmarked it in my del.icio.us account, then went on my way. A few weeks ago, I was reminded of it, looked it up on del.icio.us, and followed the link—only to find that the video had been taken down.
No big deal: Videos get taken down all the time. But it made me think a little more about “linkrot”, as we call it in the web business. We’ve been making web pages for more than a decade now. A lot of those pages are still around, and their links don’t go anywhere anymore. What can be done about it?
In 1998, Jakob Nielsen wrote an article on linkrot that makes for interesting reading today. He makes two recommendations: First, that webmasters maintain their sites so inbound links remain valid, and second, that webmasters check their outbound links and correct them if necessary. The first, I’d say, remains valid, since you presumably own the content on your own site and should always be able to ensure that inward links to that content are working. But the advice about outbound links is quixotic at best, since an active blogger can easily churn out hundreds of outbound links a year. It’s not every blogger’s job to become a random monitoring service for the entire web.
This isn’t really a criticism of Nielsen so much as a sign of how quickly things have changed. In 1998, the vast majority of people who were reading Nielsen were people who were putting content on the web as part of their jobs, whether those jobs were at an online zine or a Fortune 500 company’s investor relations site.
But as has become a truism these days, web media is amateur media, and people now create new content quickly, and then just as quickly they leave it behind. They try out Blogger accounts for a month and then get bored. Or they decide Facebook is cooler than MySpace, so they leave behind an orphan profile, with “friendships” that grow stale and unmaintained.
Anyway, the Stevie Wonder video I bookmarked was this:
http://www.youtube.com/watch?v=dSC29xl6hno
... but maybe I should’ve just bookmarked this:
http://www.youtube.com/results? search_query=stevie+wonder+superstition+sesame+street&search_type=
... which, of course, isn’t one specific video record, it’s a search page. This is less convenient for whoever follows that link, of course: You have to click at least twice to get to a video that can be watched. But it’s more resilient. An individual video can be taken down, but YouTube will probably always have the same video up at a different location.
Such an approach rankles my inner perfectionist, since this screws with the tidy notion that a URI will describe one discrete thing in the world, for some sensible definition of “thing”. Different URIs reduce the sharing aspects of del.icio.us, and make it harder to do a Google Blog Search to see who else is blogging about this video. And two different video records of the same Stevie Wonder performance will have different comments, ratings, and video responses.
But do such things really matter anyway? I almost never read YouTube comments, because all they do is make me depressed about society. And who cares if two different URIs can be used to watch the same video? Whoever followed the link got to watch the video, which is what matters.
In the long term, this approach would rely on YouTube to stay in business for a while, which is likely—but also you’d have to hope that YouTube never changes the URI or arguments of its search page. That’s less likely, because who ever links to a YouTube search page?
In the more general case, it’s hard to imagine doing this in a way that will truly stand the test of time. Say your friend writes something funny about “Iron Man” on her blog and you link to it with a search … are you going to assume she’s going to keep that domain up forever? And what search terms are you going to use to uniquely link to that entry, and only that entry?
Linking strategies notwithstanding, I wonder about the word “rot”, which carries a negative connotation in general usage that doesn’t correspond with what we know about how ecosystems work. When a bird dies and falls to the forest floor, it doesn’t go to waste—its body is soon covered by scavengers like grubs that feed on rotting flesh, converting one form of biomass to another. This is bad news for the bird, but good news for the forest. Ecosystems don’t waste energy, they just keep it circulating in a panoply of forms.
So, at the risk of overusing a metaphor, we have a web full of linkrot. Can we build anything that can feeds on it? Say, a Firefox plugin that auto-suggests destinations when you follow a broken link? After all, there are countless dead links out there, waiting to be harvested.
I had a chance to pair with Rob today. On his console window, I noticed something I wanted: his bash prompt had an indication that he was in a Git repository along with the branch he was on. Later, after he'd left, I found myself wondering how that worked and that I simply had to have it, and I wasn't willing to wait a whole day to figure out how he'd done it. Patience is not a virtue. (In that spirit, click here for the code if you're too impatient to read the rest of this blog entry which I spent countless hours writing. Uphill both ways. In the snow.)
A few minutes of googling turned up a blog entry with relevant bash fu. The code there was for changing the prompt such that it indicated whether you were using svn, git, svk or Mercurial along with some repository metadata. A couple of minutes later (it took a while to copy and paste the code since it was interweaved with comments), I found out it didn't work on Leopard. readlink turned out to be the culprit. Instead of figuring out why it wasn't working, I replaced it with something simpler (specifically I used: base_dir=`cd $base_dir; pwd`). Viola, things worked: I now had a hella cool prompt that showed me if I was in a Subversion or a Git repository - I never used Mercurial, and left SVK for Git a couple of months ago. Yay.
Being who I am I had to do something more with this new ability to distinguish between Subversion and Git. And I knew exactly which itch to scratch: 90% of the time I used the same scm commands. I even had shell aliases for them so I wouldn't have to type them all out. A few minutes later I'd converted my previously Subversion specific aliases to generic ones that worked with Git too. Photo says it all:
If you want the same, download the script as ~/.bash_vcs and add source ~/.bash_vcs at the end of your ~/.bash_profile.
If a tweet is uttered with no followers, does it make a peep? I'm getting going with Twitter on http://twitter.com/d2h.
We have 24" and 30" pairing stations, an intern, freshly roasted coffee delivered weekly, a fridge stocked with caffeine, more caffeine, beer, and Dave's Insanity sauce. We have cool t-shirts and all manner of radiators up on the walls, whiteboards and the Beta Brite. Music is served by our CI/Music server.
The bookshelves are stocked with reference materials, the occasional bottle of scotch, and recommended readings. On the list of recommended readings we've got The Carpet Makers, The Company, The Omnivore's Dilemma, The Eyre Affair, Behind Closed Doors, Bloodsucking Fiends and The Deadline, Men In Hats, Volume I, Don't Make me Think, The Insane are Running the Asylum.
Our favorite radiator is the Friday radiator. Fridays are special: we don't do billable work. Instead we open source, blog (self reference makes this blog entry extra cool), watch educational movies, play Wii on the projector. Here's today's:
Oh, let's not forget the buckets of mice.
This blog entry inspired by another excellent business card cartoon from Hugh Macleod.
I had a great time on the West coast recently with stops in Santa Barbara and Palo Alto. What always surprises me at events like these is the huge number of people I meet that are doing cool things with Rails that I've never heard of. The kind of people who are just really happy to be using Rails and happy to build businesses with it.
Most of them are not heavily involved with the community in the sense of always being in front of it. They're not the ones constantly commenting on the blogs. They're just enjoying working with the tools. That's a really refreshing sentiment.
It's easy for people to think that the interaction they witness on the web is a complete reflection of the world in general. Often it's quite the contrary. Which is why I so enjoy getting out of the web world and meeting people in the flesh. Hearing their stories, discussing their concerns, and sharing passions.
You can easily end up burning out on web participation because the loud minority twists your perception of what matters and who cares. But there's nothing like meeting people who tell you that working with Rails or listening to a talk or reading something you wrote either touched them, changed them, or made them move in a new direction. That's a big pay-off for getting involved with public sharing.
So thank you so very much to everyone who came up to me at any of the events out in California. It makes it all worth it to hear your stories. Keep on rocking with whatever it is that you're doing. Keep the passion and the optimism alive.
Rob tagged me. So:
muness$ history 1000 | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
102 git
72 ls
63 cd
40 ss
35 rake
24 m
17 up
14 st
12 sc
11 ri
Tag, you're it.
For some reason, doing a Google image search for “inflatable cockroach” doesn’t return many good results. How are our children supposed to learn if they can’t see gigantic artificial versions of repulsive vermin? So, even though this cell-phone photo is a year old, here’s me doing my part in addressing the problem:
Agile Retrospectives (Esther Derby, Diana Larsen) and Project Retrospectives
(Norman L. Kerth) have been a great resource in facilitating - or helping others facilitate - retrospectives. I'll often leaf through them a day or two before a retrospective to remind myself of the framework (more on that in an forthcoming post), and to introduce new activities or create my own.
Something that neither of those books tackle directly is how to facilitate a distributed retrospective. Given that we've been running a few of those lately, I wanted to share some tips: