You’re reading Signal v. Noise, a publication about the web by Basecamp since 1999. Happy !

David

About David

Creator of Ruby on Rails, partner at 37signals, best-selling author, public speaker, race-car driver, hobbyist photographer, and family man.

Your life’s work

David
David wrote this on 25 comments

I’d be happy if 37signals is the last place I work. In an industry so focused on the booms and busts, I find myself a kindred spirit with the firms of old. Places where people happily reported to work for 40 years, picking up a snazzy gold watch at the end as a token of life-long loyalty.

Committing myself to this long-term focus has led to a peaceful work atmosphere and an incredible clarity of purpose. If this is the last job I’ll ever have, I damn well better make sure that I like it. I won’t just tough things out. If shit is broken, we’ll fix it now, lest we be stuck with it for decades.

Two key ideas help inform this dedication. The first is Alistair Cockburn’s metaphor of software development as a co-operative game. Focusing on the residue of knowledge and practices carried over from game to game is far more important than worrying about the output of any one game.

Working people to death to ship any one feature or product is a poor strategy, as it reduces the capacity to ship the next feature or product (burn out, build-up of bad rush practices). It’s far more important to have a system for shipping that improves over the long term than one that heroically manages one monster push.

Second is Jeff Bezos’ idea: “What’s not going to change over the next 10 years?” If you’re going to stick around for decades, you’re better off making investments in things that’ll pay off for a very long time. It applies both to software and peopleware.

Of course, not everyone is at a stage in their life where they’re willing to settle down with a job for decades. But I find I enjoy working most with the people who are.

If you’re not committed to your life’s work in a company and with people you could endure for decades, are you making progress on it?

Winning is the worst thing that can happen in Vegas

David
David wrote this on 30 comments

There’s nothing more appealing than thinking you’re just that good. Our brains are optimized for fondly remembering our successes and quietly downplaying our failures.

The casinos in Vegas are primed for this by making it relatively likely you’ll win something early on. By the time you realize that the slight edge of the house means over the long run it’ll win everything back and more, well, you’ve probably spent more than your first ATM stop and then some.

Future coding is a lot like playing the roulette. If you can guess where the requirements of tomorrow will land today, you’ve just scored the ultimate programmer’s prize: looking like a wizard. You saw the future and you were right! High five, brain!

That’s the almost irresistible draw of “flexibility”—often just a euphemism for building half or whole features before you know how they’re supposed to work or whether you need them. Just like in Vegas, the worst thing that can happen is to be right about this once in a while.

Because like the casinos, the house of program complexity will take all your little bets on the future and add them up until you just don’t know how this damn program got so deep into technical debt!

Running up the debt on your code is not just about the quick hacks and dirty commits you know you really should clean up (but just don’t). No, the far more insidious kind of debt is that acquired in the name of “flexibility”.

Every little premature extraction or abstraction, every little structure meant for “when we have more of this kind”, every little setting and configuration point for “things we might want to tweak in the future”. It all adds up, and at a dangerous rate.

The road to programming hell is paved with “best practices” applied too early. Very few abstractions, extractions, or architectures are inherently bad (although I’ll contend that a few are). But most of them are downright evil if applied before they’re called for.

To take the scare quotes off flexibility, you have to be willing to write no code at all. The “Simplest Thing That Could Possibly Work” and “You’re Just Not Going To Need It” are both sayings to help you get there.

This really does mean not a single parameter to a method that has not yet found a use. No needless public methods that might get reused later (not even for testing!)

The hardest—and yet most important—thing in the world of design is the conviction to say no.

Everything is not equally good

David
David wrote this on 17 comments

When talking shop, there’s a natural tendency to avoid the drama of confrontation by relegating all disputes to Your Mileage May Vary. If we can declare all approaches and techniques to be of value only “under certain circumstances”, then we can avoid the hard work of finding the better alternative and merely stop at different.

I don’t think this serves anyone. Well, that’s not entirely true. It supports the ego of the person proposing the bad idea. It also helps the ego of anyone who bought into it. But it doesn’t help the world move forward to hoist up every bad idea as “just another option”.

Of course, you can’t stop this from happening. Not least because people differ on what’s a bad idea. And that’s fine! There will always be different groups advocating for different things. But as individuals, we shouldn’t be afraid to impart our opinion on ideas.

Ideas are meant to be attacked, torn apart, and put back together again. You may well want to shield your idea from the harsh sunlight at first, but by the time it’s ready to meet the world, it should also be ready for rain or shine. Bad ideas are supposed to wither under the stress of criticism.

Hell, even good ideas are supposed to wither in the winter of their life. Precious few ideas are immortal, and even those should be constantly tested to ensure their hearts still beat vibrantly.

