Uncategorized
Rails' Next Top Model
Of all the new and reimagined code in Rails 3, ActiveModel and ActiveRelation rank amongst what I find the most interesting. I’m excited that they potentially lower the bar to implementing one’s own data layer. If you’ve got some custom backend or datastore, writing a nice API around it has previously been quite the endeavor. To get it working is one thing; to make it as pleasant to use for application programmers is another thing entirely. ActiveModel and ActiveRelation have been extracted from ActiveRecord and make the task of building one’s own model layer far easier.
My presentation for RailsConf 2010 focused on what ActiveModel and ActiveRelation provide and how one can use it to write cleaner code in domain models, how to make your models feel more like ActiveRecord objects, and how to use ActiveRelation to build your own persistence layers.
I hope you find the slides educational. Further, I’ve posted the examples on GitHub so you can play along at home. If you’re particularly interested in ActiveRelation, I hope you’ll find the examples useful as a starting point to using that library.
Make More Awesome
Over the past year, I’ve been trying to create more stuff, some of which I’d hope to turn out awesome. Largely this is an ongoing sort of thing. I try things, I learn a little, I keep at it. Some things I try work, others don’t. I try to make a habit out of the things that have worked out well. I make a note of things that seem to help me get out of a funk when I’m not making as much as I’d like or having trouble putting in the hours I think are necessary to make cool stuff.
I first distilled these ideas into a talk I did at RubyConf 2009 on having more fun while coding. But I didn’t realize it at the time; I was just sharing some ideas about how to have fun. For me, one of the ways to have more fun is to make more time to have fun. But that’s just the beginning of making more awesome. I found I had to make more time, and develop a bunch of other habits.
For Big Design 2010, I honed the ideas, habits, and tricks I’ve found useful to me into a presentation on how to get off the couch, start making more things, and make some of those things awesome. I hope you’ll find it useful and perhaps start making lots of awesome stuff.
A quick RVM rundown
(It so happens I’m presenting this at Dallas.rb tonight. Hopefully it can also be useful to those out in internetland too.)
RVM gives you three things:
- an easy way to use multiple versions of multiple Ruby VMs
- the ability to manage multiple indpendent sets of gems
- more sanity
First, let's install RVM:
gem install rvm
rvm-install
- follow the directions to integrate with your shell of choice
Now, let's install some Rubies:
rvm list known
will show us all the released Rubies that we can install (more on list)rvm list rubies
will show which Rubies we have locally installedrvm install ree-1.8.7
gives me the latest release of the 1.8.7 branch of Ruby Enterprise Editionrvm install jruby
will give me the default release for JRubyrvm use jruby
will switch to JRubyrvm use ree
will give me Ruby Enterprise Editionrvm use ruby-1.8.6
will give me an old and familiar friendrvm use system
will put me back wherever my operating system left me
The other trick that RVM gives us is the ability to switch between different sets of installed gems:
- Each Ruby VM (JRuby, Ruby 1.9, Ruby 1.8, REE) has its own set of gems. This is a fact of life, due to differing APIs and, you know, underlying languages.
rvm use ruby-1.9.1
gives you the default Ruby 1.9 gemsetrvm use ruby-1.9.1%acme
gives you the gemset for your work with Acme Corp (more on using gemsets)rvm use ruby-1.9.1%wayne
gives you the gemset for your work with Wayne Enterprisesrvm use ree%awesome
gives you the gemset for your awesome app- You can export and import gemsets. This can come in handy to bring new people onboard. No longer will they have to sheepishly install gems on their first day as they work through dependencies you long since forgot about.
Some other handy things to peruse:
I also promised you some extra sanity:
- RVM knows how to compile things, put Rubygems and rake in place, even apply patches and pull from specific tags. You can do more important things, like watch The View or read an eleven part series on pre-draft analysis for the Cowboys.
- RVM lets you isolate different applications you're working on. Got one app that doesn't play nice with Rails 2.x installed? No problem, create a gem environment for that! Stuck in the spider-web of Merb dependencies? Isolate it in its own environment.
- RVM makes multi-platform testing and benchmarking easy. You can easily run your test suite or performance gizmo on whatever Rubies you have installed.
- RVM makes it easy to tinker with esoteric patchlevels and implementations. For instance, feel free to tinker with MagLev or the mput branch of MRI.
A couple other things RVM tastes great with:
- Using homebrew to manage packages instead of MacPorts
- Not using
sudo
to install your gems - Managing your dotfiles on GitHub
The imperfection of our tools
I enjoy a well-crafted application. I place a high value on attention to detail, have opinions on what design elements make an application work, and try to empathize with the users of applications I’m involved in creating. Applications with a good aesthetic, a few novel but effective design decisions, and sensible workflow find themselves in my Mac’s dock. Those that don’t, do not.
The applications I observe fellow creators using to create often don’t fit into their environment. They don’t fit into the native look-and-feel. They ignore important idioms. Their metaphors are imperfect, the conceptual edges left unfinished.
In part I notice this because as creators we tend to live in a few different applications, and time reveals most shortcomings. But in part, I notice this because the applications are in fact flawed. Flawed to the point, that you would think given my opening words, that I would refuse to use them. And indeed, I refuse to use many of the applications that others find completely acceptable for making the same kinds of things I do.
Increasingly, it seems the applications that people who create things live in offer a disjoint user experience. I’m thinking of visual people living in Photoshop or Illustrator or developers living in Emacs or Terminal.app. We use these applications because they best allow us to make what we want and get in our way only a little bit. But, it’s a tenuous relationship at best.
What’s this say about what we’re doing and the boundaries that we operate along? Would we accept the same kinds of shortcomings in say, a calendar application or a clock widget, if those were central to our workflow? That is, is there something about the creative process that leads us to accept sub-perfect tools? Is it inevitable that someone seeking to make new things will find their tools imperfect? Is the quest for ever-more perfect tools part of how we grow as makers?
I hate closing with a bunch of questions, but this piece is but an imperfect tool for discovering an idea.
Ed. Closing could use some work.
Give attribute_mapper a try
(For the impatient: skip directly to the `attribute_mapper` gem.)
In the past couple months, I’ve worked on two different projects that needed something like an enumeration, but in their data model. Given the ActiveRecord hammer, they opted to represent the enumeration as a has-many relationship and use a separate table to represent the actual enumeration values.
To a man with an ORM, everything looks like a model
So, their code ended up looking something like this:
class Post < ActiveRecord::Base belongs_to :status end class Status < ActiveRecord::Base has_many :tickets end
From there, the statuses
table is populated either from a migration or by seeding the data. Either way, they end up with something like this:
# Supposing statuses has a name column Status.create(:name => 'draft') Status.create(:name => 'reviewed') Status.create(:name => 'published')
With that in place, they can fiddle with posts as such:
post.status = Status.find_by_name('draft') post.status.name # => 'draft'
It gets the job done, sure. But, it adds a join to a lot of queries and abuses ActiveRecord. Luckily…
I happen to know of a better way
If what you really need is an enumeration, there’s no reason to throw in another table. You can just store the enumeration values as integers in a database column and then map those back to human-friendly labels in your code.
Before I started at FiveRuns, Marcel Molina and Bruce Williams wrote a plugin that does just this. I extracted it and here we are. It’s called attribute_mapper
, and it goes a little something like this:
class Post { :draft => 1, :reviewed => 2, :published => 3 } end
See, no extra table, no need to populate the table, and no extra model. Now, fiddling with posts goes like this:
post.status = :draft post.status # => :draft post.read_attribute(:status) # => 1
Further, we can poke the enumeration directly like so:
Post.statuses # => { :draft => 1, :reviewed => 2, :published => 3 } Post.statuses.keys # => [:draft, :reviewed, :published]
Pretty handy, friend.
Hey, that looks familiar
If you’ve read Advanced Rails Recipes, you may find this eerily familiar. In fact, recipe #61, “Look Up Constant Data Efficiently” tackles a similar problem. And in fact, I’m migrating a project away from that approach. Well, partially. I’m leaving two models in place where the “constant” model, Status
in this case, has actual code on it; that sorta makes sense, though I’m hoping to find a better way.
But, if you don’t need real behavior on your constants, attribute_mapper
is ready to make your domain model slightly simpler.
Testing declarative code
I’m a little conflicted about how and if one should write test code for declarative code. Let’s say I’m writing a MongoMapper document class. It might look something like this:
[sourcecode language=“ruby” gutter=“false”] class Issue
include MongoMapper::Document
key :title, String key :body, String key :created_at, DateTime
end [/sourcecode]
Those key
calls. Should I write a test for them? In the past, I’ve said “yes” on the principle that I was test driving the code and I needed something to fail in order to add code. Further, the growing ML-style-typing geek within me likes that writing tests for this is somewhat like constructing my open wacky type system via the test suite.
A Shoulda-flavored test might look something like this:
[sourcecode language=“ruby” gutter=“false”] class IssueTest < Test::Unit::TestCase
context ‘An issue’ do
should_have_keys :title, :body, :created_at
end
end [/sourcecode]
Ignoring the recursive rathole that I’ve now jumped into, I’m left with the question: what use is that should_have_keys
? Will it help someone better understand Issue
at some point in the future? Will it prevent me from naively breaking the software?
Perhaps this is the crux of the biscuit: by adding code to make certain those key
calls are present, have I address the inherent complexity of my application or have I imposed complexity?
I’m going to experiment with swinging back towards leaving these sorts of declarations alone. The jury is still out.
Representing time in our programs
The time problem is not easy to see in today's mainstream languages because there are no constructs that make time explicit. It is implicit in the system. We don't even know that's what we're doing when we use locks to try to make this work.
I’ve been thinking about how we represent time in programs for a while. The problem is that concurrent programs are all about time, but mostly, we only use two mechanisms to represent it in our programs.
The semi-explicit way is through locks. When we insert locks around some bit of code, we are giving hints to the system that things should only proceed in a certain order. This ordering gives us a notion of time, but it’s not horribly comforting.
The completely implicit way we represent time in our programs is by ordering calls to functions and the lines of code within those functions. Line 10 always executes before line 11, etc.
The problem that Rich Hickey, who has some fantastic ideas about this time stuff, has in the article I quoted is that time is managed manually and implicitly. When you start writing large concurrent programs, this falls apart. We need better constructs to deal with it.
Think of it like the shift from unstructured programming to structured programming to object-oriented programming. At first we just had a long code listing; no functions, just line after line of code. This became mentally untenable, so we shifted to structured, procedural programming. But some of our data was global and it was often hard to tell what functions belong to what data. So we moved to object-oriented programming and encapsulation.
Hopefully Rich Hickey, Simon Peyton-Jones and other functional programming folks can lead us to is a nice way to structure our programs around time. I’m eager to have my brain melted by what they conjure up.
It's not NoSQL, it's post-relational
Almost five years ago, we were witness to the reinvention of web frameworks. A couple upstarts named Django and Rails appeared at almost the same time, espousing many of the same values. In the typical Gandhi-cycle, they were first ignored, the incumbents fought them, and then they achieved victory over the incumbents. Today, any framework that’s used on new projects is likely to have more than a hint of Django and Rails in it.
Today, we’re seeing the same thing for databases. Something is going on and things are changing. Barring an unprecedented departure of fashion from software development, I’ll look back five years from now and write about some other shift in the development landscape.
But, all shifts like this need a name. Right now, the best we have is NoSQL. The problem with that name is that it only defines what it is not. That makes it confrontational and not amazingly particular to what it includes or excludes.
Damien Katz, the creator of CouchDB, has noted the need for a better name for this storage revolution. Allow me to proffer mine:
Post-relational
What we’re seeing its the end of the assumption that valuable data should go in some kind of relational database. The end of the assumption that SQL and ACID are the only tools for solving our problems. The end of the viability of master/slave scaling. The end of weaving the relational model through our application code.
We’re seeing an explosion in the ideas about how one should store important data. We’re looking at data to see if it’s even worth persisting. We’re experimenting with new semantics around structure, consistency and concurrency.
In the same way that post-modernism is about reconsidering the ways of the past in art and architecture, post-relational is a chance for software developers to reconsider our own ways. Just as post-modernism didn’t invalidate the entire history of art, post-relational won’t invalidate the usefulness of relational databases.
However, it’s likely that those working in some domains will decide that non-relational databases better fit their needs. That’s progress in our field. It’s fun to watch.
Say it with me: post-relational databases, post-relational storage, post-relational thinking, or simply, post-relational.
Blame the compiler
Remember when you first started programming? Those early days when you'd take some code out of a book or article, type it out, and then try to make it print silly things or draw funny pictures?
The thing I remember about those days was the temptation to blame the compiler for all the ills of my code. Something doesn't work right and you can't figure out why? Blame the compiler! Of course, this was never right. The compiler is very rarely incorrect.
My goal today is to bring back the joy of blaming the compiler. Of course, Ruby doesn't _have_ a compiler (yet!), so we have to play tricks. But that's part of the fun!
Let's blame the compiler.
See, all you have to do is extend BlameTheCompiler
. And then you'll find yourself with one chance in every three executions to say "Hmm, I'm sure I defined that method. Something must be wrong with Ruby." Just like those early days of programming, you're half right. The other half is that you've got a little prankster running in your application.
It's a fun parlour trick. I would not, however, recommend sending code including BlameTheCompiler
in as a bug report to the JRuby or Rubinius folks. They wouldn't find it as funny as you or I.
The Technology Behind Tag Better
I promised you the details on how we built Tag Better, so here we go. This is what I used to build the back-end bits. You’ll have to pester Chris or Alex to get the front-end details.
h2. Sinatra
Technically, it’s a Rails Rumble. Read between the lines of the rules and you’ll see it’s really a Rack Rumble. And so I went with my favorite for prototyping, Sinatra.
Happily, Sinatra had my back the whole time. I never came across anything that stumped me. Further, I didn’t pay any taxes for ceremony I don’t need.
Verdict: perfect tool for the job.
h2. Passenger
I hadn’t used Passenger much before this weekend. I’m pretty happy spooling up app processes in a terminal and watching the logs scroll past. localhost:3000
is my friend.
However, I’m an outlier in this regard. My teammates aren’t as interested in lower-level bits as I am, so I figured that using Passenger is the best bet to help them get the app up and running locally.
The benefit that I didn’t realize we’d get from this is running the same stack locally as on the production server. Besides some virtual host wrangling that Passenger Pane saved me from locally, getting the app up and running was painless.
Verdict: I am quite likely to keep tolerate Apache for that Passenger goodness, especially when I am the operations guy.
h2. Sprinkle + passenger_stack
The moment that I realized we’d have to set up our own server instance was one of brief, abject terror. I knew this could easily expand to fill a lot more of my time than I wanted. Luckily, I was wrong.
Ben Schwartz’s passenger_stack helped me get our Linode slice up far faster than I would have been able to by hand. I cloned his repo, tweaked it to our needs (disabled MySQL, eventually added a CouchDB recipe) and ran it on our server. Several minutes later, we had a working server. Pretty awesome.
passenger_stack
uses Sprinkle, which isn’t getting as much play in the server configuration space as Puppet and Chef. Sprinkle does seem really well suited to standing up apps on a few servers. We might want to step up to something heftier once we had more servers, but Sprinkle and passenger_stack
are simple to understand and don’t require any supporting infrastructure to use.
Verdict: Not too primitive, not too involved; just right.
h2. CouchDB
When I’m building any app that relies on an API as its primary data source, caching API response data is forefront on my mind. Serving the data locally, rather than making a request every time, means the app feels more responsive. An added benefit is not upsetting the upstream data provider.
I’ve built apps like this that use MySQL as a cache and it just never felt right. I’ve been tinkering with CouchDB and Tokyo Cabinet/Tyrant lately. I decided to go with CouchDB for this one because of the excellent CouchDBX, which makes it easier for those who don’t even know what Erlang is to use CouchDB.
CouchDB ended up working pretty well. While we haven’t really leaned into it, it didn’t present any challenges while I was developing. Using CouchRest with Sinatra worked just fine.
Verdict: It just worked, which is exactly what I needed.
h2. Skipping traditional TDD
OK, so maybe only Jared Diamond would consider this a technology. But skipping the writing of tests to drive my design was pretty helpful. Consider Kent Beck’s flight metaphor. Doing a Rails Rumble is just like the taxi-ing phase. Or a minimum valuable product. Either way, you want to make a small investment towards validating an idea.
Notice I said traditional TDD. To tell the truth, I did write a sniff test script after I had the basic app working. But it wasn’t an xUnit-style test. It’s just a shell script that bangs on the app with fixed parameters. I do have to manually inspect it to make sure nothing is blowing up. What I’m really automating here is the pain of typing out Curl commands.
Verdict: worked great for the original purposes, but I’ll probably add a proper test suite as one of the first post-contest enhancements
So that’s what I think helped make our project go off pretty well. Really, what they did was help me get stuff done and then get out of the way. Isn’t that the best kind of tool?
Tag Better
Yesterday and today, I worked with Alex Bischoff and Chris Griego on a Rails Rumble project. In less than forty-eight hours, we set out to build a web application, using Ruby, from the ground up. While we didn’t boil the ocean, we did come up with something interesting.
Tag Better is the groundwork for an app that enhances one of our favorite, but often neglected, sites: del.icio.us. Personally, I’ve tried other bookmarking tools such as a plain text file, EagleFiler and pinboard.in (which I think has an excellent chance of eclipsing Delicious). However, I’ve found myself back on Delicious, even after a hiatus.
Given Yahoo’s unsteady stewardship of the site, we figured it’s time to take matters in our own hands. Using their API, it’s entirely possible for us to build enhancements on top of Delicious. We decided to do just that.
h2. Triage and tidying
We started out from a gem of an idea that Chris had. When you’re trying to better organize your tags and bundles in Delicious, there are two modes you might want to operate under. The first couple times, you need to do triage. Get stuff roughly into order, and start creating a filing system. Once you’ve got everything under control, you switch to tidying. Now you just need to keep things clean or maybe switch things around that aren’t working well.
We tackled triage first. In specific, we wanted a way to filter down our list of tags, select a bundle, and add some of the filtered tags to that bundle.
h2. Try it out
To get started with Tag Better, you’ll first need to log in with your Delicious username and password (more on that in a moment.)

