giant robots smashing into other giant robots

We are thoughtbot. We make web & mobile apps.

Tagged:

Comments (View)

Types of Coupling

Those of you coming from a Google search are about to be disappointed: this is a post about types of coupling in programming.

Coupling refers to the degree to which components in your program rely on each other. You should generally seek to minimize this property, though you’ll see it’s impossible to eliminate entirely.

Here are a few types of coupling, ordered by severity (first is worst):

Pathological Coupling

Your class reaches inside another class and reads (or, perish the thought, changes) its instance variables.

You are literally pathological and deserve the pain this will cause you.

class NuclearLaunchController
  def initialize(launch_codes)
    @launch_codes = launch_codes
  end
end

class ExtremelyBadIdea
  def initialize(nuclear_launch_controller)
    @launch_controller = nuclear_launch_controller
  end

  def do_bad_things
    # This is poison
    @launch_controller.instance_variable_set(:@launch_codes, 'password')
  end
end

Global Coupling

You have two classes that both rely on some shared global data, maybe a Singleton or a class variable.

When many test files all depend on global factory definitions, a change to any one can ripple through the system.

# spec/factories.rb
FactoryGirl.define do
  factory :user do
    # Changes here are global and can affect many test files.
  end
end

# spec/model/user_spec.rb
before do
  # This refers to global data.
  @user = build_stubbed(:user)
end

# spec/model/order_spec.rb
before do
  # So does this.
  @user = build_stubbed(:user)
end

Note that this is probably an example where the cure (duplicating the logic for creating test objects in every spec) is worse than the disease.

Control Coupling

You pass in a flag that tells a method what to do.

Remember save(false) in ActiveRecord? That boolean argument caused control coupling. Remember how we all had to change our code when it became save(validate: false)? If we’d been calling save and save_without_validation instead, Rails Core could have refactored that method more times than the router and we’d never have known. Also, notice that passing validate: false into save does not reduce the coupling, it’s just disguised better.

Control couples are smelly because the calling method has intimate knowledge of how the receiver implements the method being called. You’re determining what an object should do based from outside it. Good OOP lets objects decide what to do based on their own state.

def save(should_run_validations=true)
  # When you see a parameter in a conditional, that's control coupling.
  # The fact that this method has an if in it has leaked out into client code.
  # Changes can now require changes in these clients.
  if should_run_validations
    run_validations
    persist
  else
    persist
  end
end

# One possible fix: define two methods and let the clients 
# choose which to call. Now we can refactor either without 
# affecting clients.
def save
  run_validations
  persist
end

def save_without_validations
  persist
end

Data Coupling

You call a method and pass it a parameter that doesn’t affect its control flow.

This is still coupling, but we’re starting to reach the kind that isn’t so bad. Sometimes you need parameters! If you wanted to remove all coupling you wouldn’t be able to pass data between objects at all.

class ScreenPrinter
  # This method is coupled to its parameter, because a change to that argument 
  # can cause breakage (if we undefined to_s, for example).
  def print(text)
    output_to_screen(text.to_s)
  end
end

Message Coupling

You call a method on an object and send no parameters.

You’re coupled to the name of the message, but not any hint of its implementation. This is the loosest type of coupling and should be your goal. Notice that this makes methods that take no arguments better than methods that take one (and so on).

# No reliance on anything outside this object. Feels good, man.
class ScreenPrinter
  def print_to_screen
    output_to_screen(@text)
  end
end

Keep an eye out for the nasty types of coupling in your code, and see if you can can’t refactor it into something further down the ladder.

(I cribbed this list of coupling types from Wikipedia’s article, paraphrased and added examples. The original article is worth reading.)

Tagged:

Comments (View)

Come Correct with Inject and Collect

Here’s a refactoring example for a simple Ruby math problem using the inject method.

The goal is to generate an n by n multiplication matrix. Pretty straightforward. Let’s make a first pass:

def multiplication_table(n)
  results = []

  (1..n).each do |row_index|
    row = []
    (1..n).each { |column_index| row << row_index * column_index }
    results << row
  end

  results.each do |row|
    header = '%-3s ' * row.length
    puts header % row
  end
end

multiplication_table(7)
1   2   3   4   5   6   7
2   4   6   8   10  12  14
3   6   9   12  15  18  21
4   8   12  16  20  24  28
5   10  15  20  25  30  35
6   12  18  24  30  36  42
7   14  21  28  35  42  49

It does the job, but it’s nothing to look at. We can condense using in-line blocks and fancy curly braces, but first let’s try using inject.

Quick background: Inject iterates over a set using a block with a collector, which is a variable whose value is passed back each round, making it good for iterative uses. The block’s return value is passed into the collector (make sure you return something or you’ll get a nil). Also, the return value of the whole inject block is the final collector value.