The reason we get rid of bad ideas is to make room for new ones. If your catalogue of techniques is brimming with YMMV charity cases, you’re less likely to come up with or entertain new entrants. Hoarding bad ideas that might come in handy when the full moon shines purple is just that. Hoarding.

The flow of new ideas is far more important. Throw ‘em up, bat ‘em out. Declaring “oh well, that didn’t work out like I thought” is an incredibly liberating feeling. I might even go as far as to say it’s motivating. It’s like clearing your desk or emptying your inbox. Ahh, a fresh start!

It takes a strong ego to let go of bad ideas that you originated, but rarely people will think less of you for it. Which is more than can be said of clinging endlessly to bad ideas past their due.

The five programming books that meant most to me

David
David wrote this on 28 comments

There are so many programming books out there, but most focus on specific technologies and their half-life is incredibly short. Others focus on process or culture. Very few focus on the timeless principles of writing good code, period. The following five books had the biggest influence on my programming style and development:

  • Smalltalk Best Practice Patterns: Incredibly practical advice for what constitutes good OO code. It’s done in Smalltalk, but the principles are mostly universal. Probably my favorite nuts’n’bolts of programming design book. Very granular.
  • Refactoring: The fundamental before/after book. Here’s some code that could be better, here’s how to make it better. The trick to reading this book is to carefully read through every single refactoring pattern and then try to apply it on your code base (you don’t have to commit if it doesn’t fix things). You can’t just blow through it or you won’t really learn it. And you can’t just say “oh, I’ll look up a refactoring when I need it” — because then you don’t know what to look for.
  • Patterns of Enterprise Application Architecture: Great inventory of many of the patterns that underpin Rails itself, as well as descriptions of many of the “new” approaches that people advocate today (like transaction scripts and service layers). You won’t necessarily implement most of these patterns yourself, but it’s an invaluable resource to understanding the differences in architectures and why framework work the way they do. (Funny anecdote: before I created Rails, I redrew many of the diagrams in OmniGraffle for Martin Fowler because I liked the book so much.)
  • Domain-Driven Design: This is probably the least readable book of the bunch. It’s a slug to work through, but the ideas are worth it. It’s a great primer on how to turn a problem space into a beautiful OO domain model. What should your models be called? What logic goes where? How do we reproduce reality into an object model.
  • Are Your Lights On?: This isn’t technically a programming book, but it deals with the biggest problem facing developers none the less: What is the problem we’re trying to solve? Is it the right problem? Could we solve a different problem instead and that would be just as good? Nothing has increased my programming productivity more than being able to restate hard problems as simple ones.

If you consider programming to be a subset of writing, and I certainly do, then you would also do well to read Elements of Style and On Writing Well. I’ve found reading those made me a better programmer as well.

Reading these five to seven books will give your programming chops more vitamins and nutritional value than a couple of year’s worth of blog posts and tutorial.

Getting hyper about hypermedia APIs

David
David wrote this on 56 comments

Using URLs instead of ID references in your APIs is a nice idea. You should do that. It makes it marginally more convenient when writing a client wrapper because you don’t have to embed URL templates. So you can do client.get(response[:person][:url]) instead of client.get("/people/#{response[:person][:id]}"). But that’s about it.

The recurrent hoopla over hypermedia APIs is completely overblown. Embedding URLs instead of IDs is not going to guard you from breakage, it’s not going to do anything materially useful for standardizing API clients, and it doesn’t do much for discoverability.

Preventing breakage
According to hypermedia lore, you will be able to willy nilly change your URLs without needing to update any clients. But that’s based on the huge assumption that every API call is going to go through the front door every time and navigate to the page they need. That’s just not how things work.

If I want to request a message off a project in Basecamp, I would have to do something like this GET /projects, GET /projects/1, GET /projects/1/messages, GET /projects/1/messages/2. That’s great for the first fumbling in the dark discovery, but it doesn’t work as soon as I bookmark that last URL because I want to send comments to it later.

Just like bookmarks in the browser break if you change the URL, so will any client that’s stored a URL for later use.

Because breaking URLs is such a bad idea, people tend not do it. If you look at the successful APIs on the web, they’ve stayed remarkably stable because that’s the best way to prevent breakage. Like the W3C says: Cool URIs don’t change. Which means this isn’t much of a problem in the wild and even if it was, hypermedia APIs would still have big holes with direct links break.

Enabling discoverability
Good API docs explain what all the possible attributes of a resource are. They explain the possible values of those attributes. The options available and so forth. Thinking that we can meaningfully derive all that by just telling people to GET / and then fumble around to discover all the options on their own just doesn’t gel with me.

