This is Anti-pattern—thoughts on programming and whatnot by Brandon Weiss.

Canary

July 28, 2013

For the last few months I’ve been working on something new. I live and work on the Internet, so it’s very important that my various websites, web apps, and whatnots are all up and working properly. That moment when you realize that something is broken, that it’s been that way for hours—or even longer—and you had no idea, sucks.

There are a few different products and services that attempt to solve this problem, but they’re either really difficult to use, ridiculously expensive, or in most cases, both. These products are all targeted at large businesses, and although I might not be large, I am a business. I want to know when things go wrong, but I don’t want to have to pay $50+ a month to know it. I don’t want to be up-sold for every basic feature. I don’t want to wait days for help and talk to an unhelpful robot when I finally get it. I don’t think it’s unreasonable to expect to pay a fair amount every month for a great product made by great people. So I’m building the product I want.

It’s called Canary. Right now it will ping URLs and let you know when they go down and when they go back up. I’ve teamed up with my friend and co-founder, Avand. We’re starting small and plan to work our way up; we’ve got some really awesome features planned.

If you’re ready to know when things go wrong before anyone else does, sign up for Canary.

Tales from the BCrypt

June 18, 2013

Update: Of course, not even three weeks after writing this bcrypt-ruby was finally updated to support externally setting the cost.

# test/test_helper.rb
BCrypt::Engine.cost = BCrypt::Engine::MIN_COST

BCrypt is the gold standard for password hashing. It’s different from the algorithms that came before it in that it’s designed to be slow. Slow is not generally considered to be a feature of good algorithms, but as computing power increases, brute-forcing a hashing algorithm takes less time, so making the algorithm slower makes the hashes it generates more secure. A slower algorithm will impact normal application usage very little—like users signing up or signing in—but exponentially increases the time it takes a password to be brute-forced. BCrypt is the easiest and most secure way to hash password.

One often-overlooked side-effect of using BCrypt is that because of how it works it makes your test suite slow. Your test suite probably creates a lot of users, authenticates with your app, and exercises the parts of your code using BCrypt a fair amount. All those extra milliseconds add up.

Fortunately, BCrypt allows you to lower the cost (time) of hashing a password. The default cost is 10, but you can lower it as low as 4. The easiest way to do this and what everyone recommends is to just override the DEFAULT_COST constant in your test helper.

# test/test_helper.rb
BCrypt::Engine::DEFAULT_COST = 4

BCrypt also has a MIN_COST constant that can be used instead of hardcoding the number.

# test/test_helper.rb
BCrypt::Engine::DEFAULT_COST = BCrypt::Engine::MIN_COST

Lowering the cost makes my tests run about 50% faster. Your mileage may vary, but you should see a marked improvement.

Now, you may have noticed a warning in your test output.

/Users/brandon/Code/canary/api/test/test_helper.rb:8: warning: already initialized constant DEFAULT_COST

Ruby understandably doesn’t like it when you override constants. It will let you but it will complain about it. I’ve been doing this for a few years and it never bothered me, but that’s because my test output was so long it pushed the warning off the screen. Today I switched my test output to be more concise and now the warning is eyeballing me every time I run the tests. It’s watching me. Watching and judging.

I ran my tests five or six more times before I couldn’t take it anymore and opted to finally fix it. BCrypt allows you to specify the cost when hashing a password, so the fix is simply to define your own default cost within your application, set it to the value you want or let it fall back to BCrypt’s default cost, and then pass the cost in as an option when hashing the password.

# app/models/user.rb
require "bcrypt"

class User

  include BCrypt

  def password=(new_password)
    @password_hash = Password.create(new_password, cost: self.class.bcrypt_cost)
  end

  def self.bcrypt_cost
    @bcrypt_cost || BCrypt::Engine::DEFAULT_COST
  end

  def self.bcrypt_cost=(cost)
    @bcrypt_cost = cost
  end

end

# test/test_helper.rb
User.bcrypt_cost = BCrypt::Engine::MIN_COST

Use Bundler.setup Instead of Bundler.require

March 12, 2013

About two years ago I recommended using Bundler.require instead of Bundler.setup to automatically require and load gem dependencies. And in the spirit of changing my mind often I’m completely reversing my stance; using Bundler.setup is significantly better than Bundler.require.

