Codeulate.

How I’d Improve The CFP Process

If I were running a conference, here’s how I’d approach the talk selection process:

  1. Skip the call for proposals entirely.
  2. Advise those interested in speaking to prepare a video of the first three minutes of their talk.
  3. Conference organizers do a first pass on the videos to weed out the weakest submissions.
  4. All registered attendees are asked to vote on the remaining videos.
  5. After votes are tabulated, the top N speakers are offered the chance to present their full talk at the conference.
  6. Speakers that didn’t make the cut can choose to run small breakout groups after the main event.

I think this approach is superior to the standard CFP process for the following reasons:

  1. It allows for the evaluation of speakers on their speaking, rather than their ability to write a proposal. Imagine your results if you hired someone based solely on the writing quality of their cover letter. You’d end up with a strong writer, but would likely discover that writing skills and day-to-day job performance are only somewhat correlated. So it goes with talk proposals. Conference organizers sometimes accept intriguing proposals only to discover that the speaker does not have the ability to present a compelling talk on that topic.
  2. It lets the audience choose the topics that will be covered at the conference. Each year, conference organizers must guess which subjects will be most useful to their attendees. Why guess when you can collect just-in-time data?
  3. It is relatively unbiased against new speakers. In the normal CFP process, inexperienced presenters are often edged out by their better-known peers (particularly if they are friends of the organizers). It requires a leap of faith to accept a rookie’s talk without any proof that they’ll do it justice. Under my system, new and experienced speakers alike must both prove they’re prepared to do a great job.
  4. It leverages the wisdom of the crowd. It seems likely that 300 attendees in aggregate will make more informed decisions than a small handful of already overworked organizers.
  5. It’s easier on those running the conference. Organizationally, certainly; but also socially. If the talks at a conference are of poor quality, it’s natural to blame the organizers. But if the attendees as a group selected the speakers, they are more likely to empathize with the difficulty of predicting speaking success. Moreover, the attendees would likely be biased to consider the speakers to be better quality than they were, rather than face the cognitive dissonance of having chosen bad speakers.

Possible drawbacks of this approach include the following:

  1. It may be harder to market a conference with no pre-announced speakers. LessConf can sell out without telling anyone who will speak, but this seems to be an exception. Perhaps my approach would pair well with choosing a few anchor speakers who are guaranteed slots. This retains most of the advantages above while ensuring that organizers have some big names to announce.
  2. It’s unlikely to address a lack of diversity amongst speakers. Organizers must often work to ensure that minority groups are sufficiently represented in the final list of selected speakers. Like the first issue, this could be addressed by having a small group of (diverse) pre-selected speakers.

What say you, conference organizers? Any interest in giving this a shot? Have I missed any potential drawbacks?

Note: I made some significant changes to my proposed process based on feedback from the commenters below. Thanks to all of you for the ideas!

A criticism of DHH’s post on Dependency Injection

DHH’s latest post on DI is bad writing and thinking, and I’m concerned about its effects on the Ruby community.

Through much trial and error, I’ve learned that every programming concept has advantages and disadvantages; nothing is purely good or bad. Global data can be good. Reducing duplication can add the cost indirection. To present anything as purely one or the other tends to be the realm of novices who haven’t yet grasped the subtleties involved. Worthwhile discussion of programming ideas takes a fairly neutral view, and focuses on tradeoffs.

The problem with David’s post is that it does the opposite. Here’s his coverage of the benefits of dependency injection:

“As has unfortunately happened with a variety of patterns that originate from rigid languages like Java, Dependency Injection has spread and been advocated as a cross-language best practice on trumped up benefits of flexibility and malleability. If your code never knows exactly who it’s talking to, it can talk to anyone! Testing stubs, mocks, and future collaborators. Hogwash.”

This is not analysis, it’s wholesale dismissal of the points that don’t match his opinion. This would get you a D in a freshman analytical writing class.

Later:

“Of course, this runs counter to another Java-derived principle to only mock types you own. Combine that with an affinity of dependency injection and the simplest thing that could possibly work is no longer not just good enough, it’s disgusting. It violates the doctrine that has been so carefully assembled.”

Ah, the ol’ switcheroo. The OTHER side has been indoctrinated and refuses to examine the tradeoffs it’s making. Unlike us, the enlightened, who know that the other guys are wrong, and need not discuss their arguments.

There’s plenty of bad writing on the internet, and I don’t usually consider it worth the time to call it out. But David is a tremendously influential character in the Ruby world, and I’m concerned that this dysfunctional approach to discussion will prove contagious. It’s particularly dangerous for newcomers, for whom a rule they can always follow seems like a life raft in a sea of uncertainty. Sadly, it will do them more harm than good.

I hope David continues to share his thoughts about Ruby. When an experienced and successful programmer speaks, I’ll always listen. But I’d love to see this faulty means of discussion deprecated, extracted to a gem, and then removed entirely.

Depend Upon Abstractions

One nice piece of advice for designing flexible programs is depend upon abstractions, not implementations.

This is the idea behind the extract class refactoring. You package up some set of data and functionality, and only allow clients to interact with it through a public API. The class’s internal workings are intentionally hidden.

This tends to lead to flexible designs because implementation details can be changed without affecting any of the calling code. Changes are kept to just one file, which makes them easier, and ease of change is the best test for good design.

Most programmers are at least somewhat familiar with this idea. However, it’s easy to forget it when you start working with outside libraries or services.

Here’s a paraphrased example from a Rails app I reviewed recently. This app uses the braintree gem to charge users, create subscriptions, and refund money.

# Gemfile
gem 'braintree'
# app/models/user.rb
class User
  SUBSCRIPTION_AMOUNT = 10.to_money

  def charge_for_subscription
    Braintree.charge(SUBSCRIPTION_AMOUNT)
  end

  def create_as_customer
    Braintree.create_customer(user.name)
  end
end
# app/models/refund.rb
class Refund
  def process!
    Braintree.refund(order.amount, user.braintree_id)
  end
end

Just because we’re calling methods in another class does not mean we’re programming against an abstraction. It’s certainly better than making raw HTTP calls to Braintree, but our choice of vendor and gem used are implementation details that have leaked into our business logic.

With calls to Braintree littered throughout, switching to another vendor will require the editing and re-testing of many files. We’ve fallen short of the ideal we described above, where one change requires edits only in one place.

Fortunately, the fix is quite easy: a simple wrapper.

# app/models/user.rb
class User
  def charge_for_subscription
    PaymentGateway.charge_for_subscription
  end

  def create_as_customer
    PaymentGateway.create_customer(user.name)
  end
end
# app/models/refund.rb
class Refund
  def process!
    PaymentGateway.refund(self)
  end
end
# New file: lib/payment_gateway.rb
class PaymentGateway

  SUBSCRIPTION_AMOUNT = 10.to_money

  def charge_for_subscription
    Braintree.charge(SUBSCRIPTION_AMOUNT)
  end

  def create_customer(customer_name)
    Braintree.create_customer(customer_name)
  end

  def refund(refund)
    Braintree.refund(refund.order_amount, refund.user_braintree_id)
  end
end

Another good name for the new class would be PaymentGatewayAdapter, as it’s an example of the adapter pattern.

This code is only subtley different, but yields significant benefits:

  1. Switching from Braintree to another vendor now requires edits to only one file. If this change is somewhat likely, this benefit alone probably justifies the refactoring.
  2. If Braintree changes its public API, we again have only one class to edit.
  3. Testing has become easier. PaymentGateway gives us what some people call ‘seams’: a place where components join together where we can easily stub behavior. Before, unit tests required stubbing Braintree’s code. Upgrading the gem could potentially break many tests. Now, we can stub our own methods, which is safer.
  4. We can use method names that better match our problem domain. A small win, but a pleasant one.
  5. We can change the parameters that PaymentGateway’s methods expect, such as we did in PaymentGateway#refund.
  6. We have a better home for constants like SUBSCRIPTION_AMOUNT and similar data.

The only downside I can think of for this code is that it adds a bit of indirection. You’ll have to jump through one additional file to found out how customer charging is implemented. However, the wrapper is very thin, so I don’t think this cost is large.

It’s easy to accidentally find yourself depending on implementation details. External libraries and services are frequently sources of this, and warrant extra suspicion. Implementations that have a decent likelikhood of change should always be wrapped in sanitary fashion.