Các plugin nên sử dụng: hook, sự kiện hoặc cái gì khác?


24

Hãy xem xét một ứng dụng cho phép các plugin phản ứng với luồng chương trình của nó.

Tôi biết 2 cách để đạt được điều này: mócsự kiện

1. Móc

Sử dụng các cuộc gọi đến các chức năng trống bên trong luồng chương trình chính. Các chức năng này có thể được ghi đè bằng các plugin.

Ví dụ, Drupal CMS thực hiện các hook có sẵn cho các mô-đun và chủ đề. Đây là một ví dụ về cách hook được thực hiện trong hàm file_copy .

function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
    // ... [File copying routine]

    // Inform modules that the file has been copied.
    module_invoke_all('file_copy', $file, $source);

    return $file;
    // ...
}

Một mô-đun có thể thực hiện một modulename_file_copy($file, $source)chức năng sẽ được gọi bởi module_invoke_allin file_copy. Sau khi chức năng này kết thúc, file_copysẽ tiếp tục thực hiện.

2. Sự kiện

Có các sự kiện gửi ứng dụng, có thể được nghe bởi các plugin. Sau khi nhận được một sự kiện mà nó đã được đăng ký, một plugin sẽ chặn luồng chương trình và thực hiện các hoạt động cần thiết.

Ví dụ, một plugin thư viện jQuery Fotorama thực hiện một số sự kiện . Ví dụ, đây là một phần của showphương thức fotorama:showtổ chức sự kiện này.

  that.show = function (options) {
    // ... [show the new frame]

    // [fire the event]
    options.reset || triggerEvent('show', {
      user: options.user,
      time: time
    });

    // ... [do lots of other stuff with navigation bars, etc.]
  };

Một kịch bản có thể nghe sự kiện này và làm một cái gì đó khi nó phát sinh:

$('.fotorama').on(
  'fotorama:show',
  function (e, fotorama, extra) {
    console.log(e.type + (extra.user ? ' after user’s touch' : ''));
    console.log('transition duration: ' + extra.time);
  }
);

CÂU HỎI

  1. Có những cách chủ đạo khác để thực hiện hành vi plugin như vậy?

  2. Nếu không, khi nào nên sử dụng móc, và khi nào nên sử dụng các sự kiện? Xem xét mục tiêu cuối cùng là làm cho mã dễ bảo trì và dễ đọc hơn, từ cả quan điểm của ứng dụng và nhà phát triển plugin?

Câu trả lời:


17

Sự khác biệt chính giữa một cái móc và sự kiện là khớp nối lỏng lẻo so với khớp nối chặt chẽ.

Một cái móc là một cách chung để phát sóng rằng một cái gì đó đã xảy ra. Bạn có thể thêm các hook mới mà không cần phải biên dịch lại các plugin và tất cả các hook đều theo một mẫu thiết kế chung. Khi API hook được xác định, nó sẽ không thay đổi, do đó, sự kết hợp giữa ứng dụng và plugin không có khả năng bị phá vỡ.

Các sự kiện được gắn chặt hơn với ứng dụng. Sự kiện có thể xác định các tham số được đính kèm với sự kiện và nếu bạn thay đổi các tham số đó, bạn sẽ phá vỡ API bằng các plugin hiện có.

Cả hai đều đạt được kết quả như nhau. Nó chỉ phụ thuộc vào cách bạn muốn kết hợp các plugin với ứng dụng.

Móc có thể cung cấp cho bạn một khớp nối năng động hơn không có khả năng bị phá vỡ khi các phiên bản mới của ứng dụng của bạn được phát hành, nhưng nhược điểm là bạn không nhận được bất kỳ cảnh báo thời gian biên dịch nào mà các plugin không còn tương thích.

Sự kiện cung cấp cho bạn khả năng nhận được các lỗi thời gian biên dịch mà plugin cần phải sửa đổi, vì một số chữ ký sự kiện đã thay đổi.

Bạn đã yêu cầu phương pháp thay thế.

Các lệnh:

Thay vì các plugin đáp ứng với các sự kiện được kích hoạt. Plugin đẩy các đối tượng lệnh vào ứng dụng. Mỗi đối tượng lệnh thực hiện một giao diện được sử dụng bởi các lệnh. Khi ứng dụng cần thực thi một tính năng, nó sẽ chạy tất cả các lệnh cho tính năng đó. Điều này rất giống với các sự kiện, ngoại trừ việc nó được triển khai như các đối tượng thay vì các hàm gọi lại.

Macro:

Thay vì các plugin đáp ứng khi mọi thứ xảy ra. Plugin chủ động gây ra sự việc. Macro là một ngôn ngữ cấp cao nhỏ chạy phía trên ứng dụng cho nó biết phải làm gì.

Người nghe thay đổi trạng thái:

