Là khỉ được coi là thực hành lập trình tốt?


15

Tôi đã rất ấn tượng, rằng trò chơi khỉ là nhiều hơn trong thể loại hack nhanh và bẩn, thay vì tiêu chuẩn, thực hành lập trình tốt. Mặc dù thỉnh thoảng tôi đã sử dụng để khắc phục các sự cố nhỏ với libs của bên thứ 3, tôi đã xem xét nó là sửa chữa tạm thời và tôi sẽ gửi bản vá thích hợp cho dự án của bên thứ 3.

Tuy nhiên, tôi đã thấy kỹ thuật này được sử dụng như "cách thông thường" trong các dự án chính, ví dụ như trong gevent.monkeymô-đun của Gevent .

Có phải khỉ đã trở thành chính thống, bình thường, thực hành lập trình chấp nhận được?

Xem thêm: "Monkeypatching For Humans" của Jeff Atwood


13
Tôi muốn nói rằng một cái gì đó có tên là vá khỉ KHÔNG được coi là thực hành lập trình tốt. Mà không biết nó là gì, chỉ bằng tên của nó.
littleadv

Điều gì xảy ra nếu bên thứ 3 không muốn thực hiện sửa lỗi bạn cần?

1
@ Thorbjørn: một câu hỏi hay, một mặt tôi không thích bắt chước, mặt khác tôi không thích ý tưởng nhân bản dự án và giữ các bản vá địa phương nếu đó chỉ là một vấn đề nhỏ.
vartec

1
@littleadv: ... sau đó gọi nó là "sửa chữa nóng" / "sửa lỗi nhanh" hoặc "sửa lỗi thời gian chạy" và nghe có vẻ tốt phải không? ;) Tất cả đều giống nhau.
dagnelies

3
javascript được xây dựng khá nhiều xung quanh khái niệm này
ZJR

Câu trả lời:


19

Không, nhưng đôi khi khỉ là một cái ác ít hơn (hơn là bị hỏng mã :)). Các quy tắc chung của tôi đối với khỉ trong ruby ​​là:

  • có một lý do thực sự tốt cho bản vá khỉ (hotfix quan trọng tạm thời là một lý do chính đáng. Định dạng đẹp của phương thức to_s thì không, trừ khi bạn đang làm việc trên ActiveSupport)

  • làm cho chúng minh bạch nhất có thể: đặt chúng vào vị trí cụ thể trong codebase và các tệp riêng biệt, viết tài liệu mô tả lý do cho khỉpatch (đây là một ví dụ ).

  • dễ dàng để loại bỏ - tài liệu nên bao gồm thông tin về loại bỏ và những gì cần xem. Rất nhiều con khỉ là tạm thời, vì vậy chúng nên dễ dàng loại bỏ.


11

Vâng, khỉpatching là rất hữu ích!

Bằng cách nào đó, tên dường như có ảnh hưởng rất lớn đến nhận thức của mọi người. Gọi nó là "khỉpatch" và nghe có vẻ tệ, gọi nó là "sửa chữa nóng" hoặc "sửa chữa nhanh" và nó có vẻ tốt.

Độc lập với điều đó, tôi nghĩ rằng khả năng thay đổi các phương thức / thuộc tính / hàm trong thời gian chạy là một điều rất hữu ích. Ngay cả những người dùng javascript cũng sử dụng nó cả ngày mà không biết.

Ví dụ:

button.onclick = function(e) { ...}

Dòng đơn giản này minh họa thực tế là bạn thay đổi hành vi của nút. Nó được thiết kế theo cách đó. Tương tự như vậy, bạn có thể thay đổi mọi chức năng khác nhưng sẽ thật ngớ ngẩn khi làm như vậy.

