+1

Tìm hiểu về Ruby Refinements

Khi nào và lúc nào chúng ta sử dụng Ruby Refinements cho dự án của mình? Ruby Refinements hay bộ lọc Ruby là 1 tính năng khá mới, được giới thiệu với Ruby 2.0.0. Ở đây chúng tôi xin phép giữ nguyên từ "Ruby Refinements".

Ruby Refinements là cái gì?

Ruby Refinements là một tính năng tuyệt vời mà cộng đồng Ruby đã chờ đợi trong một thời gian dài. Nó có mục đích chính để thay thế các đoạn mã với nhưng tác dụng phụ tiêu cực. Lợi thế chính là khả năng mở rộng scope, nghĩa là xác định rõ khu mực mã nó gây ảnh hưởng đến. Refinement là cách làm tốt giúp cho code của bạn dễ hiểu và gọn gàng. Không phải lúc nào chúng ta cũng có thể sử dụng ruby refinement trong dự án của mình. Vì vậy, bây giờ chúng ta hãy đi sâu vào tìm hiểu cách thức hoạt động của nó.

Chúng ta nên sử dụng Ruby Refinements như thế nào?

Để bắt đầu làm việc với Ruby Refinements, việc đầu tiên bạn nên thiết lập các scope mà nó gây ảnh hưởng đến. Vì vậy, chúng ta hãy định nghĩa các module và class

module ListStrings
  refine String do
    def +(other)
      "#{self}, #{other}"
    end
  end
end

Sau đó sử dụng ListStrings trong khu vực cần required

using ListStrings
'4' + '5'
# => "4, 5"

Bây giờ, bạn có thể "tinh luyện" đoạn code của bạn. Bạn cũng có thẻ làm điều đó với câu lệnh eval

 eval "using ListStrings; '4' + '5'"
# => "4, 5"

Hãy nhớ rằng, việc sử dụng sẽ chỉ gây ảnh hưởng đến các file hiện nay, các file khác sẽ không được thay đổi. Bắt đầu từ Ruby 2.3 Refinement có thể được sử dụng trong các class cụ thể, điều đó thật tuyệt, vì nó giúp bảo vệ bạn khỏ tất các hiệu ứng bất lợi

 module Foo
  refine Fixnum do
    def to_s
      :foo
    end
  end
end

class NumAsString
  def num(input)
    input.to_s
  end
end

class NumAsFoo
  using Foo
  def num(input)
    input.to_s
  end
end

NumAsString.new.num(4)
# => "4"
NumAsFoo.new.num(4)
# => :foo

Những vấn đề tồn tại của Ruby Refinements là gì?

Ruby Refinements sẽ giúp bạn giới thiệu những cách thay đổi code 1 cách an toàn. Đồng thời nó vẫn có 1 số hạn chế nhất định, vì vậy hãy chú ý điều này. Dưới đây là 1 vài vấn đề mà tôi nhin thấy:

1. Không thể sử dụng nhiều bộ lọc 1 lúc

Bạn sẽ không thể chạy 1 vài bộ lọc cho cùng 1 method, mặc dù đây không phải là 1 trường hợp phổ biến chúng ta thường gặp, nhưng chúng ta vẫn cần phải lưu ý.

2. Không tương thích với Dynamic Dispatch

Dynamic Dispatch được sử dụng gọi các method mapping, ví dụ như

 [1,2,3].map(&:to_s)

Thật đang tiếc khi những method này không sử dụng được refinements

3. Kiểm tra lịch sử các đoạn mã

Mộ điểm yếu quan trọng của refinements là làm cho các đoạn khó khăn trong việc thay đổi chúng.

module Bar
  def refinements
    require 'set'
    @refinements = (@refinements || Set.new) << Bar
  end

  refine String do
    def bar
      :bar
    end
  end
end

class A
  include Bar and using Bar
  def a
    "".bar
  end
end

A.new.refinements
# => #<Set: {Bar}>
A.new.a
# => :bar

4. Không thể sử dụng từ bên trong 1 method hoặc 1 module

Nếu bạn muốn sử dụng Refinement, bạn sẽ phải khai báo sử dụng cho phạm vi các scope. Trên phạm vi khác, nó thể có ích cho các developer trong thời gian 1 năm.

Tổng kết

Tóm lại, chúng ta có nên sử dụng chúng hay không? Mặc dù Ruby Refinements, giống như 1 tính năng hữu ích, tuy nhiên vẫn còn 1 số vấn đề nhỏ tồn tại, chúng ta vẫn khuyên bạn nên tin sử dụng nó ngay bây giờ. Sử dụng Ruby Refinements sẽ cho bạn thấy rõ các hành vi thay thế và làm cho code bạn mạch lạc hơn. Và có khả năng rất cao rằng một số nhược điểm của nó sẽ được khắc phục trong tương lai gần nhất, do đó bạn không phải quá lo lắng về điều này

Bài viết được tham khảo và dịch từ: http://blog.rubyroidlabs.com/2016/08/ruby-refinements/


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.