Project Ramon

A learning journey from a Ruby noob perspective

Refactoring Ruby: Introduce Named Parameter

introduce_named_parameter_header_img

Hello and happy Monday!

I first saw today’s refactor pattern in this StackOverflow question I asked a while ago. I also remember seeing this implemented in Sandi Metz’ Practical Object-Oriented Design In Ruby book.

Introduce Named Parameter

When parameters in our method call can’t be easily reasoned from the name of our method. We can convert our parameter list into a Hash, using our Hash key’s as names for the parameters, thus allowing our parameters to make much more sense.

The alternative to using named parameters via Hashes could mean that a reader of our code, may have to jump around to different classes to try and ascertain the purpose of the objects passed in as parameters in our target method call.

By using a hash[:key] to store and name our parameters, we not only receive the benefits of improved readability and fluency, but its particularly beneficial for parameters that are only used in some of the calls (read: optional parameters).

Before moving forward into an example, lets checkout this pattern’s mechanics:

  • Select the parameters you wish to name, if you’re planning on naming only some parameters, move the parameters you want to name to the end. This way you can omit the { } curly braces
  • Test
  • Replace the parameters in the calling code with name: :value pairs
  • Replace the parameters with a Hash object in the receiving method. Modify the receiving method to use the new Hash
  • Test

Now that we have the mechanics all laid out, lets see this in action!

Example

before:

class MrPotatoHead
  attr_reader :hands, :eyes, :nose, :mouth, :hair, :hat, :shoes, :age_in_days

  def initialize(hands, eyes, nose, mouth, hair, hat, shoes, age_in_days)
    @hands = hands
    @eyes = eyes
    @nose = nose
    @mouth = mouth
    @hair = hair
    @hat = hat
    @shoes = shoes
    @age = age_in_days
  end
end

potato_head_pete = MrPotatoHead.new('happy hands', 'exuberant eyes', 'clown nose', 'smiling mouth', 'orange hair', 'sherlock hat', '2145')  

after:

class MrPotatoHead
  def initialize(hash={})
    @hands = hash[:hands]
    @eyes = hash[:eyes]
    @nose = hash[:nose]
    @mouth = hash[:mouth]
    @hair = hash[:hair]
    @hat = hash[:hat]
    @shoes = hash[:shoes]
    @age = hash[:age_in_days]
  end
end

Conclusion

By storing all of the necessary parameters inside of a hash, we are able to add or remove parameters as needed. We also give ourself some flexibility, as illustrated in our before example, we would have had to remember the order of each parameter… Not so good.

The authors of this book go into using some additional refactoring patterns with this one, and if you’re interested, grab a copy of their book, Refactoring Ruby Edition.

Stay tuned…

Advertisements

Categories: Ruby

Tags: , ,

5 replies

  1. A method with more than two or three positional arguments is usually a smell, so this refactoring is a must for me. Worth mentioning that you can use Hash#fetch to require arguments, like this: hash.fetch(:hands). It fails loudly when the argument is not provided. I also use named parameters when I can, available in Ruby 2.0. The effect is the same 🙂

  2. In that case I’d prefer a new ruby 2 named arguments syntax: initialize(hands:, eyes:, nose:, mouth:, hair:, hat:, shoes:, age_in_days:). It protects the method from assigning unexpected values and allows to declare required values.

    http://brainspec.com/blog/2012/10/08/keyword-arguments-ruby-2-0/

Trackbacks

  1. Refactoring Ruby: Remove Named Parameter | Project Ramon

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