The Path to Programming Greatness

There was a time when I thought the height of programming was the ability to take a problem, and solve it. Take an idea or a specification, and start writing code. Once the code does what you wanted it to do, you're done! Just keep learning about new frameworks and technologies to help you figure out how to get things done.

I think at that time I was in the "don't know how much you don't know" phase. I've since learned that being able to write code that matches a spec is only the first step in becoming a better programmer.

After you can write code, now you have to figure out how to write good code. Why does this matter? This has been discussed by greater minds than mine, but here are a few reasons why I think you need to always work to make yourself a better programmer:

  • Maintainability: If you come back to your code in a month (or a year, or 5 years), and your code is a mess, you can't assume you'll remember why you did everything the way you did.
  • Working with others: Even if you're able to remember what you've done and keep everything in your head straight (certainly not something I can claim about myself), when you start to add other people into the mix, you get problems. The larger the team grows, the more important it becomes that code is easy to understand and add to.
  • Growth: There are always going to be new features, or changes to existing features. Good code is flexible enough to handle this. If a change requires updating 50 different classes, or refactoring half the project, then the code is brittle. If developers aren't diligent, a project can quickly become unmanageable. Often at this point the team just throws up their hands and decides it's time for a "rewrite" -- something that drives fear into the hearts of managers.

I've found a few general ways to improve code:

  • Refactoring: Remember when I said that once the code did what it was supposed to do, I thought it was done? Now I've realized that this is just the beginning. What comes next is refactoring. I think a lot of people see code from great programmers and think that the code came straight out of their heads exactly as it reads on-screen. In my experience, even the great programmers start with ugly but workable code, and refactor from there. Usually we just get to see the end result.
  • Design Patterns: Think of these as "pre-built" solutions. When you look at a project as a whole, you probably won't find an existing solution that already does exactly what you need (otherwise, why would you be writing it?). But design patterns are a way to keep your code clean on the small to medium scale. The tricky part is knowing when to use them.
  • Testing: This is what makes the previous two concepts work. I used to think that tests existed mainly to catch bugs; either before they happen by testing complex code, or afterwards to prevent regressions. While I certainly saw the value in this, I found writing tests to be very difficult, and I questioned whether it was worth the time. What I realize now is that if writing a test is hard, it's often a sign that the code under test has problems. Code that is well factored and designed is easier to test. I now use tests as much for design as I do to catch bugs.

Those are the general concepts. But how do you get there? Over time I've kept a list of resources that I've found especially useful, and I'd like to share them here.

I've found that there's a sort of path that comes between the wide-eyed programmer who isn't even aware of these concepts, and the seasoned programmer:

  1. Step 1: The Basics. Learning the semantics of clean code, refactoring and testing.
  2. Step 2: Refinement. Design patterns and advanced testing concepts.
  3. Step 3: Limitation. Knowing what to use and when.

I think the last step is key; even if you were to learn all there was to know, you still wouldn't be a good developer until you knew when to use these principles, and when not to use them. Any of them can be taken too far: for example endless refactoring without making progress on features, or writing so many tests so that the codebase is dwarfed by the tests.

The resources below will help guide your learning at each step. Note that not all of these resources are specific to Ruby. While there are differences between languages, it would be a mistake to limit yourself only to the Ruby world. In particular, a lot of the concepts thought of as being core to Ruby come from Java in particular.

I also want to point out that by no means do I feel that I've reached the limit of my learning. In fact I think the great programmers are the ones who are always learning, questioning and improving themselves.

Step 1: The Basics

Books:

Articles & Videos:

Step 2: Refinement

Books:

Articles & Videos:

Step 3: Limitations

Books:

Articles & Videos:


Posted by Costa Walcott on 23 Feb 2013 in Programming.
Tagged: design patterns, refactoring, testing
View comments



Introducing stately: elegant state machines

Recently, I've been working on a new Ruby gem called stately, which aims to be a paired down, elegant, no-surprises state machine helper. It's still a work in progress, but I've used it successfully on one project so far.

A word on state machines

First, I should point out that I'm not always an advocate for state machines. I think they are overused (and abused). Typically, I prefer to err on the side of simply tracking state with a string on my ActiveRecord (or whatever) models and handling state transitions naturally, via methods and filters. However, there are plenty of situations where it makes sense to use a state machine. Stately is designed for those situations.