The original reason I thought using Bundler.require was better was just a variety of bad habits leftover from Rails. Over the years Rails has changed a lot in how it handles dependencies. Gems used to be manually required, then were automatically required via Bundler. Code in the app folder has always been automatically required, and up until relatively recently so was code in the lib folder. The general message was and still is pretty clear; Rails implicitly—if not explicitly—discourages manual requiring. Over time this led me to the erroneous conclusion that manually requiring dependencies was repetitious and unnecessary. Why do something manually that can be done automatically?

But as I’ve gotten better my opinion has shifted the other way. There are some huge benefits to using Bundler.setup to set up load paths for gems, adding application directories to the load paths, and then manually requiring dependencies wherever they are used in an application.

It provides amazing design feedback and documentation

Manually requiring dependencies at the top of every file very explicitly tells you and anyone else exactly what dependencies that file has. This makes code easier to read, understand, test, and refactor. It also makes it painfully obvious when a class is too complicated. If a class needs more than five require statements to work there’s probably too much going on in that class.

It forces you to think about your dependencies and the cost associated with using them

Dependencies aren’t free. Every dependency you have adds complexity and increases coupling. Automatically loading all dependencies makes them seem like they’re free and can be used whenever and wherever in your application. Having to manually require a dependency to use it forces you to justify its use and keeps your dependency list lean.

It makes removing dependencies easier

If you automatically load all your dependencies when you load your environment, you have no way of knowing what parts of your application are using any given dependency. You’d have to manually search for class names, method names, and other ways of identifying a dependency in order to update it or remove it, which is tedious and error-prone. If you manually require dependencies, you can just search for the require statement and remove or replace the dependency.


The big question at the heart of this all is what is your application? Is it one monolithic, tightly-coupled mess? Or is it a structured collection of small, loosely-coupled objects? Using Bundler.require will lead you towards the former, but using Bundler.setup will help ensure you make the latter.

Ship Now, Not Later

March 04, 2013

A few days ago I shipped a small project I’ve been working on called Arrival. It estimates arrival times for Apple products based on previous release cycles. Embarrassingly, this is something I’d been thinking about for the better part of two years, but it took until a few days ago for me to make it happen.

I first had the idea a few years back after I stumbled onto the MacRumors Buyer’s Guide and was shocked at how poorly it was designed and how terribly it visualized the data. I was sure I could do much better. So I spent a few days cranking out a rough version that was functional but lacked an amazing visual design. And that’s where I hit a wall. I think great design is imperative and there was no way I was going to ship a product that didn’t look amazing.

I spent the next two years sitting on it while I emailed designers to try and find someone to create the perfect design. Many expressed interest but most were ultimately too busy. Twice someone said yes and started working on it but dropped off as other things came up. Eventually I just gave up and shelved it, figuring I’d just meet the right person to work on it with eventually.

A month or two ago my friend Andy Keil reached out to me with an idea for an event called FinishUp Weekend. It’s the antithesis of Startup Weekend, the premise being that starting is easy, finishing is hard, so instead of starting something new let’s finish up the projects we already have. He asked if I’d be interested in going and I told him absolutely, and that I knew just what I was going to work on.

Two months later I flew down to Austin, met Andre Jurgensen (co-founder of Handsome) at the event and jammed it out over the next two days. I would love to say that the moment I told Andy I was going I had an epiphany and realized waiting for the perfect design was ridiculous, but the truth is, all through the weeks leading up to the event and even for a little bit while I was down there I debated whether or not I should ship it. It wasn’t until I met Josh Long, who came down to participate in the event and gave a small talk about Execute, a book he wrote—in three fucking days—that I realized how asinine I had truly been. If I’d waited to ship it until it was as perfect as I wanted it to be, I would never have shipped it at all.

The moment after I shipped Arrival was the best I’ve felt in a long time, and I already usually feel pretty good. The high I got from shipping it is better than any food I’ve ever eaten, any drink I’ve ever tasted, or any drug I’ve ever done. The first day Arrival received 30,000 hits, three days later it has received over 60,000 hits, and the feedback has been nothing but positive. If you have an unfinished project that hasn’t shipped yet because you’re still perfecting it and it doesn’t quite meet your expectations, remember that you’re the only thing standing in your own way. Stop fucking around and ship it.

Litany Against Distraction

November 02, 2012

I must not get distracted.
Distraction is the mind-killer.
Distraction is the little-death that brings total obliteration.
I will face my distraction.
I will permit it to pass over me and through me.
And when it has gone past I will turn the inner eye to see its path.
Where the distraction has gone there will be nothing.
Only I will remain.