Once you’re logged in, you’ll see your tag bundles on the left and all your tags on the right. If you click a bundle, the tags that are included in that bundle are highlighted. Clicking a tag toggles its inclusion in the bundle. Changes in Tag Better are immediately reflected in Delicious.
That’s the core interaction. You can also logout, of course. And, if you feel the need, we offer a way to remove your bundle and tag data from our system’s caches.
We were just four short characters away from getting live filtering of your tags via the search box on the top right. Alex and I even got it working, but keyboard cat had already played us out at that point. I promise we’ll add it as soon as judging is over!
A couple other caveats: you might want to create a test bundle (in the Delicious UI) to play with, rather than one you’ve already organized. I don’t think there are problems in the code, but it never hurt to show caution. Also, IE support is probably “interesting”, at this point.
h2. Trust
Even though we need your Delicious username and password to edit bundles on your behalf, we have made sure to never store authentication information on our side. Your authentication data is stored in a cookie on your machine; if you don’t like that, you should probably skip out on using Tag Better as a hosted app. If you delete that cookie, we won’t operate on your data. Further, we’ve added the ability for you to remove your bundle and tag data from our system. That’s the only data that we save on our disks.
I mentioned trust and your authentication data earlier. It’s an important part of an application like this. We don’t want to screw your bookmarks up, and you don’t want us to do skeezy things with your bookmarks. Unfortunately, Delicious does not yet offer a delegated authentication API like Flickr and Twitter do. So, we’ve got two options.
On the one hand, you could trust us. This is up to you. I’d like to think that if you’ve met Alex, Chris or I, then you’re happy to use the application knowing we’ve got more amusing things to do than soil your bookmarks. Further, when the competition is over, we’ll open the source repository up to the public. If you’re a code-review sort of person, go nuts.
On the other hand, you could run it yourself. Again, once the competition is over, we’re going to release the code. Look over the readme, install the dependencies, and run it on your own hardware. Sleep safely at night knowing your password is safely ensconced on your personal machine.
Tomorrow I’ll talk a bit about the technology we used to make Tag Better. Until then, I hope you’ll give it a try. If you have ideas for feedback, leave a comment here!
Code re-use as technical debt
I have extremely mixed feelings about code re-use. I think it’s largely a red herring, never working out as well as developers would hope. After all, developers are like golfers; always optimistic about how well an approach will work or how far down the fairway their ball landed.
But here’s a real stab in the side of code re-use: in many cases, it’s tantamount to technical debt. Embrace technical debt:
For example, early on at IMVU, we incorporated in tons of open source projects. This was a huge win (and we were delighted to give credit where it was due), because it allowed our initial products to get to market much faster. The downside was that we had to combine dozens of projects whose internal architectures, coding styles, and general quality varied widely. It took us a long time to pay off all the debt that incurred – but it was worth it.
Using someone else’s code will help you keep moving now, but you stand a good chance of needing to rewrite it later.
That’s not to say it’s all bad. By the time you know you need to replace someone else’s code, you’ll have learned about the domain it covers and how you need to solve that problem in your domain.
Keep it in mind: just because you can drop someone else’s code into your app and use it, doesn’t mean it’s all roses and butterscotch.
rufus-tokyo goes 1.0.0
rufus-tokyo 1.0.0 - I’ve been tinkering with Tokyo Cabinet and Tyrant lately. It’s great stuff. Grab this gem and start tinkering!
When to do test-driven development
I believe that writing code using testing[1] as a design activity yields long-term benefits that make my life easier.
Though I’m a strong believer, I’ve struggled with TDD in the past. I’ve found I get bogged down in keeping the red-green-refactor cycle going. Sometimes I have to work with code that is lacking sufficient tests, but I know I can’t boil the ocean before I proceed to whatever I’m really trying to do with the code. Other times, I’m not sure if I’m testing the right things; I could be missing tests in one place and writing too many tests in another.
Three easy pieces
Last week, I read three insightful pieces and made one discovery of my own that deepened my understanding of the practice of TDD. Allow me to share.
First off, Kent Beck has been exploring the phases in the life of a startup. The earliest stage is proving the idea. He later asserted that when you’re doing stuff like this, you can drop TDD, temporarily. I thought about this and it clicked. If you’re working on a prototype, where you’re trying to explore an idea and see if it works, you don’t want to iterate on the code, as TDD would have you do. You want to iterate on the idea. TDD will just slow you down.

On the other end of the spectrum, you’ve got maintenance programming. Once a startup, company or project has proven their idea and shipped a system, you are maintaining software. Keeping it working, living, breathing. For this sort of development, where you’re making small, focused changes without adding significant functionality, Tim Bray pointed out that TDD is critical. Using it to drive the process of fixing bugs, cleaning up the system and adding minor functionality is really handy for figuring out if you’ve broken something in some dark corner. It also helps the next guy to do the same. It’s a win, and I suspect it’s the sweet-spot of TDD.
If you imagine prototyping and maintenance as opposite ends of the software life-cycle spectrum, adding significant new features to existing software probably lies somewhere in the middle. You may need to “poke around” to decide if what you’re doing is right, like when you’re prototyping. But once you’re done, you want some way for others who have to maintain the software (such as yourself) to figure out what it’s supposed to do and whether assumptions have been broken.
Then I read an anecdote by Uncle Bob about how he worked out an ambitious new feature in Fitnesse. He and his pair got a new feature working, celebrated, and called it a night. When he woke up, he realized they weren’t actually done; they still had to clean it up, by writing tests.
Oh. Duh.
This was the missing link, for me. Sometimes, you need to iterate on the idea first. If skipping the tests helps you, so it goes. Once you’ve got the idea working (and committed!), then start writing tests[2]. Once you’re happy with the structure and coverage of your code, you commit again and then push it to your peers[3].
The crux of my revelation is this: you get the benefits of TDD-as-a-design-activity by doing it. When you do it is immaterial. You just have to do it.
My own revelation is blindingly obvious in retrospect. If the going gets tough, proceed in this order: get it to work, write some tests for it, then clean up the code. Sometimes you can break this cycle if what you’re working on doesn’t take too much cognitive capacity. But if you overflow your mental buffer, you have to break it down into steps and work through the cycle. Failing to realize this was one of the causes of me bogging down in TDD.
Context is everything. Always.
Adding context to answer the question of when you start writing tests is something I haven’t found much writing on until recently. I’m increasingly finding that considering the situation is a great ninja-move in my quest towards writing beautiful, useful code.
fn1. Call it a test, example, behavior, or story. Whatever.
fn2. Jim Weirich did a great presentation on how to backfill tests on existing code.
fn3. Pardon the Git-centric terminology[4].
fn4. If you are not already, please start using Git immediately.
Meaningful work
Just like being awake is more than just having your eyes open, going to work should be more than just being at a workplace trading time for money. It should be meaningful. But where does meaning come from? Of course, it comes from ourselves. We put meaning into things, and share our meanings with others, and teach each other how to build meaning out of what is in front of us.
Buster’s on to something here. He’s articulating one of the qualities I find in the best developers: what they do has meaning and matters to their personality. They are working to make things that result in greater happiness for themselves and others. Their passion is manifest in the quality of their code.
You should also check out Buster’s personal site. He’s got a neat info-graphics, personal data-mining thing going on there.
How did SQL get so popular?
Many developers, especially of the younger generation, dislike relational databases and their business-partner, SQL. It is regarded by some as the new assembly language. With all this distaste going around, how did it gain such a strong foothold in industry?
I offer you two answers: ACID and surface area.
ACID
Atomicity, consistency, isolation and durability. It’s not something most folks want to think about. To a rookie developer, it’s overwhelming. They’re not yet familiar with the semantics of the systems their programs run upon. Is fread
thread-safe? “How should I know, I just learned C last semester and about fread
’s parameters last week!”
The promises of a modern relational database include a compelling bullet point: your data is safe with us. Use our APIs, don’t break the rules, and we will make sure you never blow away some data and get a call at 3 AM. Rather, the DBA will, but what do you care about that guy?
So I submit to you that most programmers don’t use databases because they’re great. Rather, they have come to rely upon them because the canonical tome on transactions is heavy enough to maim small mammals and rife with formalisms. So they skip the nine-hundred page textbook and pick up the six-hundred page O’Reilly book.
Surface Area
Most programs that people will pay you to write involve side-effects. Further, many of those side-effects have to do with saving data off so you can perform further side-effects on it in the future.
The rookie developer typically leans first to files. Files are familiar and pervasive. But files leave a lot to said rookie. How should I structure my data? How do I load and save the data? How do I manipulate the data once it’s in memory? Even in scripting languages, with their simplified APIs, this means the rookie is faced with APIs like this:
fopen
fread
fwrite
seek
fclose
encode
decode
hash_set
hash_get
When I was bit a wee lad o’ programming, I found this Gordian knot difficult to cut. But then, one day, I was told by a programmer of greater wisdom to use a database. That API looked like this:
connect
execute
fetch
next
select
insert
update
delete
It was a lot easier to understand, even though the last four are a completely different language.
So, I submit to you, that SQL also won because it was easier to understand how one might structure their programs, make them work and, if they’re lucky, get them to run quickly.
Inflection point
I’d wager that five years from now, the generation of developers who are now upcoming won’t take the database tier for granted. Key-value stores, distributed file systems and document databases will all play into the question of “what do we do with the important data?” Sometimes, relational databases will prove useful. But increasingly, other things will too.
In the end, there’s two ways to look at this: we will soon throw down the shackles of our relational overlords, or, prepare yourself for the database renaissance in programming fashion that will occur in a decade or so.
Everyone wins!
Put your objects in space
Space-based Architecture - on building and scaling your system with a tuple space, the kissing cousin of the messaging queue. I didn’t know that tuple spaces are used much in finance apps, but I’m not surprised. They’re a worthy idea.
A console for any Ruby project
I’ve been finding this little snippet extremely useful lately:
$ irb -Ilib -rmy_library
If your Ruby app or library follows the idiom of requiring all the files for your app in a file named after the library, this will load everything up. If you’re being clever, you may need to invoke said cleverness before you can really get started poking around.
Anyone doing something similar?
Elevating the art of language implementation
Suppose we can take the following statement as true:
Whether you use it or not, the state of the programming craft has been elevated by many of the ideas bundled in Ruby on Rails.
ActiveRecord in particular brought many ideas that made it easier for more people to program with a database. Whereas before most people thought in terms of mappings or extracting data from hashes, AR gave a more fluent and object-like notation to work with. Thus, more interesting applications were born.
Right now, good VM technology is limited to Sun and Microsoft, while Apple, Google and Mozilla are re-inventing it for their web browsers. Open source languages, mostly, lack this VM technology.
ActiveRecord improved the state of the programming craft by spreading ideas that make working with a database easier. Could a similar improvement in the programming craft be realized by diffusing the knowledge of how to implement a good VM through a library? Is this a worthwhile aspiration?
When technical discussions get intense
Pro-tip: trying to unwind contentious technical discussions is a losing game. There are really multiple things going on: people discussing trade-offs in absolutes, personal vendettas being aired, missing tact filters and turf protection. If you’re lucky, there’s also some useful information hidden in the turd tossing.
Solution: don’t read too deeply, go do something useful instead.
Bonus tip: talking it out, face to face, over good drinks in a nice environment is “something useful”.