In many cases, it's convienient to setup an object that could be in one of multiple potential states such that by changing its state, it triggers one or more actions. For instance, let's define an object called Order (representing a customer's order at a pizza shop) as always being in one of three states: completed, invalid (i.e. the customer's credit card failed and we can't complete the order), and refunded (for the rare occasion when our pizza shop delivers an inferior pizza).

When an Order's state is changed, we want to trigger some helpful actions. The reason why we're interested in triggering actions in response to changing state on our Order object is that it allows us to cleanly separate concerns from the rest of our application. Consider the example where we are writing an application that splits off our credit card processing from other business logic:

class OrderCharger
  def initialize(order, credit_card)
    @order = order
    @credit_card = credit_card
  end

  def charge
    if charge
      order.complete
    else
      order.invalidate
    end
  end

  private

  def charge
    # complicated order charging logic here…
    # return true if it all succeeds
    true
  end
end

This is an example of an understated but beautiful pattern I use constantly that separates business logic into concrete, separate ruby ojects that are easily tested. Steve Klabnik calls this pattern the 'Plain Old Ruby Domain Object'. I plan on writing about this pattern in a future post.

Throughout our code, we may have a couple places where we need to charge a card and complete an order (say, on a web form when the user is done ordering, or through an admin panel where an employee can enter card details they get from a phone call). In both cases, we simply do the following:

OrderCharger.new(order, credit_card).charge

Digging into the object, we notice that we've cleanly separated any logic about what an Order needs to do to finish an order (or invalidate itself, should things go south) from the process of charging a customer's credit card. An Order isn't really concerned with the mechanics of charging credit cards and our OrderCharger doesn't really want to know all the messy details of what an Order needs to do when, say, a credit card fails. Instead, OrderCharger just tells the Order that it should be in either the completed or the invalid states and leaves it at that.

Stately defines the methods complete and invalidate on the Order object for us.

Introducing stately

Stately allows you to define some states on an object and setup transitions between those states. A transition is usually one or more methods you want to run whenever the object is going to transition into that state. For instance:

class Order
  stately start: :processing do
    state :completed do
      after_transition do: :email_receipt
    end
  end
end

The example above sets up an Order object with two possible states: processing, and completed. It also defines an instance method called complete on Order. Calling that method, as is done in OrderCharger above, will then do the following two steps (in order):

  1. Set the Order instance attribute state to be the string complete.
  2. Call the instance method email_receipt.

Having an after_transition is a handy feature for our example above, as it's the perfect place to let the customer know their pizza is on its way.

Following the pattern above, you can quickly define the states for invalid and refunded. Stately has an elegant DSL that tries hard to be self-documenting. As I mention in the README, a couple of the design goals behind the gem are:

  • Self-documenting so anyone can pick it up and know exactly what the transitions of a state are
  • No surprises. If your Order object was actually an ActiveRecord model, you would need an after_transition do: :save in order to persist the object's changes to your database (in our example, this would be the state column in the orders table).
  • Minimalist. Stately is about as simple as it gets and it tries hard to focus on the basics without getting into more complicated territory best reserved for more ambitious state machine gems.

Stately can do more than just handle transitions too. For instance, it has some handy validations that will prevent a state transition if certain preconditions aren't met.

Getting started

Stately is easy to get started with. First, be sure to check out the repo and read through the README. I've been adding examples and other documentation to get you up to speed quickly. But, here's a couple of quick pointers to get going on a Rails 3 project:

First, add stately to your Gemfile:

gem stately

Be sure to run bundle install to install the gem.

Second, find the object that you'd like to use Stately with, and add the following template:

stately start: :initial_state, attr: :my_state_attr do
  # ...
end

Your :initial_state is a symbol for the object's initial state, when the object is first instantiated (in our example, we used :processing). The optional attr: defines what the name of the attribut on the object is used to track state (the default is state). For instance, if you had an ActiveRecord model called Order, which had a single column called order_state, you would need to use attr: :order_state above.

Third, define each of your states. They can be simple, like:

state :invalid

You can also make them complex, like:

state :completed do
  prevent_from :refunded

  before_transition from: :processing, do: :calculate_total
  after_transition do: :email_receipt

  validate :validates_credit_card
end

Stately is designed to be intuitive and easy to understand, even by people who aren't otherwise familiar with the gem.

How to contribute

Stately is still a work in progress. If you're so inclined, there are a number of ways you can get involved in the development of stately:

  1. Use it and provide feedback. I built this gem to help solve a problem I've been having, but I want to hear how it has helped you (or how it could be improved). Leave a comment here, file a bug report, and submit pull requests.

  2. Refactoring. The gem needs to be cleaned up. I've been working on it, but there is still plenty more to do.

  3. Rethink how actions are derived given a state name. Right now, a hard-coded list of action names are used based on the state name, but there is plenty of room for improvement here.

  4. Help get the word out. I'd love to get as many opinions on this gem as possible, so the more the better.

Hope you found this helpful. Let me know what you think of the gem and any projects you're using it in.


Posted by Ryan Twomey on 04 Feb 2013 in gems.
Tagged: gems, ruby, design patterns
View comments



Staying consistent with Ruby style guides

Writing code for many years, there's one thing I prize above nearly all else: consistency. As a contractor, it's delightfully refreshing and unfortunately rare to jump onto a project where code followed a style guide (especially one that I roughly agreed with), and it noticeably decreased the time it takes to get familiar with the codebase.

Contrast that to a project where code is a horrible mish-mash, inexplicably inconsistent; a downright eyesore. I hate starting a project like this and I usually spend time upfront just cleaning things up, adding a bit of organization, and simply getting things to a readable state.

Having a good style guide that's rigorously (though not religiously) enforced is a key component to introducing elegance in your Ruby apps. Discipline starts with a style guide.

In the beginning...

We're all hackers. However long you've been a programmer, in whatever language you choose, we've all started off in the same place: tinkering and bashing until something works. As we become more proficient we build bigger and bigger programs with more ambitious goals, and more complicated codebases. As we do this, we often struggle with organization and style considerations.

At some point, you've probably come across Ruby and realized the inherent elegance of the language. There's a strong push towards readability over cleverness, which usually results in more English-like structure.

As projects become more complicated, and more people join the team, we realize it's important to standardize around a commonly-accepted formatting style. This reduces the context-switching we mentally have to perform every time we jump from one team member's contributions to another, and it lets us focus on the system itself.

What exactly is a style guide?

It's whatever you want! But generally, the best ones are clear, unambiguous documents of opinions that comprise:

  • Language formatting instructions (i.e. two spaces instead of tabs)
  • Which language and/or framework features to prefer over others (for instance, "prefer map over collect").

The best style guides evolve over time, and often require quite a bit of experience to be solid.

Discipline begets transcendence

When a programmer is in the zone, he or she is no longer thinking of the keys being tapped on the keyboard, the characters entered into a text editor, the number of lines being written. Instead, you're completely focused on the system, building each of the instruments that will soon form a symphony. This is coding transcendence, and it's only achievable when the act of programming melts away. When you can completely forget about syntax, language rules, and other minutiae, then you enter the zone.

Discipline is all about internalizing syntax to the point where you don't even have to think about it any more. This is key: a style guide reduces the number of mental cycles you need to expend to write a line of code because it takes all the tiny little decisions out of your hands. For instance, if you didn't have a style guide, you might be equally likely to write the following:

users.map { |user| user.company.touch :updated_at }

# later, in some other part of your code...
companies.map do |company|
  company.trade_organization.touch :updated_at
end

Both are perfectly legit, and neither is right or wrong. However, if you're trying to get into the zone (or, conversely, a new member of a team just looking to get up-to-speed), the last thing you want to do is see code that accomplishes similar goals but doesn't follow the same written pattern. You have to think, for however brief a moment, to put it together.

A style guide, however, trains your eye to recognize a syntactic pattern and skip over the step of mentally unrolling it, and instead focus only on the differences from the last time you saw the pattern. Here's the same thing above, but internally consistent:

users.map { |user| user.company.touch :updated_at }

# later, in some other part of your code...
companies.map { |company| company.trade_organization.touch :updated_at }

Reading the internally consistent lines goes faster because you can focus strictly on the differences. The syntax rules melt away and you can focus on the system.

Style guides are all about removing the decision making in styling your code. Once you've internalized the concepts, you'll write code faster that's easier to read and gives you more time in the zone.

Consistency is King

Starting a new project with a style guide in place is always easier than going back and converting a large codebase. Whatever situation you're in, first decide what you personally like and what is going to work for your team.

  • Start by reading through the Ruby Community Style Guide and GitHub's Style Guide. You don't have to agree with all of these, but start thinking about what you prefer so you can decide what you want to pull into your own style guide.

  • Next, check out thoughtbot's style guide, which goes a bit deeper on the opinion side of choosing what elements of a language or framework to use over others.

You can go in any number of directions with your own style guide, but I suggest keeping things simple and not spending much time on edge cases or hypotheticals. Instead, treat your style guide as a living document, updating it as you encounter new situations. But, once you've committed to a style, stick to it and only consider modifying it if you are clearly sure it's a change your strongly prefer.

Do you have a formal style guide? Do you only follow a style guide on team projects, or your personal stuff as well? What other guides are good resources people should check out?


Posted by Ryan Twomey on 01 Feb 2013 in Refactoring.
Tagged: refactoring, ruby
View comments



How to use Postgres EXPLAIN

A key tool in analyzing slow SQL queries is to use the Postgres EXPLAIN command. You may have noticed the output of this in your Rails log already: if Rails detects a slow SQL query in development mode, it will automatically re-run the query with EXPLAIN on, and output the results in your log. This command can be very helpful in understanding exactly what Postgres is doing under the hood.

Let's take a look at one of the quickest ways to use EXPLAIN to find a missing index. Let's say you have the following pop up in your log:

Limit (cost=102403.14..102403.22 rows=30 width=943)
  -> Sort (cost=102403.14..102403.27 rows=49 width=943)
        Sort Key: id
        -> Seq Scan on vehicles (cost=0.00..102401.77 rows=49 width=943)
              Filter: ((created_at >= '2012-01-04 16:06:25.350568'::timestamp without time zone) AND (created_at < '2013-01-24 16:46:05.787881'::timestamp without time zone) AND (company_id = 1234))

The important thing to note is the 'Seq Scan' part of that EXPLAIN. This indicates that Postgres has determined it needs to iterate sequentially through a list of results in order to find the right result (the Filter line is showing you what that sequence consists of). Whenever you see a 'Seq Scan' in your logs, it's usually a good indication of a potential place to put an index.

Having an index on vehicles.company_id will eliminate the need for this costly 'Seq Scan', so let's add one. Create a migration that looks similar to:

class AddIndexToVehiclesCompanyId < ActiveRecord::Migration
  def change
    add_index :vehicles, :company_id
  end
end

I knew that it was on the vehicles table because Postgres tells me the 'Seq Scan' is going through vehicle results, and I knew I needed an indx on the company_id because that's in the WHERE clause of my query and is indicated in the Filter line above (in other words, if Postgres is iterating through results to find the one result where company_id = 1234, we know we need to add an index so it can immediately find the row with that company_id).

After running the migrations, I can confirm that this query has sped up significantly and I'm no longer getting an EXPLAIN result in my logs. Hooray for fast queries!


Posted by Ryan Twomey on 25 Jan 2013 in Tutorials.
Tagged: postgres, optimization, rails
View comments



Adding a counter cache for fun and profit

Let's say you visit one of your Rails app's pages in your browser and, in glancing at your logs, you happen to notice a whole bunch of these:

 (0.3ms) SELECT COUNT(*) FROM "wheels" WHERE "wheels"."vehicle_id" = 1
 (0.3ms) SELECT COUNT(*) FROM "wheels" WHERE "wheels"."cohort_id" = 2
 (0.2ms) SELECT COUNT(*) FROM "wheels" WHERE "wheels"."cohort_id" = 3
 (1.1ms) SELECT COUNT(*) FROM "wheels" WHERE "wheels"."cohort_id" = 4
 (1.0ms) SELECT COUNT(*) FROM "wheels" WHERE "wheels"."cohort_id" = 5
 (1.1ms) SELECT COUNT(*) FROM "wheels" WHERE "wheels"."cohort_id" = 6
 (0.5ms) SELECT COUNT(*) FROM "wheels" WHERE "wheels"."cohort_id" = 7
 (0.3ms) SELECT COUNT(*) FROM "wheels" WHERE "wheels"."cohort_id" = 8

This is a sure sign that it's time to add a counter_cache. A counter cache in Rails is just an additional column that tracks the number of associated models. For instance, here's how you'd setup your two models:

class Wheel < ActiveRecord::Base
  belongs_to :vehicle, counter_cache: true
end

class Vehicle < ActiveRecord::Base
  has_many :wheels
end

Then, we need to add a migration:

class AddWheelsCountToVehicles < ActiveRecord::Migration
  def up
    add_column :vehicles, :wheels_count, :integer, default: 0, null: false

    Vehicle.find_each(select: 'id') do |result|
      Vehicle.reset_counters(result.id, :wheels)
    end
  end

  def down
    remove_column :vehicles, :wheels_count
  end
end

This migration will add a column, named wheels_count to the vehicles table, and set the default to 0. It then proceeds to iterate through all Vehicles in the database, one-at-a-time selecting just the vehicle ID. Next, the Rails reset_counters method is called on Vehicle. Given an ID of a Vehicle and the counter_cache column to update, Rails will count the number of associated Wheel objects and update the wheels_count column.

Of course, if you have a lot of Vehicles in your database, that migration could take some time to run, so plan ahead for how you'll deploy this to your app.


Posted by Ryan Twomey on 25 Jan 2013 in Tutorials.
Tagged: optimization, rails
View comments



Recent Posts

Subscribe for updates


Are you an iOS developer? Check out my site PushLayer, a service that makes it easy to send iOS push notifications.