How do I know that the data I happen to be stumbling across includes everything that’s possible to do? What if the project I request doesn’t have any documents attached with it? How do I know how to find those and how to add new ones?

Standardizing API clients
The idea that you can write one client to access multiple different APIs in any meaningful way disregards the idea that different apps do different things. Just because there’s a standard way to follow a resource to a sub-resource doesn’t mean that you can just write one generic client that then automatically knows how to work with any API.

Any generic API will not know what to do with the things it get. It won’t know the difference between Flickr photos and Basecamp projects. The assistance of being able to follow a link to go from photo to comments and project to messages is nice, but as explained in the beginning, not exactly earth shattering.

Every single application is still going to need a custom API client. That client needs to know what attributes are available on each resource and what to do with them.

In summary, here’s a low-fi solution to these three problems that doesn’t require a spec or involving the IETF:

  1. Don’t change your API URLs.
  2. Document your API.
  3. Provide a custom client wrapper (you’ll have to write one anyways).

On top of that, be a chap and use URLs in IDs because convenience is nice and it doesn’t take too much effort if you’re using something like jbuilder anyway. But don’t go thinking that you’ve magically solved all these problems just because you did.

We’ve been down this path to over-standardization of APIs before. It lead to the construction of the WS-deathstar. Let’s not repeat the same mistakes twice. Some times fewer standards and less ceremony is exactly what’s called for.

Put chubby models on a diet with concerns

David
David wrote this on 47 comments

Different models in your Rails application will often share a set of cross-cutting concerns. In Basecamp, we have almost forty such concerns with names like Trashable, Searchable, Visible, Movable, Taggable.

These concerns encapsulate both data access and domain logic about a certain slice of responsibility. Here’s a simplified version of the taggable concern:

module Taggable
  extend ActiveSupport::Concern

  included do
    has_many :taggings, as: :taggable, dependent: :destroy
    has_many :tags, through: :taggings
  end

  def tag_names
    tags.map(&:name)
  end
end

This concern can then be mixed into all the models that are taggable and you’ll have a single place to update the logic and reason about it.

Here’s a similar concern where all we add is a single class method:

