Monkey patching trong ruby

1. Monkey patching là gì?

Monkey patch là cách mà một chương trình mở rộng hoặc thay đổi để hỗ trợ hệ thống phần mềm hiện tại. Điều này cũng được biết tới với tên gọi là duck puching, dựa trên thuật ngữ duck typing

Sự ra đời của tên gọi này cũng khá là thú vị. Nó được ra đời từ một thuật ngữ trước đó, guerrilla patch, cái liên quan tới việc thay đổi mã một cách không công khai, có thể không thích hợp với những bản patch khác ở thời điểm chạy. Từ guerrilla được đọc gần giống với gorilla và sau đó trở thành monkey nhằm tránh gây sự sỡ hãi 😄

Trong Ruby, Python và những ngôn ngữ lập trình dynamic khác, monkey patch chỉ đề cập tới những thay đổi động của class hoặc module ở runtime.

2. Ứng dụng monkey patch

Monkey patching thường được sử dụng trong các trường hợp sau

  • Thay thế methods / attributes / functions lúc runtime, ví dụ: stub chức năng trong quá trình testing
  • Thay đổi hoặc mở rộng hành vi của thư viện bên thứ 3 mà không thông qua bảo trì
  • Áp dụng patch lúc runtime của object trong bộ nhớ thay vì sửa lỗi trong source code
  • Phân phối các bản vá đi kèm đồng thời với mã nguồn

3. Monkey patching trong Ruby

Chúng ta sẽ cùng nhau xem monkey patch trong ruby thông qua một số ví dụ sau: Thêm mới một methods trong class có sẵn của ngôn ngữ Ruby

class String
  def self.lorem
	"Lorem ipsum dolor sit amet, consectetur adipiscing elit."
  end
end

Hàm này là hàm của class và trả về một chuỗi string như trên, chúng ta sẽ cùng thử xem kết quả:

2.3.0 :001 > class String
2.3.0 :002?>  def self.lorem
2.3.0 :003?>   "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
2.3.0 :004?>  end
2.3.0 :005?>end
 => :lorem
2.3.0 :006 > String.lorem
 => "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
2.3.0 :007 >

Chúng ta cũng có thể thay đổi cách hoạt động của một function bằng cách ghi đè với cách sau:

class String
  def upcase
	self.reverse
  end
end

Cùng xem kết quả

2.3.0 :007 > class String
2.3.0 :008?>   def upcase
2.3.0 :009?>     self.reverse
2.3.0 :010?>   end
2.3.0 :011?> end
 => :upcase
2.3.0 :012 > "Framgia".upcase
 => "aigmarF"
2.3.0 :013 >

Giống như các bạn thấy, chúng ta hoàn toàn có thể can thiệp được vào bên trong ngôn ngữ Ruby khá dễ dàng.

4. Khi nào nên sử dụng Monkey patching

Ruby là một ngôn ngữ lập trình mạnh mẽ. Tuy nhiên, mạnh mẽ không có nghĩa là nó sẽ làm tốt hầu hết mọi công việc mà chúng ta muốn. Monkey patching nói riêng là một công cụ mạnh mẽ. Tuy nhiên, công cụ mạnh mẽ mà được sử dụng sai cũng dẫn đến hậu quả khôn lường. Bất cứ khi nào bạn monkey patch một class cũng đồng nghĩa với việc bạn đang tạo ra một mối nguy hiểm cho chương trình của bạn trong tương lai. Classes được monkey patch sẽ khó để hiểu và debug. Nếu không cận thận, những lỗi gây ra sẽ khó lòng sửa chữa. Khi monkey patching một method có nghĩa là chúng đang đang phá vỡ những thành phần liên quan có sử dụng method đó, và dẫn tới nhiều lỗi khó lường khác. Khi thêm một method vào một class bằng Monkey Patching có nghĩa là chúng ta đã tạo ra nhiều lỗi có thể xảy ra.

Tất nhiên bạn có thể sử dụng monkey patch, nhưng để tốt nhất, điều chúng ta cần làm là nhóm những phần patching của bạn lại thành một file hoặc một thưc mục để an toàn và dễ quản lý hơn. Bên cạnh đó việc triển khai viết test cũng giảm thiểu được lỗi gây ra khi chúng ta thực hiện patching.

Reference: