Argument order dependencies

Message senders need to know about required arguments when instantiating classes and sending external messages (i.e. messages to objects other than self) and argument dependencies are typically unavoidable. However, message senders often do not need to know about the order of required arguments. Refactoring code to remove argument order dependencies has a side benefit of making the code easier to read and maintain.

class Person
  def initialize(name, age, height=nil)
    @name = name
    @age = age
    @height = height
  end
end

class Company
  attr_reader :employees
  def initialize
    @employees = []
  end

  def add_employee(name, age, height=nil)
    @employees << Person.new(name, age, height)
  end
end

company = Company.new
company.add_employee("Bob Phat", 42, 72)
company.add_employee("Nice Pen", 16, 60)
p company.employees
# => [#<Person:0x007fe6e8abb7c0 @name="Bob Phat", @age=42, @height=72>, #<Person:0x007fe6e8a9dd60 @name="Nice Pen", @age=16, @height=60>]

The Company class has the following dependencies on the Person class:

1. Company knows that the Person class is named Person
2. Company know that Person responds to the new message and is initialized with name, age, and height
3. Company knows that the new message takes name first, age second, and height third as an optional parameter

We can eliminate dependency #3 with the following refactoring:

class Person
  def initialize(args)
    @name = args.fetch(:name)
    @age = args.fetch(:age)
    @height = args.fetch(:height, nil)
  end
end

class Company
  attr_reader :employees
  def initialize
    @employees = []
  end

  def add_employee(args)
    @employees << Person.new(args)
  end
end

company = Company.new
company.add_employee(name: "Bob Phat", age: 42, height: 72)
company.add_employee(height: 60, name: "Nice Pen", age: 16)
p company.employees
# => [#<Person:0x007fe6e8abb7c0 @name="Bob Phat", @age=42, @height=72>, #<Person:0x007fe6e8a9dd60 @name="Nice Pen", @age=16, @height=60>]

The Company#add_employee method is significantly more readable when it accepts a hash with descriptive key names as an argument. This refactoring also removes the argument order dependency. Company still needs to know that Person is initialized with a hash that includes :name, :age, and an optional :height key, but it does not need to know the order of these arguments.

Advertisements

One thought on “Argument order dependencies

  1. Pingback: Dev Bootcamp Rap Recap: Week 2 | Duke Greene is Thinking Out Loud.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s