# current_account.posts.visible_to(current_user)
module Visible
  extend ActiveSupport::Concern

  module ClassMethods
    def visible_to(person)
      where \
        "(#{table_name}.bucket_id IN (?) AND
          #{table_name}.bucket_type = 'Project') OR
         (#{table_name}.bucket_id IN (?) AND
          #{table_name}.bucket_type = 'Calendar')",
        person.projects.pluck('projects.id'),
        calendar_scope.pluck('calendars.id')
    end
  end
end

Concerns are also a helpful way of extracting a slice of model that doesn’t seem part of its essence (what is and isn’t in the essence of a model is a fuzzy line and a longer discussion) without going full-bore Single Responsibility Principle and running the risk of ballooning your object inventory.

Here’s a Dropboxed concern that we mix into just the Person model, which allows us to later to route incoming emails to be from the right person:

module Dropboxed
  extend ActiveSupport::Concern

  included do
    before_create :generate_dropbox_key
  end

  def rekey_dropbox
    generate_dropbox_key
    save!
  end

  private
    def generate_dropbox_key
      self.dropbox_key = SignalId::Token.unique(24) do |key|
        self.class.find_by_dropbox_key(key)
      end
    end
end

Now this is certainly not the only way to slice up chubby models. For Visible concern, you could have Viewer.visible(current_account.posts, to: current_user) and encapsulate the query in a stand-alone object. For Dropboxed, you could have a Dropbox stand-alone class.

But I find that concerns are often just the right amount of abstraction and that they often result in a friendlier API. I far prefer current_account.posts.visible_to(current_user) to involving a third query object. And of course things like Taggable that needs to add associations to the target object are hard to do in any other way.

It’s true that this will lead to a proliferation of methods on some objects, but that has never bothered me. I care about how I interact with my code base through the source. That concerns happen to mix it all together into a big model under the hood is irrelevant to the understanding of the domain model.

We’ve been using this notion of extracting concerns from chubby models in all the applications at 37signals for years. It’s resulted in a domain model that’s simple and easy to understand without needless ceremony. Basecamp Classic’s domain model is 8+ years old now and still going strong with the use of concerns.

This approach to breaking up domain logic into concerns is similar in some ways to the DCI notion of Roles. It doesn’t have the run-time mixin acrobatics nor does it have the “thy models shall be completely devoid of logic themselves” prescription, but other than that, it’ll often result in similar logic extracted using similar names.

In Rails 4, we’re going to invite programmers to use concerns with the default app/models/concerns and app/controllers/concerns directories that are automatically part of the load path. Together with the ActiveSupport::Concern wrapper, it’s just enough support to make this light-weight factoring mechanism shine. But you can start using this approach with any Rails app today.

Enjoy!

500px _ Photo _Impact rising_ by David Heinemeier Hansson.jpg

500px does nothing new, it just does everything a little better, a little cleaner, and a little clearer. It’s not complicated, but it’s really hard to do.

Pattern vision

David
David wrote this on 16 comments

Design and programming patterns are wonderful ways of disseminating knowledge. It’s immensely satisfying to bring solution to a tough problem by applying a perfect-fit pattern.

But success with pattern applications is like taking that first innocent bump. You quickly want more of what made you feel this good. And buoyed by the high of a perfect fit, it’s easy to develop pattern vision where code, like Tetris shapes, become mere blocks for fitting into the pattern holes.

With this infliction, you will invariably drift away from the original intent of making specific and immediate pain go away. Where the perfect and legitimate fit will remove a thorn that’s obviously hurting the code right now, the speculative fit pretends to do the same for future hurts.

Now that’s an honorable intention. A pinch of prevention over a pound of cure, right? Only, it rarely works out like that. Speculative pattern applications to avoid future, possible ails is a form of fortune telling. It’s the reason YAGNI was coined.

The further down this rabbit hole you go, the farther away from practical improvement you’ll end up. Go deep enough and the pattern vision turns into articles of faith. Inheritance is always bad, only composition can be our true savior! Only standalone command objects can give us the reusability this application needs!

Turning patterns into articles of faith takes them out of the realm of rational discussion. Code either adheres to the holy patterns or it doesn’t. If it does not, the programmer must first repent, say his 25 rose-delegations, and then swear never to let an opportunity for a policy object extraction pass by him again!

The naming of many design principles supports this theological world view that patterns also at times inhibit. It’s obvious that you’re a sinner if you break The Law of Demeter and of weak will if you forgo the Single Responsibility Principle.

Patterns are best thought of like helpful guidelines and suggestions, not laws, not imperatives. It’s a written account of “hey, if you have this problem, you can try this thing to make it better”. Their core value is transforming some code to better code in a way that’s immediately obvious to the writer.

Evaluating such improvement is easy. You look at the code you had before applying the pattern and after it. Did it make the code simpler to understand? Clearer? Prettier? If you can’t easily see whether that’s so, you’ve been sold.

Cities with signals

David
David wrote this on 28 comments

The 36 people of 37signals have lived and worked from the following cities during their time at the company:

  • Ann Arbor, Michigan
  • Austin, Texas
  • Bangkok, Thailand
  • Belleville, Illinois
  • Boulder, Colorado
  • Buffalo, New York
  • Caldwell, Idaho
  • Cambridge, United Kingdom
  • Chicago, Illinois
  • Copenhagen, Denmark
  • Durham, North Carolina
  • Edmond, Oklahoma
  • Fayetteville, Tennessee
  • Fenwick, Ontario
  • London, United Kingdom
  • Malibu, California
  • Malmö, Sweden
  • Manchester, United Kingdom
  • Marbella, Spain
  • Moscow, Russia
  • Mufreesboro, Tennessee
  • Parksville, British Columbia, Canada
  • Pasadena, California
  • Phoenix, Arizona
  • Pittsburgh, PA
  • Portland, Oregon
  • Provo, Utah
  • Rapid City, South Dakota
  • San Diego, California
  • Saratov, Russia
  • Solana Beach, California
  • Tampa, Florida
  • Tempe, Arizona
  • Vancouver, Canada
  • Vineland, Ontario

If we had limited ourselves to only looking within a commuter’s distance of the Chicago office, we would have missed out on a lot of great people.

Publishers shouldn't be app developers

David
David wrote this on 24 comments

The ease with which you can write software for the web is an anomaly. It’s an incredibly forgiving medium and the barriers to entry are unnaturally low. It hardly takes any craftsmanship at all to connect a web form to a database and have it work well enough to publish content.

Outside of this anomaly, software development is generally hard. Magazine and newspaper publishers around the world are finding out just how hard as they all rush to bring their wares to native apps on iOS, Android.

These magazine apps completely suck, generally speaking. They suck in the same ways that the CD-ROM rush of the 90s sucked. They suck for all the reasons poorly written native software sucks: They’re slow, they crash, they get stuck.

It’s like every magazine is reinventing HTML and programming their own browser for it. Of course that’s going to end badly!

The solution when it hurts to hit yourself is to stop hitting yourself. Custom app development to publish a magazine is just nonsense.

Apple should save its customers from these cruddy experiences by either putting out something like iMagazine Creator (ala iBooks Creator) or find a better way to get existing HTML magazines on the iPad.

Reading magazines on the iPad is too good of a use case to have it screwed up by this rash of crappy native apps.