Saturday, December 30, 2006

(The other solution is a link due to some formatting issues in Blogger.)

What's cool about Pat's solution is that it solves a more general problem. The more general problem is, how do you use auto_complete_for and text_field_with_auto_complete in your controller and views if you're not going directly to an ActiveRecord model? The answer is, the autocomplete methods only require a particular method from ActiveRecord, namely find, and they don't actually require the ActiveRecord version -- just any method named find.

Anyway, going back to the specific functionality, the downside is, it's more code than my original solution, but the upside is, it isolates all the wizardly stuff in a pair of objects that can quite happily live in the /lib directory. This means the controller and view retain the usual helper methods, which make them a lot more maintainable. Unfortunately, as Pat's own blog points out, it doesn't require an expert to use Rails, which means that if you're using expert techniques within Rails, isolating them in the /lib directory is a good idea.

Imagine a world filled with dragons, elves, etc. Putting the wizardly code in /lib is kind of the same thing as making wizards live in towers, instead of smack dab in the middle of downtown. If you've got a bustling city filled with dwarves and orcs arguing about the price of ale, the last thing in the world you want is some irresponsible wizard turning entire city blocks into antimatter during the course of some experiment gone wrong. Perhaps this analogy is a bit of a stretch, but it's the best party weekend of the year and a blizzard has me snowed in. I tried to dig my car out earlier today, I couldn't even figure out where it was, and my driveway is only about ten feet long. Anyway, this post seems to have a bunch of tangents, but long story short, Pat's solution is pretty cool.

The second is James Gray's Higher-Order Ruby, which is based on the Mark-Jason Dominus book Higher-Order Perl, which I love. It's also very directly based, in that a lot of the examples are direct translations from Perl to Ruby. This was very useful to me when I first learned Ruby, since the direct translation has a side effect of illustrating differences and similarities in the two languages. The Ruby in these examples is much more idiomatic.

I revisited Higher-Order Perl recently, and I'm hoping to expand on these techniques in either Perl, Ruby, or even Lisp (I'm using DrScheme on Mac OS X and I love it), in another post in the future.

Friday, December 29, 2006

So a couple days ago I discovered something in Seaside which I thought was the coolest thing ever, and I went into Gmail to post to the Ruby-Talk mailing list to see if it was possible in Ruby as well. But midway through, I thought, wait, this would make a great Ruby Quiz, so I sent it to James Gray (he of Ruby Quiz fame) as a submission. And the challenge was, do this in Ruby.

Unfortunately James was forced to crush my ego with his overwhelmingly superior Ruby-fu, but I imagine he has to do this all the time. He answered the challenge himself and proved it was easy:

This will return a list of all classes active in Ruby -- core language, gems you've loaded, models or controllers or what have you built in Rails, anything which is now part of the object space. Hence the name, ObjectSpace.

