2009-05-18 11 views
6

Tôi là một coder Ruby. Đối với tôi, monkeypatching là để thay đổi, ở thời gian chạy, các lớp hoặc các phương thức mô-đun trong một dự án bên ngoài. Những gì tôi quan tâm, là những gì cơ chế bạn có tại chỗ sẽ bảo vệ bạn khỏi một số sự lạm dụng của tính năng tốt đẹp đó. Follows, một số kịch bản mà tôi đã gặp phải, nơi monkeypatching đã cắn tôi.Làm thế nào để Smalltalk đối phó với monkeypatching?

Trong khi tôi không biết Smalltalk chút nào, ngôn ngữ đó đã có từ lâu trước khi Ruby. Tôi đã thực hiện một số nghiên cứu để xem liệu Smalltalk có giải quyết được một số vấn đề này hay không nhưng không tìm thấy nhiều trên Google. Vì vậy, ở đây tôi, yêu cầu Smalltalkers nếu họ có thể chia sẻ sự khôn ngoan của họ.

Kịch bản A: lỗi sửa chữa xung đột

dự án A và B phụ thuộc vào dự án C. Dự án C có một lỗi. Bản phát hành dự án A và B có bản sửa lỗi cho dự án C.

Nếu mã của bạn sử dụng Project A và B, làm cách nào bạn biết các bản vá sẽ không xung đột?

Kịch bản B: lỗi thời lỗi sửa chữa

Dự án C phát hành một phiên bản nhỏ cố định của dự án của họ.

Nếu bạn tải dự án A, bản vá sẽ vẫn được áp dụng, có khả năng vỡ? Tôi quan tâm để biết nếu có một số cơ chế tại chỗ, ví dụ, để không tải các bản vá nếu mã được cố định.

Kịch bản C: mâu thuẫn mở rộng

Dự án A và dự án sử dụng B lớp C của Foo. Cả hai đều thêm một phương thức tiện ích vào Foo, ví dụ: #toDate. Phiên bản toDate của A trả về một chuỗi ngày tháng và một đối tượng B là Ngày tháng.

Nếu bạn tải cả hai dự án (với C dep), có cơ chế cảnh báo/ngăn chặn xung đột không? Hoặc bạn sẽ phải chờ cho đến khi thời gian chạy ném một lỗi vì một kỳ vọng sai trong một phương pháp?

Về bản cập nhật câu hỏi

Đọc các câu trả lời, tôi nhận ra câu hỏi của tôi là quá rộng và mơ hồ. Vì vậy, đây là một phiên bản viết lại của nó.

+0

Khả năng khỉ thật sự có vấn đề không? – CookieOfFortune

+0

Những lời chỉ trích của bạn về monkeypatching có vẻ khá xa nhãn hiệu. Không có gì vốn có trong monkeypatching dẫn đến abstractions rò rỉ bất kỳ hơn trong thiết kế lớp học ban đầu. Cũng không phải là nó vốn có nhiều "crufty" hơn so với các mã khác. Việc tách một đối tượng thành các tệp khác nhau là đúng, mặc dù một số người cho rằng các mô-đun có thể quản lý là một điều tốt - thực tế, nó được coi là thực hành tốt để nhóm các chức năng liên quan trong Objective-C. Có lẽ vấn đề của bạn là nhiều hơn với các lập trình viên hơn là với các tính năng ngôn ngữ. – Chuck

+0

Trong bất kỳ cae nào, toàn bộ khái niệm về việc chia nhỏ mọi thứ thành các tệp riêng biệt là không đúng chỗ; smalltalk không làm theo cách đó. –

Trả lời

1

Nó nói "yeah! Đi cho nó!"

Toàn bộ khái niệm thực sự có thể xuất hiện trong Smalltalk trước.

Chuyển đến lớp gốc trong trình duyệt lớp và bạn có thể thêm tất cả các phương thức vào hình ảnh bạn muốn. Tuy nhiên, hãy nhớ rằng Smalltalk có một bức tranh rất khác về thế giới so với các ngôn ngữ thông thường khác (chỉ một ngôn ngữ thông dụng khác như Smalltalk là APL.) Bạn có một hình ảnh chứa toàn bộ mã và thời gian chạy. gói. Khi bạn thay đổi hình ảnh, mỗi bit mã trong hình ảnh sẽ bị ảnh hưởng. Các hình ảnh khác không thay đổi. Bạn có thể có các bộ thay đổi để tải lại các hacks yêu thích của mình, nhưng về cơ bản chúng đang nhập mã vào hình ảnh.

1

Smalltalkers không sử dụng thuật ngữ 'vá khỉ' nhưng tôi có cảm giác rằng 'ghi đè phương pháp' là thuật ngữ gần nhất.Nghĩa là, ghi đè lên một phương thức của một lớp trong gói A, với một phương thức của cùng một lớp trong gói B. Vì vậy, khi bạn tải một gói B, phương thức gốc trong A được ghi đè lên.

