1. Monkey patch là gì
- Là 1 tính năng của ruby cho phép bạn chỉnh sửa 1 hàm có sẵn hoặc thêm mới 1 hàm vào trong class bất kỳ.
a. Thêm mới method vào class
- Đoạn code sau sẽ raise lỗi
NoMethodError (undefined method shuffle for "aaa":String)
12<span class="token string">"monkey patch"</span><span class="token punctuation">.</span>shuffle - Nguyên nhân là class
String
không có methodshuffle
- Chúng ta có thể sử dụng monkey path để thêm method
shuffle
vào classString
123456789<span class="token keyword">class</span> <span class="token class-name">String</span><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">shuffle</span></span><span class="token keyword">self</span><span class="token punctuation">.</span>chars<span class="token punctuation">.</span>shuffle<span class="token punctuation">.</span>join<span class="token keyword">end</span><span class="token keyword">end</span>puts <span class="token string">"monkey patch"</span><span class="token punctuation">.</span>shuffle<span class="token comment"># n ptchemkyao</span>
b. Chỉnh sửa method có sẵn trong class
- Tương tự chúng ta cũng có thể sử dụng monkey path để chỉnh sửa method có sẵn trong class
- Ví dụ123456789<span class="token keyword">class</span> <span class="token class-name">String</span><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">length</span></span><span class="token number">100</span><span class="token keyword">end</span><span class="token keyword">end</span>puts <span class="token string">"monkey patch"</span><span class="token punctuation">.</span>length<span class="token comment"># 100</span>
2. Cách tổ chức code với monkey patch
- Monkey patch là 1 công cụ mạnh mẽ nhưng cũng có thể gây ra lỗi và khó khăn khi debug nếu không được sử dụng và tổ chức code tốt.
- Trong các ví dụ trên mình đã monkey path trực tiếp vào class
- Đó không phải là 1 cách tốt vì các nguyên nhân sau.
i. Code sẽ bị override
- Khi 1 method có 2 monkey-path thì bản path thứ 2 sẽ overide bản path thứ 1 và ảnh hưởng đến các đoạn code đã chạy với bản path thứ 1.
- Ví dụ:123456789101112131415161718<span class="token keyword">class</span> <span class="token class-name">String</span><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">length</span></span><span class="token number">100</span><span class="token keyword">end</span><span class="token keyword">end</span>puts <span class="token string">"monkey patch"</span><span class="token punctuation">.</span>length<span class="token comment"># 100</span><span class="token keyword">class</span> <span class="token class-name">String</span><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">length</span></span><span class="token number">200</span><span class="token keyword">end</span><span class="token keyword">end</span>puts <span class="token string">"monkey patch"</span><span class="token punctuation">.</span>length<span class="token comment"># 200</span>
ii. Không handle được mình có đang sử dụng monkey path hay không
- Khi không muốn sử dụng monky-path, bạn chỉ có cách comment lại đoạn code monkey path
- Tuy nhiên làm như vậy sẽ ảnh hưởng đến các đoạn code đang chạy đúng với monkey path
iii. Solution
- Sử dụng module chứa monkey path và include chỉ khi cần sử dụng monkey path
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">module</span> <span class="token constant">CoreExtensions</span> <span class="token keyword">module</span> <span class="token builtin">String</span> <span class="token keyword">module</span> <span class="token constant">MonkeyPath</span> <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">shuffle</span></span> <span class="token keyword">self</span><span class="token punctuation">.</span>chars<span class="token punctuation">.</span>shuffle<span class="token punctuation">.</span>join <span class="token keyword">end</span> <span class="token keyword">end</span> <span class="token keyword">end</span> <span class="token keyword">end</span> <span class="token builtin">String</span><span class="token punctuation">.</span><span class="token keyword">include</span> <span class="token constant">CoreExtensions</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token builtin">String</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token constant">MonkeyPath</span> puts <span class="token string">"monkey patch"</span><span class="token punctuation">.</span>shuffle |