Now, obviously, this is way too easy to be a Ruby Quiz. All it tests is your knowledge of the existence of ObjectSpace. However, just for the fun of it, the Seaside component I was originally so ga-ga about, it didn't just do that. In Smalltalk, that's two words: Smalltalk allClasses. (Of course in English it's four words, but whatever.) What had me so stoked about the Seaside version was that it puts this facility in a text field linked to a ScriptaculousAjax.Autocompleter, so you can easily get access to your Smalltalk (and Seaside, etc.) classes just by typing their names, or the closest approximations you happen to remember at any particular moment.

So, how much extra work would it take to supply this kind of functionality in Rails?

Just to contextualize, Seaside is actually an acronym -- something like "Smalltalk Enterprise Application Server Integrated Development Environment." I don't think that's 100% accurate, in fact I think it's way off, but I am pretty sure I got the last three letters right. Developing in Seaside is pretty weird for me, because I'm a vi guy at heart, and Seaside actually turns your web application into an IDE for itself, which takes some getting used to. And this of course is why it has a nifty autocompleter for reflection like that. Because it gives you a context where you'd actually need one.

To supply all this extra functionality in Rails -- to turn Rails into an IDE for itself -- well, I imagine that would take tons of work. It'd certainly take a serious chunk out of my quality time. But this particular slice of functionality? Easy.

First you limp to the side like your legs was brokenShaking and twitching kinda like you've been smokingCrazy wack funkyPeople say, "You look like MC Hammer on crack, Humpty!"

The controller code is easy. Unfortunately, due to some problem within Blogger, and my own laziness in upgrading, posting code samples inline is essentially impossible (except maybe with iframes). I sure hope Blogger is reading this, I was really happy til I tried to paste the code in. I just edited out some seriously irate abuse againt Blogger. I am other than a passionate user at this particular moment.

It's just James' code, plus something in the controller to filter (case-insensitive) according to whatever the user's search parameter was.

Unfortunately, though, the dynamic dropdown is a little more work. You have to do it by hand. If you've worked on this kind of thing before, or if you've read Chad Fowler's book Rails Recipes, you know that Rails has a one-line solution for this sort of thing -- and that the standard Rails one-line solution only works if you're making a dropdown which corresponds to some attribute of every instance of some Rails model. Now we could do it that way, but only if we salted every class name in the database, which would be pretty ridiculous, and also cost us the dynamicity which is the whole point of the exercise.

So we have to resort to a slightly more involved implementation, with (*shudder*) hand-written JavaScript! (Gasp!)

(And yes, if we're resorting to handwritten JavaScript, we might as well use handwritten HTML too.)

"But what about that partial?" you say.

We do indeed need code for the partial, but since it's just rendering the list returned for the dropdown, it's pretty basic.

And there you have it. That's the whole thing. Of course using "klass" rather than "class" is pretty vital, otherwise you're using the built-in Ruby method class and you get all kinds of weird errors. Other than that, though, pretty straight forward.

At this point, all you need to do is fire up Mongrel and view it in a browser. By the way, if you followed my advice and used the Rails 1.2 release candidate, you now have an automated way to familiarize yourself with the new classes in that code base. Pretty cool, right? Fun toy. Are you wondering where in that code base the new ActiveResource stuff lives? Just type in "resource" and see what comes back. Wanna see what's new in ActiveSupport? Pretty easy to do.

So, although this isn't the vitally useful technology in Rails that it is in Seaside, it's still a very fun little widget.

Thursday, December 28, 2006

Last year I was obsessed with artificial intelligence, especially Bayesian techniques. I was unemployed, although, I spend so much time deliberately unemployed studying things I want to study that calling myself unemployed is kind of a disservice to anybody unemployed who actually wants a job -- I mean techincally I'm unemployed now -- anyway, long story short, I was spending pretty much all day every day reading, building toy robots, and and googling Bayesian networks, Lisp, and other stuff I was curious about.

I ended up posting (and then taking down) some extremely aggravated rants against Google, because if you want to live a life free from Google ads for Google jobs, let me tell you, the way to live life free of that particular annoyance is not to google Lisp or Bayesian networks. Initially it wasn't even an annoyance, but after a while, it got very irritating -- the more so because the taglines were so marketing-y and so not cool at all. Reading between the lines, I had to wonder if their HR departmant was desperate and willing to hire anybody just to meet their numbers.

(I can prove for a fact that they weren't, because they didn't hire me, although, in my defense, I sent them a resume which was practically drawn in crayon -- it had cutesy little captions as annoying as Google's campus -- and came in an e-mail explaining that I didn't actually want to work for them, I was just submitting to their brainwashing. This was not exactly my slickest sales pitch ever.)

Anyway, also, ever since I got stranded in the job market when nobody wanted to hire Perl wizards any more, I've done periodic research on which languages return the most job results on various job sites. (This isn't necessarily the most valuable metric, but it's worth being aware of.) At that particular time, you couldn't google Python on many of those sites without seeing numerous ads which came from cheesy headhunters but were obviously for contracts at Google. You'd see things like "a leader in the search space located in Mountain View near Sandshore Amphitheatre!" every day. Actually I may be getting my landmarks wrong, I don't live in the Bay any more, but you get the idea -- that kind of specificity, that kind of subtlety, for a Python contract lasting six months to a year. (Which, I imagine, is probably a pretty useful way for a manager to pick up a long-term hire if they want to circumvent a picky, rigorous, and therefore time-consuming hiring process.)

It kind of irritated me, the idea that this company once famous for its absurdly high standards was now running ads with the tagline "we can't hire smart people fast enough!" It should be pretty obvious what the choices you face in that situation are: you either slow down, or start hiring idiots. If you have two goals, and you can only reach one, you will have to choose one goal or the other. And after I went to Google for a Python users' group meeting, I developed a pretty cynical suspicion about the choice they'd made. After all, they had Legos decorating the area with the users' group meeting -- but the Legos were Harry Potter Legos, built according to the instructions. It's true, geeks like Legos, but no self-respecting geek buys Legos to follow the instructions. Maybe with Mindstorms kits, or Technics kits, but not with Harry Potter kits. Most Lego geeks wouldn't bother with a Harry Potter kit in the first place. I have the overwhelming suspicion that somebody told somebody else, "Geeks like Legos, take the gold card and go to Toys R Us!" without ever taking the time to wonder which Legos geeks like, or why.

[Google] employees seem a little less excited about things than the last time I was there. Nobody says "We're on a mission to change the world!" anymore. Now they say, "Yeah, I'm just going to stick around here another six months until my options vest." and "I kind of want to transfer out of my group but I worry that all the other groups are worse."

Like I say, there's a real downside any time you get to say "I told you so." It's so much better to be wrong about cynical ideas, or to simply never see anything that makes you cynical in the first place. But I knew it, and although I've taken it down, at the time, I posted it. For what that's worth.

Wednesday, December 27, 2006

It's my presentation from Albuquerque Barcamp, in November, and it starts off with twenty minutes of me summarizing the basic idea, and talking with local Web marketing maven Reid Givens about my career, his career, Object#to_json, marketing, banks in Canada, and the weather in Española. I also sing the James Bond theme song for some insane reason, and talk a lot about how cool I think I am, which is pretty embarassing to listen to, so I'd advise skipping that part.

The topic of the presentation is basically "Ajax + Flash + Rails = MVC3?" -- as in, "MVC Cubed?" -- the fundamental question being, is the standard MVC implementation in Rails sufficient for very complex Ajax applications? This comes out of working on an app which was fairly involved, and which seemed complicated enough to justify MVC not just in the Rails sense, the Web app sense so popular today, but also in the original GUI sense. MVC was invented along with Smalltalk at Xerox Parc, and it wasn't invented to handle Web apps, it was invented to structure GUIs. So I have this Rails app with a built-in MVC system, with an Ajax front end complex enough to justify MVC for its GUI, and a Flash component complicated enough to justify MVC as well. So, the question is, how do you deal with that? Do you need three different MVC implementations? How could that possibly be DRY?

The funny thing is, it was a much less technical audience than I expected it to be, but people pretty much understood everything I was saying as far as I could tell. So there's a little bit of explaining what MVC is, but hopefully it's still interesting anyway.

So, anyway, hope you check out the podcast, and if you do, hope you like it.

Early this year, Caterina Fake said the startup environment in the Bay Area was giving her the same "sharks in the water" feeling she got in 1998. A lot of really bad ideas blew up during that time, and when the bust arrived, there were some really cool ideas that went down with the bad ones -- Pets.com and all the rest of the stuff that deserved to go. Reid Givens, a web guy in Albuquerque, told me he likes to say the bust flushed the system, got rid of all the crap, but the truth is, it just got rid of everything, the good and the bad. Popular Power was a pretty cool concept.

Recently I had a pretty interesting experience with startups. I talked to a startup looking for Rails programmers. This is startup number one; they're in the Bay Area, so we'll call them San Francisco. I talked to the tech guy there, and after talking to him, I wasn't really that interested. Then I talked to the exec guy, and he got me interested. I did a ton of research about the names he dropped, and I decided they might be onto something. So they scheduled a flight for me to go to the Bay Area and meet with them. So I told this other company I was consulting for, I told them, look, these guys in the Bay, they might want me to start like instantly, they're in this startup hurry hurry mentality, you might need to start looking, and this other company, they were in Los Angeles, they said, well, fly out to meet us as well. Because we might want to fight to keep you. So that was the plan.

(This second company, this isn't the other startup, but it leads to the other startup.)

Anyway, then I talked to the tech guy again, at the first startup, San Francisco, and he said some things about my code which I emphatically disagreed with, and I decided I wasn't interested as much after all, and the flight was cancelled. But I was still scheduled to go to LA, so I talked with the company I was consulting for, and we went through with that trip anyway. And the company I was consulting for, it was basically run by one guy, and this guy had a friend who was having a very interesting experience.

His friend had a small company, startup number two, which we'll call Los Angeles. Los Angeles had built a web app in the Getting Real style, part-time, on the side, only a few people, working cheaply, quickly, and cleanly, without a ton of features, just a few features done exactly right, and he had a ton of interested prospective buyers, and some of them were talking about a lot of money.

So San Francisco, they have connections; they're hooked into the VC world. They have a successful repeat entrepreneur coming on as co-founder and they have kickass backers. (Yes, coming on as co-founder. Little cognitive dissonance for you?) And they told me, they kind of feel that any company that makes less than $100 million is kind of a failure.

So Los Angeles is selling for less than $100 million, but several multiples of what they spent to build the thing. This startup built on the side and being sold for a lot of money, that's a new thing. That's like a 37 Signals thing, a smart thing that survives the hard times and makes hella money in the good times. San Francisco, whose goal is to make tons and tons of money and then sell the company to somebody, all without any expectation of actually charging anybody for anything, this seems like something I've seen before, and the last time I saw this, it didn't go so well. In fact it went pretty badly, and in retrospect, everybody involved looked pretty stupid.

So you've got San Francisco, on a mission to make $100 million, and you've got Los Angeles, actually making money, but less than $100 million. Of course the question is how much less, and I can't say, but it's not so much less that anybody's crying for the Los Angeles guys and their terrible loss. Oh no, quite the opposite. The guy from Los Angeles I was talking to, I think he was incredibly cool not to be wearing a shit-eating grin all day long.

I think what's going on here is that the venture capital system is based around the idea that companies require substantial investment to get going. But that isn't true any more. (Huge hour-long mp3 behind the link, absolutely worth it.) Infrastructure means open source software and bandwidth. Bandwidth is cheap, and open source is free.

Every venture capitalist wants that huge success, the big disruptive innovation that destroys old industries and makes them millions.

The irony is, the biggest disruptive innovation that ever came from the Internet could in fact be open source software, and the old industry it destroys will probably be venture capital.

Think about it. Free software and cheap infrastructure basically eliminates the whole raison d'etre for venture capitalists. Companies are cheap to start. All the stuff you used to need millions for is now free. That means venture capitalists just don't matter any more. It isn't about being lucky enough to get $5 million in funding; it's about starting something with the cash in your pocket. If you make something and it's good enough, the guys with $5 million in funding will come to you, because those guys are basically just money in search of intelligence, and it's a lot better to be intelligence in search of money. If you're intelligence in search of money, you'll choose the best way to get money. The best way to get money isn't to find some VCs to beg, borrow, or steal from; the best way to get money is to make something people will pay for. So if you're intelligence in search of money, you'll make stuff people want to pay for, and you won't even bother with the VCs, because they need you more than you need them.

Raganwald has a pretty kickass post about this very subject, and his conclusion is that nine out of ten times, you don't want to work for a startup. 37 Signals has a great fucking book about how VC funding for startups is stupid and the Los Angeles model is smart.

And me? Today, I'm going to send out resumes to a bunch of startups.

Good question.

Let me explain.

There's an important piece of the picture which both Raganwald and 37 Signals are missing.

You can glimpse it here. It's a case study of the Flickr acquisition, and it concludes:

So what was Yahoo’s motivation to acquire Flickr? Flickr was acquired into the Yahoo search group, thus indicating Yahoo’s intention to integrate Flickr photos into the general image search engine. It’s interesting that the acquisition was not initiated by the Yahoo Photos group, thus revenue, revenue growth, and profit were not the main motivations for the acquisition. Secondly, Flickr had developed a robust tagging platform that could be applied to other Yahoo products. Third, Yahoo was interested in acquiring the people behind Flickr and absorbing their thinking and DNA into the company. The least important factor in the acquisition was the user community that Yahoo acquired. While Flickr’s growth and buzz were important in validating the technologies that Flickr pioneered, the sheer number of Flickr users was not an important factor in the acquisition. Thus, at its heart, the Flickr acquisition should be thought of as a technology and people acquisition.

If you're really productive, why not make employers pay market rate for you? Why go work as an ordinary employee for a big company, when you could start a startup and make them buy it to get you?

When most people hear the word "startup," they think of the famous ones that have gone public. But most startups that succeed do it by getting bought. And usually the acquirer doesn't just want the technology, but the people who created it as well.

Often big companies buy startups before they're profitable. Obviously in such cases they're not after revenues. What they want is the development team and the software they've built so far. When a startup gets bought for 2 or 3 million six months in, it's really more of a hiring bonus than an acquisition.

What a lot of people don't realize about startups is that Silicon Valley creates such a huge number of startups not just because of the casino factor -- the "maybe this time we'll get lucky factor" -- but also because it's a fantastic recruiting system. Compare it to sorting resumes, for instance. No resume I've ever seen in my life records the number of hours worked in an average week, or contrasts average weeks with unusual weeks, let alone providing the standard deviation, but if you see startups on the resume, you know you're dealing with somebody who will work hard. The smaller the company when they joined it, and the larger the company got, the more likely they have some capacity for leadership -- and that's true irrespective of their title at the company, and irrespective of what their resume says they did there. The more unusual the problem their startup addressed, the more likely they have the capacity to solve challenging problems in original ways. These are all good things, and that's just if the startup fails, because you wouldn't be looking at a resume if it succeeded.

If it really works out, and the company gets bought, huge companies with gigantic money-making machines that need smart people behind the wheel suddenly have very smart people behind that wheel.

So I've been mostly working for startups for the past six months. This is a new strategy in my career, but I have faith in it. Part of the reason I work for startups is, it makes me look good. It also keeps my brain healthy by putting interesting challenges in front of it. But a more important reason is the people.

If you're working with somebody at a startup, you know that they think it's possible they might be one of the best in their field, and they're willing to work very hard to prove it (or to find out otherwise). You also know that they're working sufficiently hard that they will absolutely demand your best, and boot you if you provide anything less. A lot of people might consider that high-pressure, and it is, but high pressure is often a result of high standards, and high standards are a very good thing.

Obviously what I'm talking about doesn't have much to do with the type of entreprenuers Caterina mentions in her post, the ones she sees in pictures from literally every Valley party. It doesn't have a lot to do with every single startup I've worked for or had friends at. There's no doubt the world of startups contains more than its fair share of bullshit. Every startup I've talked to, I've asked a lot of questions of, and some of them, the answers were so stupid I felt sorry for them. Confidence does not always come from experience or insight. But that's why you ask the right questions. It's called due diligence.

But the final reason I'm going to send resumes to startups?

Have you ever seen a tiger, in person?

If you haven't, you should hurry up, because they are much closer to being extinct than anybody who is reasonably safe from being eaten by one would ever wish. They are much, much closer to being extinct than many people even realize. These are beautiful, magnificent creatures, and one day, they may be gone.

This creates an Ajax autocompleter with Scriptaculous and Prototype which gets automatically populated with all Smalltalk classes matching whatever you've typed.

Is that cool or what?

I'm not sure if Smalltalk allClasses evaluates to a list of all classes within Smalltalk, or all classes within your Smalltalk image -- in which case, it would include everything from Seaside and Magritte as well -- but either way, wow.

(Update: it does include Seaside, and anything else in the image. Nice.)

By the way, I don't know if I've said this before, but SqueakMap puts RubyGems to shame. Imagine RubyGems with Google built in. (Or at least a searchable RDoc.) That's SqueakMap. Even simpler install, built-in search and documentation. Madness.

One more interesting Smalltalk tidbit. I looked into Objective-C on a whim, which is the language used for developing Mac OS X apps, and it's C with Smalltalk blended in. (It seems like a weird combination, but it's good to know.)

Tuesday, December 26, 2006

Microsoft entered the browser market with the explicit goal of driving Netscape out of business. They realized that if what Netscape made was good enough, people could host their applications over the network, instead of running them on the desktop, and it would matter much, much less to have a virtual monopoly on operating systems. What good is owning the desktop if every application sits on the network?

So of course the browser wars happened. And I have long ago lost the link, but I saw it, it was an actual quote from Microsoft management, their goal was to destroy the market, so nobody could ever make money selling a browser. (Such a business goal, by the way, is explicitly prohibited by antitrust law, but, you know, like Microsoft cares.)

We all know how Microsoft did it. The relentless arms race of features. Netscape took the bait every time, giving us browsers that were just as bloated, that had just as many idiotic features we didn't need. So it stopped being about changing the world, and instead it became about who could ship bloatware faster. Microsoft tricked Netscape into playing their game, and guess who wins when you do that.

Microsoft saw the future coming, thought, "no way! fuck that!" and then went ahead and in their efforts to prevent it from ever happening created the very future they feared.

This means, by Microsoft's own logic, that Microsoft is going to be what killed Microsoft.

If only we could believe it was hirikiri. If only! Then we could give them some credit. We could say, "they looked in the mirror, they saw a monster, and they did the right thing." But no. It wasn't intentional.

They were just that stupid.

I know they have some of the best engineers in the world. Allegedly. I know even God wishes he had as much money as Bill Gates. (Allegedly.) But let's face it, when you make stuff as heinously ugly as Word, when your business practices are unabashedly evil and even openly criminal, it is only a matter of time until everybody with self-respect is gone, and the only people left who will code for you are mercenaries. And the thing about mercenaries is, if you tell them to shoot your own foot, they will do it. They don't care. It's the money you give them that aims the gun. It's not common sense, it's not good taste, and it's not self-respect. If you say "aim for the foot," they'll say, "your foot?" And if you say "yes," they'll say "left or right?" And if you say, "both," well, let's face it, that pretty much explains every product Microsoft has made for a very long time now. It certainly explains that fucking paperclip.

The real word, though, isn't stupid. It's foolish. Or maybe even arrogant. They saw the future coming and they realized they would have to work much harder and compete in a real marketplace if that future happened. So instead of taking on that responsibility, they tried to stop the future from happening. What could be more arrogant? They tricked IBM into handing over a virtual monopoly, held onto it with criminal ruthlessness, and then when they saw a future coming that would make they irrelevant, they figured they were badass enough to somehow stop the flow of time.

I think we can call that arrogance.

However, if, by our logic, Microsoft is kind of stupid, and if they've created the future they feared, then shouldn't we expect them to go under? Aren't they going to vanish in a puff of righteous come-uppance? Unfortunately, no. Microsoft's days as anything other than a dumb-ass bully with a huge wallet are very, very over, and have been for a very long time. But a dumb-ass bully with a huge wallet is still a dangerous opponent, and Microsoft has a war chest that'll keep it in the black for a long time to come.

Still, their dominance has ended.

Until very recently, the number one reason consumers gave for buying their first computer was spreadsheets. Today, it's e-mail. That's an application hosted on the network, where the desktop doesn't matter. If you want to choose a better operating system, go for it. It makes no difference. Windows is irrelevant there, and without Windows, Microsoft has nothing. That means all they can do is ride on legacy systems until even the latest of the late adopters has come to their senses. (Hey, it works for COBOL programmers.) But if that's their plan, it means the evil genius who took over the world has turned into a toothless bottom-feeder. No wonder Bill Gates retired.

It could just be a matter of time. It could just be a matter of a paradigm shift, too, but it was a paradigm shift they saw coming, fought to prevent, and in so doing, helped to create. That's what's so funny about the whole thing. It's like those old AT&T ads. Have you ever seen a world without Microsoft? You will. And the company that's going to bring it to you? Microsoft.

There's a great podcast of a Clay Shirky presentation where he explains how some of the online businesses which, in the late 90s, destroyed old ways of doing things, these businesses often mistakenly saw themselves, at the time, as continuing the traditions they were actually burying. His big example is sites like travelocity.com. These sites often saw themselves as online travel agents, instead of the end of the line for travel agencies, which is what they actually were. Microsoft's "victory" in the browser wars is pretty much the same thing. They thought they were continuining their tradition of "embrace and extend" domination, but in reality, they were just building a guarantee of their own future irrelevance.

Sunday, December 24, 2006

In Rails, as far as I can tell, if you've got an instance variable that needs to be set the same way every time, using after_filter to set it won't work. This probably isn't a bug; it makes sense because filters are what you filter your actions through. You use before_filter to make sure your users are logged in, for instance.

The reason I'm thinking about this is that I recently came across some code where somebody had used before_filter to set an instance variable. I thought, hmm, that's not what you're supposed to do, but does it work for after_filter? Can I misuse that the same way? It turns out the answer is no, but it makes me wonder, if the fact that you can't misuse after_filter that way is a feature, then surely the fact that you can misuse before_filter that way is a bug.

It's debatable, though. It isn't really a problem in the framework; it's just a design flaw, because it allows you to do something like this:

before_filter :foo

def foo @user = User.find(session[:user])end

Where you're no longer really filtering, you're just doing something first. The thing is, Rails is very, very easy to use, and this attracts people who like simple tools. This means it both attracts people who love the elegance of simple tools, and people who aren't prepared to wrestle with complex tools. But the distinction between filtering and merely doing something first is a subtle distinction. Having to be consciously aware of it is somewhat inelegant, and people who aren't prepared to use complicated tools are probably going to trip over this distinction at least once. I did, and I can usually handle complicated tools without any problem.

Anyway, it threw me for a second that you can misuse the one filter but you can't misuse the other. But the explanation is pretty simple. You can't misuse after_filter because the actions render in the actions. The after_filter is called after all the rendering happens, so even though you are setting an instance variable on the controller, it won't matter, because the instance vars were already copied to the view before you even got there. The comments in Rails depict it as a chain:

(Weirdly, I could only find these comments in the 1.2 release candidate, but I could swear I've seen them before.)

Anyway -- this is kind of a subtle pitfall for newbies. Actually, screw newbies, it's a subtle pitfall for me. I fell into it, and I've been making Web apps for a decade. They even called me a Perl guru at one point. Anyway, yay my ego. Point is, subtle pitfall. There are two parts to it. First, just because you can use before_filter as a generic preprocessor doesn't mean you can use after_filter as a generic postprocessor, and second, just because you can do the preprocessor thing doesn't actually make it a good idea. It is in fact a bad idea.

Moral of the story: only use before_filter for filtering.

(I had a look at the Rails source to see if I could find a way to patch this, but it was just a quick glance, and no dice so far.)

By the way, one interesting footnote to this experience. There's a very smart man who says that good programmers avoid working on stupid problems for the same reason models avoid cheeseburgers. The general idea is that working on bad code makes you a bad coder. For a while I agreed, but now I'm not so sure. I was working on bad code here, when I encountered this anti-pattern, and it wasn't until I copied the mistake in a different context -- applying a before_filter misuse to an after_filter -- that I realized it was a problem at all. On the one hand, this supports the idea that working with bad code makes you a bad coder, because clearly this was a case of monkey see, monkey do. But puzzling over my mistake led me to examine the Rails source and consider a relatively subtle design question. It's entirely possible that working with bad code made me a better programmer, in this instance.

It reminds me of when I was a kid, we had a Salvadoran housekeeper. She was a refugee from Reagan's secret wars in Central America. She cleaned toilets for a living, and she had a master's degree. Her husband had a doctorate. My mother asked her, why don't you get transcripts from the university? But the university had been bombed to smithereens, and not only were her transcripts gone, her professors were all dead. So my mother thought this woman must be hating her life, cleaning toilets when she had an advanced degree, but in fact she was just happy she was still alive. She said, it's not the job, it's how you do it.

The reverse is also true. I've seen people working on fascinating problems who made themselves worse coders in the process just because they were approaching interesting questions in a stupid way. I've done it myself; the most interesting piece of software I ever built was for an idealistic startup with great ambitions but no clue on earth how to run a software business. I reviewed the code later and was flat-out embarassed about how dumb some of the mistakes I made were. The problem came from being perpetually distracted by business issues that had nothing to do with the software. Approaching a set of interesting questions in a stupid way, I made stupid mistakes.

Thursday, December 21, 2006

Bruce Tate is no dummy. Far from it. But his otherwise very interesting introduction to Haskell says that Haskell's "style of lazy processing makes functional languages much more efficient than you'd otherwise expect and allows a powerful abstraction called infinite streams that's not available to other programming languages."

Not available in other programming languages?

You can do this in Perl! It's easy!

OK, maybe easy isn't the word. But it's easier than you'd think. There's a lot about infinite streams in Perl in this book, and it's a pretty good book, btw. Not only that, if you read Hal Fulton's The Ruby Way, there's a section of that where code by Jim Weirich uses continuations to create infinite streams as well. (They call them generators in that book, but they're effectively infinite streams.)

Anyway, I don't think most people would describe either Perl or Ruby as "functional languages," but infinite streams are easy to produce in either one.

The problem with this isn't that the Rails way might not always really be the best way. The problem is that sometimes, the Rails way isn't even relevant. Sometimes what you want to do is neither what Rails grudgingly permits nor what it actively encourages.

I see this a lot with JavaScript. Now it's entirely possible that I just need to step up my RJS game, and if so, then all these criticisms of Rails could in fact be entirely meaningless. Take it with a grain of salt. But in the past six months I've worked on five Rails sites professionally, and in the past year, God only knows how many for fun. I don't think I've worked on a single Rails project yet where I didn't at least once have to add a Rails form handler or JavaScript shortcut to a template just so I could grab the output via view source, copy it, paste it back into the template, and then modify it to do what I really wanted it to do in the first place.

Rails is a fantastic technology, but the frustration here is that, having completely blown all its predecessors away, you kind of expect it to continue kicking ass all over the place, and this cut-and-paste workflow is not exactly crane style kung fu. If you're watching a Bruce Lee movie, and Chuck Norris takes over at the end, it's not exactly an improvement.

This isn't necessarily a design flaw in Rails, either. There's more than one type of Web app to build, and Rails is designed around a certain category of Web app. If you want to do something different with it, you can, it just won't necessarily be easy. At Canada on Rails, I heard DHH say nearly exactly those words, and he was telling the truth.

I'm not really sure what the solution is here. It's probably either a massive review of RJS, or -- perhaps more likely -- some custom code, like a plugin or something, which allows you greater flexibility and specificity on the JS side of things. I don't know if that's going to happen. I don't even know how I'd do it. The big learning things on my plate right now are Scheme, Seaside, and Rails 1.2. That's certainly enough to keep me busy.

About a year ago, I was doing some tutoring in Java for a local college. One of the girls I was tutoring was very good-looking, young, fit, and was supposed to be mastering interfaces. Instead she was struggling with System.out.println(). Around the same time I was tutoring her in Java, I was reading books on Lisp by Paul Graham and Peter Seibel. She was at my place one day, saw one of these books, and asked what it was about. I told her it was high magic and nothing she ought to trouble her pretty little head about.

She opened one of the books, gave it a little snort of contempt, and said, "Oh yeah, Scheme. We did that last year. It's all about recursion?"

As far as languages of the gods go, this young woman was smart, but she wasn't a programming goddess. She didn't have to be. One moral of this story is that no matter how clever and enlightened you think you are, you might in fact just be this silly sexist moron. But a much more relevant moral is that the simpler language might in fact be the better language. It's entirely possible that this young woman found Scheme easy and Java hard because simple designs make more sense.

To say that Lisp is a language of the gods, and Java is a language for mortals, that could in fact be getting everything entirely backwards. Scheme is actually easier to use than Java. So the easier language is the language of the gods, and the hard one is the one for regular people? How does that make sense? And think about something else. The best implementation of Smalltalk I've used is Squeak. Squeak was designed for children. So if Squeak is a language of the gods, what does that make Logo? The language of the angels?

Maybe there's something else going on here.

If there's anything godlike about using Lisp or Smalltalk when the rest of the world is on Java and C#, it isn't the skill level required. It's the balls. Standing up to the rest of the world and telling them, "your technology decisions are bad and I'm going to use a language that doesn't suck" is a very unusual move. It requires a lot of courage. But if you think about that, that's kind of bad. I mean, if what I'm saying is true, then the average technology business is kind of pathetic.

Unfortunately, I've worked for a very large number of different technology businesses, and I can tell you with confidence, certainty, and no fear of inaccuracy that the average technology business is indeed kind of pathetic.

The sad thing is that Ruby still kind of qualifies as Prometheus. It is still a midpoint between the languages of the gods and the languages of ordinary mortals, but not just because of its design. Using Rails is ballsier than using PHP, but it's still abject cowardice compared to using Seaside.

You certainly don't have to be a programming god to use Rails. Far from it. It's possible to put together Rails sites without ever really learning to program at all. When Java replaced C++ as the dominant language, one of the Java guys said that they had brought the world kicking and screaming a few inches closer to Lisp. Rails is fast becoming huge, but to a certain extent, they're only doing the same thing the Java guys did -- bringing the world a few inches closer to Lisp (and Smalltalk). It's not so much dragging the world kicking and screaming in this case, though. This time around it's more about hiding all the good stuff under the hood, where nine out of ten users will never even see it.

But say that we know the average technology business is really kind of pathetic. Say further that the only difference between a company running Seaside, a company running Rails, and a company running PHP is that the Seaside company has huge balls, the Rails company has some balls, and the PHP company has no balls at all. That's got nothing to do with the godlike qualities of any particular language. All that tells you is that very few companies opt to use the best technology available to them. And unfortunately, anybody who has noticed that Microsoft exists already knew that.

The culture of technology businesses has a serious problem, which is that technology decisions are generally made by people who do not understand technological issues. But saying that the best languages somehow require godlike intelligence, when they are in fact simpler to use, more intuitive, and in one case designed for little kids, that's just silly. The difference between a Smalltalk programmer and a Java programmer isn't really located inside their brains at all. Look a little lower down. It's a difference at the scrotum level. One of these programmers has a scrotum, and one of them does not.

It's worth pointing out, the poster children for Lisp and Smalltalk are Paul Graham and Avi Bryant. Neither one of these guys actually had to stand up to management and tell them they were wrong. They just went ahead and started companies using better technology. Paul Graham obviously won pretty big when he did that. It's too early to tell with Avi Bryant, but there's no doubt at all that Dabble puts every other Web app in the world to shame.

I'm going a little too far here, and obviously some of the sexism has returned, with all this talk about genitals, but really, I'm just having fun with this. Think about it. Lisp and Smalltalk aren't languages of the gods. Maybe there are no gods. Maybe all there is is clear thinking and fuzzy thinking, good decisions and bad decisions, morons with MBAs and people who have the courage to state the obvious.

Maybe it is that simple.

---- Update: More people seem to have read this than I anticipated, the anticipated number being zero, so, just for the record, I don't hate anybody's languages. It's not about advocacy. And also, think about this: as trendy as Rails is today, last year, DHH and anyone else on Rails were in that same category with Paul Graham and Avi Bryant, building companies on technologies other people swore weren't ready for prime time. Like I said, it's not about advocacy, it's about, if you want to do it, just do it already.

Monday, December 18, 2006

OK, yes I love Unix, no I don't know how to compile stuff with make. yes I've used make, no it isn't my favorite tool. yes I like getting my hands dirty, no I don't want to spend all day configuring a Unix box, even a Mac OS X Unix box, pretty though it is.

If you need to get Rails up and running on OS X, get Darwinports. It is fast, it is nice, and it is easy. A client told me I needed Locomotive, and Locomotive is great, but it doesn't seem to ship with Edge Rails, and it doesn't get you around the fact that Ruby's on v1.8.5 and OS X is still shipping v1.8.2, without gems.

Also, Rails has this gigantic community, this huge hype machine, and it's an incredible piece of technology to boot. But guess what? You want to get Seaside up and running on Mac OS X? You do two things. You install Squeak (one click) and then you install Seaside (another click). Then you're done. I realize some of that is due to the differences between Ruby and Smalltalk, but still. Seaside definitely clobbers Rails on ease of install. Not the most important factor in every analysis, but certainly the most important factor on a lazy Sunday afternoon when you're still half-asleep.

Monday, December 4, 2006

A while back I commented on DHH's blog about how cool one of the upcoming changes in Rails 1.2 is going to be. The change is that form_tag will now take a block. I commented that this allowed you to have fun simply passing Procs or lambdas directly to form_tag, and was sharply criticized by another commenter:

Proc is short for: (say it with me) procedure. HTML is not a procedure. Yes, we do use executable code to generate HTML, this is called a template, and again, is different from a code block. Storing web forms as proc objects does not compute, even if you put it in an rhtml file.

Comments have since been closed on the entry -- DHH's blog is very popular and appears to be regularly clogged with spam as a consequence -- but I finally came up with my comeback. Yep, about a month later. Not exactly a snappy comeback, but maybe an interesting one.

The criticism was kind of harsh, but the point was valid. Storing Procs in the view is pretty unorthodox. Confusing other programmers is usually a bad idea. But the idea that it could never be useful, I knew he was wrong there, and I finally figured out why.

Say you've got a Web app running in both England and France. The two countries use different languages and different postal systems. So, you're presenting your content in one of two languages, and you have something controlling that. It comes time to write the order form, and you don't know what kind of address form they're going to need. They could need the British postal system, or the French one. You don't know until runtime.

So you just do this:

form_tag &address_form

Elsewhere in the application, say in the helpers, you have a method called address_form which returns or builds the correct partial based on the user's chosen language. Since the language and the address form requirements vary together by country, they are effectively the same thing.

Admittedly, multilingual countries exist, and are in fact very common. Postal systems do not always vary by language. Certainly there are other ways to do this. It's just an example. And it's an example written under the influence of only one small shot of espresso. I do my best work with three or four. But like any example it exists to illustrate a point, and that point is, this design decision can be useful and beneficial beyond the obvious -- beyond its intended application. I think good design results in code which isn't just easy to use for the problems it was designed to solve, but which is also easy to use in ways the original programmer never imagined -- whereas bad design constrains your range of possible choices to things that the original programmer already knew would happen. The great thing about this decision for Rails 1.2 is that it's going to open up new possibilities -- in addition to the fact that it is an excellent way to handle the problem it was designed to solve.

Saturday, December 2, 2006

Prefactoring is an exposition of principles for software design, laid out in the context of the development of a fictional application. I've never been into that particular style of writing about software design; in fact, it was the only thing I didn't like about Martin Fowler's Refactoring, which is the inspiration for both Prefactoring's own fictional case study and its name as well.

When you've got one programming book named after another one, one reasonable idea is to compare the two. Prefactoring's premise is that, instead of fixing your design afterwards -- an extremely terse summary of Refactoring -- you apply what you've learned from that in the past to build it with the right design principles from the get-go. That sounds like good common sense, and it is. Unfortunately, it really only makes sense in the context of a misunderstanding of Refactoring. Refactoring and debugging are different things. It's very common in software for people to use buzzwords and catchphrases as an alternative to thinking, and consequently, in certain organizations, you'll hear "refactoring" used as a synonym for "debugging."

In fact, refactoring is supposed to happen during debugging -- but it's also supposed to happen during the course of development, and in fact this is the preferred time to do it. Refactoring comes from agile development, specifically Extreme Programming, where the basic cycle is to write unit tests, write the simplest code that can possibly satisfy those tests, refactor that code, and then begin again with new unit tests. Refactoring can mean improving things during debugging, but much more importantly, what it really means is streamlining existing code as you refine it. To say that the best thing to learn from refactoring is to get your code right first time is to use the vocabulary of agile development to advocate waterfall development, and this, in fact, is what Prefactoring often seems to do.

Worse still, many of the code examples are in Java, and they don't use Josh Bloch's guidelines from Effective Java or Java Puzzlers. This might be a quibble, but I'd certainly hire or fire based on this quibble, as I think it's very important (and therefore not a quibble at all). Pretty much everything I've done for months has been in Ruby on Rails, so I'm frequently reminded that Java is not popular in every sector of the tech industry -- however, if you are going to write Java, I personally feel that writing Java without observing Bloch's guidelines is careless at best, and borders on outright negligence.

On the other hand, I seem to be kind of eviscerating this book here, and that's not quite fair. I disagree with some of the design principles laid out in this book, but most of them are pretty strong in the common sense department. Also, software development is one of those things where you can be better off after reading a book even if you disagree with it. For instance, just in criticizing this book's attitude towards refactoring, I've had to question my own understanding of it. If you read this book with the right frame of mind, you'll challenge your own ideas and come to new conclusions, and probably become a better developer in the process.

Now that I've gotten through the basics of Ruby and Rails -- including arcane basics like lambda() and instance_variable_set(), and embarassing basics like unit testing, which is embarassing because I only really made it a habit last week -- I'm starting to get really interested in API design. Ultimately, as useful and trendy as Rails is, and as lovely and gentle as Ruby is, the thing that make them both most interesting to me is the question of how to design for client programmers.

If you define an API as a set of tools which make life easier for downstream programmers, the line between a language and an API is blurred. This kind of ties in to the current fashionability of DSLs -- a DSL is midway between a language and an API.

Jamis Buck blogged two excellentposts about API design, and one thing I really like about both posts, each one praises work done by other members of the Rails core team. I'm a big fan of credit where credit is due.