Ghi đè phương pháp có ưu điểm của chúng nhưng có nhiều lợi ích hơn khi không được sử dụng cẩn thận, vì vậy nói chung chúng tôi có xu hướng tránh chúng. Nó cũng phụ thuộc vào phương ngữ Smalltalk - trong VisualWorks ví dụ các công cụ hỗ trợ ghi đè khá tốt trong khi ở Squeak thì không.

+0

+1 để nhận biết tầm quan trọng của việc sử dụng thuật ngữ trong mỗi (phụ) văn hóa, -1 cho khó hiểu với phương pháp ghi đè (một điều hoàn toàn khác) – Javier

+0

Rõ ràng là không hoàn toàn khác nhau, sau khi đọc bài viết trên miếng vá khỉ trên Wikipedia. Vâng, có vẻ như trong Smalltalk chúng ta do đó khỉ vá chỉ đơn giản bằng cách thay đổi một số phương pháp trong một hình ảnh sống? Chúng tôi đang làm điều đó tất cả các thời gian anyway. –

+0

Trong Nhật báo nó thực sự giống nhau :) –

5

Trong Smalltalk, chúng tôi có truyền thống được gọi là ghi đè này. Tùy thuộc vào các công cụ kiểm soát phiên bản bạn sử dụng với Smalltalk, bạn hoặc là;

  • tạo ra một phiên bản mới của gói mà ban đầu thuộc sở hữu lớp/phương pháp (s) trong câu hỏi
  • tạo ra một gói phần mềm mới mà sẽ sở hữu ghi đè của lớp/phương pháp (s) trong câu hỏi

Trong VisualWorks và ObjectStudio (Smalltalk mà tôi quen thuộc nhất), cách tiếp cận thứ hai được sử dụng. Trong VA Smalltalk, nơi Envy được sử dụng, cách tiếp cận cũ được thực hiện. Tôi tin rằng Squeak sẽ làm theo cách tiếp cận thứ hai bằng cách sử dụng Monticello, nhưng tôi không hoàn toàn chắc chắn.

Trong hầu hết các triển khai Smalltalk, thật dễ dàng để xem cả phiên bản gốc của mã bị ghi đè và ghi đè hiện được cài đặt.

Trong ứng dụng khách, ghi đè thực sự chỉ tác động đến bạn khi bạn cập nhật phiên bản Smalltalk mới từ venor (hoặc nhóm Squeak, et al.). Đối với các ứng dụng máy chủ, nơi nhiều ứng dụng có thể nằm trong máy chủ, bạn cần phải cẩn thận hơn nhiều về những gì bạn quyết định làm.

Ghi đè (hoặc khỉ, như bạn gọi cho họ) là một công cụ mạnh mẽ, nhưng bạn cần phải cẩn thận về cách bạn sử dụng chúng - và nếu bạn sử dụng chúng, bạn nên kiểm tra lại xem bạn có cần chúng không một cách thường xuyên. Trong bộ tổng hợp tin tức nguồn mở của tôi, BottomFeeder, tôi đã xóa rất nhiều ghi đè mà tôi đã đặt ban đầu.

0

trả lời cho bản thân mình, đây là thời điểm hiện tại của tôi xem:

Kịch bản A và B

Vì tất cả các code đang mở, việc thực hành tốt nhất là để sửa chữa các dự án bị hỏng trực tiếp. Các công cụ như git quản lý hợp nhất mã đã có, vì vậy chúng tôi không cần phải dựa vào một hợp nhất thời gian chạy, điều đó sẽ không phải lúc nào cũng hoạt động.

Tùy thuộc vào sự sẵn sàng của thượng nguồn để hợp nhất sửa lỗi và tốc độ của bạn để phát hành phiên bản mới, bạn có thể hình dung để tạo ra một monkeypatch. Trong trường hợp đó, tốt nhất là nên có một cơ chế cho biết:

monkeypatch(ClassName, :method, &newcode) of the broken project 
is applied if project.version in [a set of releases where the bug exist] 
if the project version is unknown to the monkeypatch, 
    raise an error to tell the developer to fix the monkeypatch (check if bug exist). 
if a monkeypatch for that project, classname and method already exist, yell 

Đây là từ đỉnh đầu của tôi. Nó có thể là vấn đề nếu một bugfix đòi hỏi nhiều hơn một sự thay đổi phương pháp.

Kịch bản C: TODO

+0

Đối với kịch bản C, cách tốt nhất để tránh xung đột là sử dụng chọn tên vùng đệm, vì vậy nếu bạn có gói Foo và thanh gói, cả hai đều muốn mở rộng hành vi của một số lớp, như thêm phương thứC#toDate: , bạn mở rộng nó 2 lần: gói Foo mở rộng bằng cách sử dụng fooToDate: tên và thanh gói, - barToDate:. và sự cố đã biến mất :) –