Bây giờ, đối với câu hỏi cung cấp các bản vá theo cách đó ... tốt ... tại sao không. Bạn chỉ cần tải về một bản vá nhỏ thay vì một bản phát hành lớn. Heck, bạn thậm chí có thể vá một máy chủ mà không dừng lại, thật tuyệt! Và sau đó, một ngày, bạn cũng có thể lấy bản phát hành mới nhất để cập nhật lớn hơn. Đủ công bằng. Vì vậy, có, tôi bỏ phiếu cho "bản vá thời gian chạy" là một điều tốt.

Thật thú vị, một số ngôn ngữ như Erlang thậm chí đã được xây dựng xung quanh khái niệm này. Khả năng cập nhật một máy chủ nhanh chóng.

Tất nhiên, cuối cùng, và giống như mọi thứ khác, vấn đề là bạn sử dụng nó như thế nào. Bạn có thể tạo ra những thứ OO tuyệt vời và một thứ tồi tệ, tất cả đều giống nhau.

BIÊN TẬP:

Hãy để tôi thêm một số phân biệt trường hợp, cho dù bạn đang vá thư viện của riêng bạn hoặc của bên thứ ba .

... về cơ bản, những gì bạn làm với một bản vá như vậy là sửa một lỗi của thư viện của riêng bạn hoặc của bên thứ ba . Trong cả hai trường hợp, nó hữu ích. Đối với riêng bạn, nó cho phép bạn cung cấp một bản sửa lỗi nhanh chóng. Đối với bên thứ ba, bạn sẽ đợi (vài tháng?) Cho đến khi họ tự sửa nó hoặc bạn tự làm điều đó ngay bây giờ. (bạn vẫn có thể gửi cho họ bản vá, để họ sẽ sửa nó về phía họ). Khi họ phát hành phiên bản lib tiếp theo với sự cố đã được khắc phục, bạn vẫn có thể, nếu bạn muốn cập nhật thư viện và xóa bản vá về phía bạn.

Bây giờ, tất nhiên, nếu bạn sử dụng một bản vá để thay đổi hành vi của một lib và xa lánh mục đích / cách làm việc của nó, thì rõ ràng đó là một công thức cho thảm họa. Ngay cả một con khỉ cũng sẽ thấy điều đó ... tốt, tôi hy vọng. ;)


1
Không ai nói nó không hữu ích. Tuy nhiên, nói chung nó không phải là một thực hành tốt. Và "hotfix" và "sửa lỗi nhanh" không có vẻ tốt hơn đối với tôi.
Lukas Stejskal

1
Chà, tôi thấy khả năng thay đổi hành vi của một ứng dụng đang hoạt động rất hữu ích, thậm chí còn nhiều hơn nếu nó là một ứng dụng lớn. Heck, bạn thậm chí có thể có mã lưu trữ phương thức cũ làm bản sao lưu và một lệnh để tự động phục hồi theo yêu cầu! Khả năng là rất lớn!
dagnelies

Tôi đồng ý rằng đó là một tính năng mạnh mẽ và hữu ích. Nhưng cũng rất nguy hiểm (đặc biệt là trong Ruby), do đó, nó nên được sử dụng hết sức thận trọng (đặc biệt để sửa đổi thư viện của bên thứ ba và tiêu chuẩn). Bạn đã bao giờ cố gắng duy trì ứng dụng tùy thuộc vào một số thư viện của bên thứ 3 bị lừa? Một công thức cho thảm họa bất cứ khi nào bạn cố gắng cập nhật một số thư viện.
Lukas Stejskal

1
Vâng, tôi đồng ý, nếu bạn sử dụng các bản vá này một cách bất cẩn, theo những cách vô ý hoặc lạm dụng chúng, nó có thể nhanh chóng trở nên lộn xộn. Giống như bạn có thể lạm dụng bất kỳ khái niệm hoặc làm cho một mớ hỗn độn với bất cứ điều gì. Tuy nhiên, nếu không, nếu chúng được tổ chức tốt và minh bạch, và tất cả chúng đều chảy trong phiên bản lớn tiếp theo, nó có vẻ sạch sẽ đối với tôi. ... tuy nhiên, tôi không có kinh nghiệm với các thư viện ruby ​​được vá rất nhiều.
dagnelies