Các sự kiện được kích hoạt bởi ứng dụng với sự suy nghĩ trước của nhà phát triển. Nhà phát triển phải cố ý viết mã phát hành sự kiện. Thay vào đó, một cách tiếp cận khác là làm cho các đối tượng tự động phát khi trạng thái bên trong của chúng thay đổi. Hoặc là sự thay đổi của một tài sản hoặc các chỉ số khác. Các plugin sau đó có thể lắng nghe những thay đổi trạng thái cụ thể này và phản ứng tương ứng. Ưu điểm của phương pháp này là lập trình viên không phải nhớ phát sóng các sự kiện. Ví dụ, có thể có một đối tượng Tài liệu và lập trình viên đặt cờ để đánh dấu rằng tài liệu cần được lưu. Thay đổi trạng thái này được phát đến các plugin nghe và có thể có một plugin thay đổi tiêu đề tài liệu để bao gồm dấu hoa thị.


2
1 cho các lựa chọn thay thế, -1 cho các định nghĩa và lập luận khớp nối (mà không tồn tại nhưng khớp nối là kết quả của sự lựa chọn thiết kế, bất cứ tên bạn cung cấp cho hệ thống plugin của bạn)

5
Tôi nghĩ rằng bạn cũng đang đưa ra các giả định về cách một sự kiện di chuyển từ máy phát đến người quan sát / người nghe. Như một vấn đề thực tế, nó là ngược lại, các móc được liên kết chặt chẽ trong khi các sự kiện thì không.
Ahmed Masud

3

Chắc chắn các sự kiện, nó cho phép sự trừu tượng cần thiết đã ở cấp độ kiến ​​trúc.

Đừng hy vọng rằng bất cứ ai viết một plugin thực sự làm như vậy là tài liệu hoặc theo bất kỳ cách nào chính xác. Tôi đã duy trì một API tài liệu tốt với hàng triệu người dùng và tôi có thể nói với bạn từ một trải nghiệm rất đau đớn mà về cơ bản không ai đọc tài liệu này và hầu như không ai sử dụng API chính xác.

Lấy ví dụ sau với hook: Bạn có một hệ thống có 20 plugin đang chạy. Một trong những plugin đó gọi file_copyphương thức theo cách nó được ghi lại và mong đợi một kết quả như được ghi lại. Nhưng một số plugin khác đã kết nối chức năng đó và do đó, một trong những vấn đề sau đây gây ra sự cố hoặc trục trặc:

  • Các chức năng móc chỉ đơn giản là sụp đổ. Tất cả các plugin khác hiện đang bị vặn, bởi vì chúng không còn có thể file_copy hoặc chức năng hoạt động khác với những gì được mong đợi.
  • Đầu vào là chính xác dựa trên tài liệu, nhưng các plugin khác không mong đợi nó và mang lại kết quả hoặc sự cố lạ.
  • Cuộc gọi chạy tốt, nhưng kết quả không còn như mong đợi theo tài liệu để plugin bị lỗi hoặc gặp sự cố.

Nếu bạn thực hiện tương tự như trên với các sự kiện có cùng các vấn đề bên trong các plugin đó, điều sau đây sẽ xảy ra:

  • Chức năng sự kiện của plugin X gặp sự cố, nhưng tất cả những thứ khác đều hoạt động tốt. Nhưng vì các plugin đó không liên quan, bạn chỉ cần vô hiệu hóa plugin bị lỗi đó trong khi các plugin khác tiếp tục hoạt động tốt.
  • Đầu vào kỳ lạ có thể được xử lý đúng bởi chức năng của bạn và bạn có thể kiểm tra chính xác tất cả những thứ có thể cho từng plugin riêng lẻ. Nhà phát triển plugin hiện có một cách ổn định và đáng tin cậy để thực sự kiểm tra plugin của mình, điều này cho phép anh ta chắc chắn rằng nếu nó hoạt động với anh ta thì nó sẽ hoạt động cho tất cả mọi người. Nếu một plugin cung cấp đầu vào không chính xác, nó có thể bị cô lập với một plugin đó.
  • Tương tự, kết quả có thể được kiểm tra và xác định đúng trong mọi trường hợp, vì vậy nhà phát triển plugin có câu trả lời ổn định và đáng tin cậy từ chức năng đó mà anh ấy / cô ấy có thể kiểm tra.

1

Kế thừa có thể là một lựa chọn.

Khác với hook, kế thừa không cần định nghĩa phương thức bổ sung và không mất hiệu năng khi gọi phương thức rỗng trong trường hợp không có gì được nối.

Khác với các sự kiện, kế thừa cũng không cần thêm mã cho việc gọi sự kiện.

Tuy nhiên, kế thừa hoạt động tốt nhất nếu chỉ có một plugin sửa đổi một loại hành vi. Nếu bạn cần nhiều plugin, cái thứ hai sẽ cần lấy từ cái thứ nhất, v.v., không phù hợp.


-1 Bởi vì bạn sử dụng Kế thừa và sau đó thay đổi mã khởi tạo để sử dụng đặc tả và sử dụng sai kế thừa của bạn vì hành vi mới có mục đích khác là ứng dụng chính ...
SparK

0

Chắc chắn các sự kiện. Nó cho phép kiến ​​trúc của bạn có khả năng mở rộng hơn.

Hãy tưởng tượng điều gì sẽ xảy ra nếu bạn cần đặt plugin của mình vào một máy riêng chẳng hạn. Sử dụng các sự kiện - bạn sẽ chỉ cần sửa đổi một chút an toàn mã để làm cho mạng sự kiện của bạn dựa trên.

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.