Simple example from the docs:

(5..10).inject {|sum, n| sum + n }            #=> 45

The inject method takes a parameter, which initializes the collector value (default is to set to the first value). You can pass in an empty array and add values:

def multiplication_table(n)
  results = (1..n).map do |row_index|
    (1..n).inject([]) { |row, n| row + [row_index * n] }
  end

  results.each { |row| puts '%-3s ' * row.length % row }
end

So that’s inject with the iterative collect (Whoo-aaaa - got you all in check)

Note: For a more in-depth discussion of inject, read Mike Burns’ recent post.

Tagged:

Comments (View)

Humans Present: An OSS Lifestyle

I recently sat down with Mike Burns to discuss his operating system and computer setup. Mike uses an entirely Open Source stack.

We discussed how he got started with this, the current state of running Linux, as well as some of the unique benefits and cool features of doing so.

We decided to make this special video available for free, and you can watch it here.

Tagged:

Comments (View)

Time.now is on my side

I needed an open? method. First try:

def open?
  opens_at < Time.now < closes_at
end

However, Ruby doesn’t support that kind of expression. Second try:

def open?
  (opens_at < Time.now) && (Time.now < closes_at)
end

It’s noisy and lacks expression. Third time’s a charm:

def open?
  Time.now.between? opens_at, closes_at
end

Ship it.

Tagged:

Comments (View)

Decorators compared to Strategies, Composites, and Presenters

We’ve been paying closer attention lately to how we use design patterns in our Ruby on Rails work.

Decorators have emerged as one pattern that’s helped us keep code ready for change. We’ve chosen our spots carefully, but it’s proven useful quite often.

For me, it’s been a new technique that’s required asking a lot of questions to evaluate alternative decorator implementations in Ruby and understand terms.

Some questions I’ve had:

  • What’s the difference between a decorator and a strategy?
  • What’s the difference between a decorator and a composite?
  • What’s the difference between a decorator and a presenter?

Tie-dyed t-shirt

Intent

A decorator’s intent, as described in Design Patterns by the Gang of Four, is:

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Invoking a classic decorator in Ruby looks like this:

coffee = Coffee.new
Sugar.new(Milk.new(coffee)).cost

A popular alternative style is:

coffee = Coffee.new
coffee.extend Milk
coffee.extend Sugar
coffee.cost

There’s a family of patterns that are similar to decorators.

When would we use them instead of a decorator?

Strategy

The Gang of Four differentiates these succinctly:

  • A decorator changes an object’s skin.
  • A strategy changes an object’s guts.

Said another way, a decorator is likely to add functionality (decorate) an object and a strategy is likely to swap functionality.

Example of a strategy in Ruby using the same Coffee analogy:

class Coffee
  def initialize(brewing_strategy = DripBrewingStrategy.new)
    @brewing_strategy = brewing_strategy
  end

  def brew
    @brewing_strategy.brew
  end
end

Coffee.new SteepBrewingStrategy.new

The form is similar to a PORO decorator, which is why the patterns feel related.

The difference is that the object passed to the constructor is not being “wrapped” like a decorator. We’re “swapping” functionality.

The decorator is additive and the strategy is a replacement.

With words like “guts”, “swapping”, and “replacement”, it’s no surprise that strategies are often used with Dependency “Injection”. In the example above, constructor injection lets us easily swap the brewing strategy.

Composite

Gang of Four:

  • A decorator can be viewed as a composite with only one component.
  • A decorator isn’t intended for object aggregation.

Example of a composite in Ruby from the ActivePresenter library:

class SignupPresenter < ActivePresenter::Base
  presents :user, :account
end

A decorator decorates a single component and a composite composes multiple components (user and account in the example above).

Both patterns are named well.

Presenters

Now, the most confusing one:

  • A decorator is a class that adds functionality to another class.
  • A presenter is a class that adds presentation functionality to another class.
  • A presenter is sometimes a decorator.
  • A presenter is sometimes a composite (as in the ActivePresenter example above).

This is my own definition. I don’t have an authority to refer you to since you won’t find “Presenter” in Gang of Four. As best I can tell, the Rails community began using the term “Presenter” with this 2007 article by Jay Fields.

The easiest mnemonic is just to defer to their names. What makes a presenter a presenter is its presentation-ness.

One example:

class HumanizedStat
  def initialize(component)
    @component = component
  end

  def to_s
    # giant case statement that used to be in a model
  end

  # a bunch of private helper methods supporting #to_s
  # which used to be in app/helpers
end

In this case, the presenter looks a lot like a decorator (but doesn’t meet the Gang of Four definition): it’s adding functionality to a single component.

However, because the functionality is completely presentation-related, I’d expect this to be considered a presenter and maybe saved in a app/presenters directory.