... Tôi đã thêm một số ý kiến ​​về trường hợp sau.
dagnelies

8

Tôi tin rằng tất cả các bản vá vốn đã có rủi ro do bản chất thời gian chạy của chúng và không có khả năng bị bắt tại thời điểm thiết kế.

Họ hoan nghênh các ngoại lệ thời gian chạy, và yêu cầu trình gỡ lỗi và đồng hồ phức tạp chỉ để làm theo.

Chúng được sử dụng khi mọi người lớp SEAL, và vì vậy không thể kế thừa. Tuy nhiên, có nhiều cách tốt hơn để mở rộng các đối tượng mà không làm hỏng chúng.

Theo quan điểm của tôi


4

Vá nói chung nên là phương sách cuối cùng, khỉ vá thậm chí còn hơn thế. Vấn đề chủ yếu là một trong những khả năng bảo trì.

Cách đây rất lâu, kernel linux của tôi có 3 bản vá riêng biệt được áp dụng cho nó, cần thiết cho trình điều khiển card màn hình của tôi và hai ứng dụng độc quyền mà tôi có. Hai trong số chúng có những thay đổi mâu thuẫn, điều đó có nghĩa là tôi cần một bản vá thứ 4 để giải quyết sự khác biệt giữa chúng. Bây giờ, bất cứ khi nào vấn đề bảo mật được khắc phục trong kernel ngược dòng, tôi phải đợi nhà cung cấp 3 bản vá đó phát hành bản cập nhật cho phiên bản kernel mới, mất từ ​​một đến sáu tháng, hoặc tôi phải tự duy trì việc ngược dòng bản vá bảo mật cho đến khi các nhà cung cấp bản vá khác bắt kịp.

Sau một vài năm, các nhà cung cấp quản lý để được đưa vào nguồn hạt nhân ngược dòng và tôi đã có thể dừng hành động cân bằng, nhưng bạn có thể thấy nó là một mớ hỗn độn trong thời gian đó. Đừng gây ra điều đó cho các lập trình viên của bạn trừ khi bạn phải làm vậy.


3

Không. Nó không phải là một kỹ thuật tiêu chuẩn để phát triển phần mềm. Nó vẫn là một cách giải quyết để giải quyết một vấn đề cấp tính và có những hạn chế rõ ràng. Vi phạm nguyên tắc thay thế Liskov đến với tâm trí. Khỉ vá làm cho nghiêm trọng hơn để lý do về các chương trình. Đối với các chương trình của riêng bạn, bạn nên đặt mã nơi nó thuộc về. Đối với lib của bên thứ ba, bạn sẽ luôn gặp nguy hiểm, bản vá của bạn sẽ không hoạt động với phiên bản lib tiếp theo.

Tất nhiên việc vá khỉ rất hữu ích nếu bạn biết bạn đang làm gì và không có thời gian để thực hiện giải pháp RẮN . Nhưng bạn không bao giờ nên coi đây là một kỹ thuật tiêu chuẩn và xây dựng bản vá khỉ trên bản vá khỉ.

BTW, bạn đã bao giờ viết một bài kiểm tra đơn vị cho một bản vá khỉ?


Tôi không nghĩ bạn có thể áp dụng LSP ở đây. Nó có một định nghĩa rất cụ thể liên quan đến các kiểu con.
Konrad Rudolph

@KonradRudolph Khỉ vá một đối tượng thay đổi loại của nó. Trong các ngôn ngữ được gõ động, mọi loại t có cùng giao diện với loại u là một kiểu con của u. Nếu nó đi như một con vịt ...
Scarfridge

Thay đổi loại hình của nó - đủ công bằng. Có ý nghĩa.
Konrad Rudolph

RE "Đây không phải là một kỹ thuật tiêu chuẩn để phát triển phần mềm.", Nó dường như được thực hiện * mọi lúc và trong các thư viện lớn "trong Python để thử nghiệm.
Tommy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.