Thursday, December 11, 2008

What, you're too good to map routes now?

Bruce Tate spoke at LoneStar RubyConf about, among other things, how weird and complex ActiveScaffolded controllers are compared to old-school "def super_special_find_thing" actions pre DHH going off the deep end with this crazy REST business. He (Bruce) billed the problem as a steeper learning curve for beginners to grok all the sundries of a resource, contrasting a Rails 1 scaffolded controller to one of Rails 2 side by side. It's an effective argument, and although I like REST for several design reasons I won't bother going into here, I tend to agree with Bruce and with David Black that there's a better than even chance that we've lost the forest for the trees on this stuff.

Enter the latest Railscast, which paints nested resources through a Rails 2.2 lens, with some nice new shortcuts. Toward the end, Ryan brings up the idea of both nesting and not nesting a route to point to the same action on the same controller, indexing comments both scoped to articles and not ("/articles/1/comments" versus "/comments"). This is sort of a problem, since unless the logic is different enough between the two scenarios to warrant a second controller or action, it makes for a slightly messy conditional for find:
if params[:article_id]
@article = Article.find params[:article_id]
@comments = @articles.comments
else
@comments = Comments.all
end
Not sasquatch, but not a good prom date, either. But maybe it's justifiable. Anyway, Ryan focused on the obvious routing error when visiting /comments and used the situation to highlight a heretofore glaring oversight in the map.resource method; that is, always generating 14 (now 7) routes, by gum whether you want em or fuckin not.
map.resources :comments, :only => :index
It definitely scratches the itch scaffolding leaves, with its willy-nilly XML format.xml calls that are never tested and such (see Bruce's talk for more on that), and I realize Ryan's just coming up with a simple example to highlight the feature, but seriously. How fucking hard is
map.comments "/comments", :controller => :comments, :action => :index
I guess I like this for several reasons, clarity being somewhere near the top (but brevity nowhere in sight), and while I would probably use the resources :only method on an app myself, the thing it best demonstrates is an understanding of the routing system. Our app is full of map.resources calls for single action controllers (consequently rake routes takes a fucking year to boot up -- I can't be expected to memorize how two-deep nested routes get named, which is also covered by Rails 2.2 and the Railscast), as opposed to using old fashioned (downright quaint) custom named routes, probably mainly because whoever mapped those routes, coming of age in the Rails 2 era, didn't know you could actually just map whatever the hell you want. It's all map.resources and catch whatever at the bottom with map.connect "/:controller/:action".

So it's the indication of the attitude that bugs me, not necessarily anything about the feature. I'm not going to do much with a web stack that involves a single line of code, "app.go", so pardon me if I'm actually interested in even the most pedestrian understanding of how my framework gets from an HTTP request to render :partial. The spirit of REST in Rails isn't lost on me, and I realize it's an extension of the mission statement: keep the bullshit out of my way and let me get something done. But there's a difference between keeping me from having to hand-crank my car and my willful ignorance of what a fuel injector does.

Saturday, July 12, 2008

Of Genies and Malcontents

One cannot complain about the ineffectiveness of a tool when using it in a less-than-optimal fashion.

Better said, and with an obvious appeal to both geekiness and 8-bit nostalgia: I bought an NES Game Genie in 1991, with sugarplum dreams of finally beating Master Blaster (which, after years of deliberation, I've decided is impossible). There I sat, this golden gate to glory in my sweaty little hands. I lovingly but firmly slid Teenage Mutant Ninja Turtles onto the mantle of the Genie, gazing in awe at the lovely gold against the (let's now admit it, all these years later) blase grey. I tucked this now-10-inch-long apparatus into my NES, only briefly balking at the notion of not clicking the cartridge down, and pushed the cartridge back. Lightly, in deference.

Some people call it static, what I saw. I call it bullshit.

I didn't panic. I RTFM, I find that you're supposed to push the unit in until the NES lid comes down. I did that. More bullshit.

Dreams shattered, I threw the golden Judas Iscariot box of Genie shit across the room, now preparing for my first merchandise return. I sat there, thinking of the recriminations I'd meet at the hands of some Wal-Mart employee for being unable to know a real miracle in gaming technology from a $40 snake-oil-level swindle, and who the hell hasn't beaten Super Mario Bros. by now, you little retarded shit?

Every product return since echoes of that inner discourse.

Anyway, a friend of mine came over the next day, with fresh enthusiasm to meet my abject despondence. Never one for subtlety -- he who once threw a brick at a rattlesnake -- he grabbed that game-and-Genie and jammed that motherfucker far enough that the pink pixellated Genie on the label probably could prove one way or the other whether my NES had prostate cancer. Fucking bingo. That sick pink finger in cuff and cufflink slid delightfully over the screen, bringing all my dreams of success slinking back like so many once-scolded, now forgiven puppies.

This is, ostensibly, a programming blog, so, I imagine you're thinking, what in the name of the invisible pink unicorn does this have to do with, ahem, programming? Beyond of course the nature of Game Genie alphabetical codes somehow arbitrarily being able to make Mario grey and heavy.

I guess, then, the typey-typey, runny-runny part of the blog post starts with my admission of a secret and somewhat irrational love for C. College was where I picked up the coding bug, unlike most of my compatriots, who will only be too happy to reminisce of those heady days of Q-BASIC and puberty and yeah, shit, dude. A light dabbling with VB and C++ aside, I cut my teeth in that first C class, watching the professor demonstrate bubble sort by physically shifting around six students at the front of the class. I learned many things from my time in college, including "Never date an alcoholic unless you want to be an alcoholic." Only slightly less well known, however, is that most state universities' CS departments are made up of guys who highly dislike the notion of enterprise software. And what represents enterprise and business software, with all its pomp and circumstance, better than Object-Oriented Programming? (And by extrapolation, OO Analysis and Design.) Objects are things dreamt up by ivory tower architects. class:C++::struct:C, and that's all you really need to know about that. OO is about squares and rectangles, or hourly and salaried employees. With this sort of rhetoric, it's no wonder I ended my college years dearly hoping to not be doing stupid-ass Java, which was not only garrulous to a fault and restrictive, but positively _mired_ in objects. I wanted a job writing reams of C code, spurred on by my Compilers professor's claim that "the first million lines of code you write are the hardest."

You have no reason to believe it, I understand, but I assure you that I play host to an immodest amount of object bigotry, although it certainly took its sweet damn time manifesting. Any notion that OO was a proper model upon which to base a project was pounded out of me by my professors, each and every one. "Why write that neural network in C++? You can take all those classes you wrote and map them to functions in C." I knew there was something I wanted, something I just couldn't put my finger on. I wanted to tell a neuron to process some data. I didn't give a shit what it did with it, just that it gave me a result. But the elegance of using objects still eluded me. So I was practicing what a friend calls POOP -- procedural object-oriented programming.

Maybe the best example to bring me to my thesis [effing finally!] is my Software Engineering class, during which we mostly sat and listened to our prof's horror stories about writing code for the gov'mint. I learned a lot in that class, as much in unintentional example-as-counter-example (read: waterfall as a workable process) as not. The lesson I keep coming back to, like most of its kind, is an extremely dense and complicated thing hidden in a very pert toss-off statement, which I roughly paraphrase here:

"Objects. Hmm. In my experience, object-oriented programming just doesn't work. Everyone said, ten years ago, 'OK, everybody, just start writing classes to do whatever. We'll have libraries of classes, a class for a clock, a class for arrows. You can sell them, share them, whatever, and everyone will be able to reuse them without ever needing to write another clock or arrow.' And that's just bullshit. You can't buy a clock class from someone, because you always need it to be slightly different -- the hands need to be longer, or blue, or it needs to be digital. So it's just a fool's errand, object-oriented programming."

Now, I'm not going to delve into the massive fallacies of this argument any more than I need to, but I recognize you might need to. Take a second, come up with a zinger, and let's continue. K. I thought this was bullshit when I heard it, although, like I said earlier, I was a pretty massive procedural adherent at the time, with just this passing interest in OO, so I didn't think much more of it for years. Its effect on me aside, though, it brings me straight to my point:

If you don't understand the theory behind a school of thought, its application is going to evade you. If you were somehow laboring under the notion that you drive nails with the hammer handle, you would be justified in not wanting to use a hammer. But, of course, you're an idiot who uses tools he doesn't understand. If you think OO is about clocks...well, you're just fucking _wrong_. Reuse isn't about somebody tossing around libraries full of random classes. I can't even begin to fathom the absurdity of that, unless he was just watering down the notion of APIs, analogs to RubyGems or SourceForge or whatever. And anyway, as we all know, RubyGems is a massive failure, right? OO is about responsibilities and drawing lines, about consistent interfaces and not giving a shit what goes on behind them. Those books that try to boil OO down to "Trucks and Cars are both PassengerVehicles, where Cars have four doors and Trucks have two and a tailgate." are getting it wrong, or at least glossing over the important details. Nobody's going to model a vehicle that way -- who would need to? Except Halo, I suppose. OO is about modeling, and it's about modeling of a very specific type. It's not something Toyota is going to use to build computer models of a new concept car. They're going to use it to model the abstract concept of a car as it relates to inventory. Or its progress through the manufacturing process. The behavior of a PassengerVehicle isn't drive_forward(), or stop(). It's move_forward_in_assembly_line(), or complete?(). We, as business software developers, model a business. Which is fundamentally a set of abstract activities that are mostly mental in nature. So we're really modeling ideas.

Which has fucking _nothing_ to do with squares and rectangles.

And they don't even try to explain polymorphism or information hiding. That's the last five minutes of class, during which they fill the empty spaces next to the 2. and the 3., right below the giant 1. Inheritance!!!!!!!!!!

This post obviously deals mainly with OO, but the concept applies broadly. Don't bring up typechecking and Ruby -- a lot of people have written a lot of good Ruby code (and other languages of its ilk) without missing typechecking. Complaining that Ruby has no typechecking is like complaining that airplanes maintain such an absurd distance from the ground. In this, the industry of omnipresent malignity, every tool is derided as shit ("MySQL sucks, but not as bad as SQLServer. And don't even get me started on Oracle, DB2 or Postgres."). For such a good job, which let's face it, is just getting to be creative and nerdy and wear comfortable shoes to work, we certainly bitch about stuff a lot. I guess we have to take most of that as understood, just part of the collective personality of programmers in general -- but please, let's at least learn how to use something before we break out the week-old fruit.