Separating the General from the Specific

The ability to encapsulate behavior into blocks and pass it into methods is an extremely useful programming technique. This lets you separate the general and specific pieces of your code. Open irb and let’s explore what this separation of concerns looks like.

Suppose you have a range of numbers from 1 to 20, and you’re interested in only getting the even numbers. In Ruby, this is how you can do it:

 >>​ Array(1..20).select { |x| x.even? }
 =>​ [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Later, you decide that the list is too big and you want to add another condition: the even numbers must also be greater than 10:

 >>​ Array(1..20).select { |x| x.even? and x > 10 }
 =>​ [12, 14, 16, 18, 20]

Notice that the only code that you had to change was contained within the blocks. That is, the actual “business logic” piece. You didn’t have to implement your own special version of Array#select in order to cope with a change in requirements. This also comes up pretty often with sorting.

Imagine that you’re working on an e-commerce site that sells sports shoes, and you want to display a selection of the products on the main page:

 >>​ require ​'ostruct'
 
 >>​ catalog = []
 >>​ catalog << OpenStruct.new(​name: ​​'Nike'​, ​qty: ​20, ​price: ​99.00)
 >>​ catalog << OpenStruct.new(​name: ​​'Adidas'​, ​qty: ​10, ​price: ​109.00)
 >>​ catalog << OpenStruct.new(​name: ​​'New Balance'​, ​qty: ​2, ​price: ​89.00)

It’s plain to see that we have a pretty wide selection of footwear. Now, the boss wants to display the products by the lowest priced first:

 >>​ catalog.sort_by { |x| x.price }
 =>​ [​#<OpenStruct name="New Balance", qty=2, price=89.0>,
  #<OpenStruct name="Nike", qty=20, price=99.0>,
  #<OpenStruct name="Adidas", qty=10, price=109.0>]

What if now she wants the products with the highest quantity to be displayed first?

 >>​ catalog.sort_by { |x| x.qty }.reverse
 =>​ [​#<OpenStruct name="Nike", qty=20, price=99.0>,
  #<OpenStruct name="Adidas", qty=10, price=109.0>,
  #<OpenStruct name="New Balance", qty=2, price=89.0>]

In both instances, all you had to change was the code in the block. In fact, you didn’t have to change the implementation of Enumerable#sort_by. You were able to trust that the method would do its job provided you gave it a reasonable sorting criteria to work with.

So how is this possible? With yield.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.170.134