---
title: Types of Coupling
teaser: Those of you coming from a Google search are about to be disappointed.
tags: web,ruby,good code
author: Ben Orenstein
published_on: 2012-05-15
---

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.

```ruby
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
```

As mentioned by Mike Burns in the comments, monkey-patching falls into this
category. Beware!

## Global Coupling

_You have two classes that both rely on some shared global data, maybe a
[Singleton](http://en.wikipedia.org/wiki/Singleton_pattern) or a class
variable._

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

```ruby
# spec/factories.rb
FactoryBot.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 from outside it. Good <abbr title="Object Oriented
Programming">OOP</abbr> lets objects decide what to do based on their own state.

```ruby
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.

```ruby
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).

```ruby
# No reliance on anything outside this object. Feels good, yo.
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.)

[Wikipedia's article]: http://en.wikipedia.org/wiki/Coupling_(computer_programming)
