ปลั๊กอินควรใช้อะไร: hooks เหตุการณ์หรืออย่างอื่น?


24

พิจารณาแอพที่อนุญาตให้ปลั๊กอินตอบสนองต่อโฟลว์ของโปรแกรม

ฉันรู้ 2 วิธีในการบรรลุเป้าหมายนี้: hooksและevents

1. ตะขอ

ใช้การเรียกฟังก์ชั่นที่ว่างเปล่าภายในผังโปรแกรมหลัก ฟังก์ชั่นเหล่านี้สามารถแทนที่ได้ด้วยปลั๊กอิน

ตัวอย่างเช่น Drupal CMS ใช้ฮุคที่พร้อมใช้งานกับโมดูลและธีม นี่คือตัวอย่างของวิธีการใช้เบ็ดในฟังก์ชั่น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;
    // ...
}

โมดูลสามารถใช้modulename_file_copy($file, $source)ฟังก์ชั่นซึ่งจะถูกเรียกโดยในmodule_invoke_all file_copyหลังจากฟังก์ชั่นนี้เสร็จสิ้นการfile_copyดำเนินการจะดำเนินการต่อ

2. กิจกรรม

มีแอปส่งกิจกรรมซึ่งสามารถฟังได้โดยปลั๊กอิน หลังจากได้รับอีเวนต์ที่สมัครเป็นสมาชิกแล้วปลั๊กอินจะขัดขวางการทำงานของโปรแกรมและดำเนินการตามความจำเป็น

ยกตัวอย่างเช่นแกลเลอรี่ jQuery ปลั๊กอิน Fotorama ดำเนินการหลายเหตุการณ์ ตัวอย่างเช่นต่อไปนี้เป็นส่วนหนึ่งของshowวิธีการที่ใช้ในการfotorama:showจัดกิจกรรม

  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.]
  };

สคริปต์สามารถฟังเหตุการณ์นี้และทำอะไรบางอย่างเมื่อไฟ:

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

คำถาม

  1. มีวิธีอื่นที่สำคัญในการใช้งานปลั๊กอินหรือไม่

  2. ถ้าไม่ควรใช้ตะขอเมื่อใดและเมื่อใดควรใช้เหตุการณ์เมื่อใด เมื่อพิจารณาถึงเป้าหมายสูงสุดคือการทำให้โค้ดสามารถดูแลและอ่านได้ง่ายขึ้นจากทั้งแอพและมุมมองของนักพัฒนาปลั๊กอิน

คำตอบ:


17

ความแตกต่างที่สำคัญระหว่างเบ็ดและเหตุการณ์คือการแต่งงานกันอย่างหลวม ๆ กับการแต่งงานกันอย่างแน่นหนา

เบ็ดเป็นวิธีทั่วไปในการถ่ายทอดสิ่งที่เกิดขึ้น คุณสามารถเพิ่ม hooks ใหม่โดยไม่ต้องคอมไพล์ปลั๊กอินใหม่และ hooks ทั้งหมดจะเป็นไปตามรูปแบบการออกแบบทั่วไป เมื่อ hook API ถูกกำหนดแล้วจะไม่เปลี่ยนแปลงดังนั้นการเชื่อมต่อระหว่างแอพและปลั๊กอินจะไม่แตก

อีเวนต์นั้นเชื่อมโยงกับแอปอย่างแน่นหนายิ่งขึ้น เหตุการณ์สามารถกำหนดพารามิเตอร์ที่แนบมากับเหตุการณ์และถ้าคุณเปลี่ยนพารามิเตอร์เหล่านั้นคุณทำลาย API ด้วยปลั๊กอินที่มีอยู่

พวกเขาทั้งสองบรรลุผลลัพธ์เดียวกัน ขึ้นอยู่กับว่าคุณต้องการเชื่อมต่อปลั๊กอินกับแอปอย่างไร

Hooks สามารถเสนอการเชื่อมต่อแบบไดนามิกที่ไม่น่าจะผิดเพราะแอพเวอร์ชั่นใหม่ของคุณจะเปิดตัว แต่ข้อเสียคือคุณไม่ได้รับคำเตือนเวลาคอมไพล์ว่าปลั๊กอินไม่สามารถใช้งานได้อีกต่อไป

เหตุการณ์เสนอความสามารถในการรวบรวมข้อผิดพลาดเวลาที่ปลั๊กอินต้องแก้ไขเนื่องจากลายเซ็นเหตุการณ์บางส่วนมีการเปลี่ยนแปลง

คุณขอวิธีการอื่น

คำสั่ง:

แทนที่จะเป็นปลั๊กอินที่ตอบสนองต่อเหตุการณ์ที่ถูกกระตุ้น ปลั๊กอินผลักดันวัตถุคำสั่งไปยังแอปพลิเคชัน แต่ละอ็อบเจ็กต์คำสั่งใช้อินเตอร์เฟสที่ใช้โดยคำสั่ง เมื่อแอปพลิเคชันต้องการเรียกใช้งานคุณสมบัติแอปพลิเคชันจะเรียกใช้คำสั่งทั้งหมดสำหรับคุณสมบัตินั้น สิ่งนี้คล้ายกับเหตุการณ์มากยกเว้นว่ามันจะถูกนำไปใช้เป็นวัตถุแทนที่จะเป็นฟังก์ชันการโทรกลับ

แมโคร:

แทนที่จะเป็นปลั๊กอินตอบสนองเมื่อสิ่งต่าง ๆ เกิดขึ้น ปลั๊กอินทำให้เกิดสิ่งต่าง ๆ ในเชิงรุก แมโครเป็นภาษาระดับสูงขนาดเล็กที่ทำงานอยู่เหนือแอปพลิเคชันซึ่งบอกว่าจะต้องทำอย่างไร

ผู้ฟังเปลี่ยนสถานะ:

เหตุการณ์ถูกเรียกใช้โดยแอปพลิเคชันโดยนักพัฒนาล่วงหน้า ผู้พัฒนาต้องเขียนโค้ดที่รู้เท่าทันเหตุการณ์ แต่วิธีการทางเลือกคือการทำให้วัตถุออกอากาศโดยอัตโนมัติเมื่อสถานะภายในของวัตถุเปลี่ยนแปลง ทั้งการเปลี่ยนแปลงของคุณสมบัติหรือตัวบ่งชี้อื่น ๆ ปลั๊กอินสามารถฟังการเปลี่ยนแปลงสถานะเฉพาะเหล่านี้และตอบสนองตามนั้น ข้อดีของวิธีนี้คือโปรแกรมเมอร์ไม่จำเป็นต้องจดจำเหตุการณ์ที่ออกอากาศ ตัวอย่างเช่นอาจมีวัตถุเอกสารและโปรแกรมเมอร์ตั้งค่าสถานะเพื่อทำเครื่องหมายว่าเอกสารจะต้องมีการบันทึก การเปลี่ยนสถานะนี้ถูกถ่ายทอดไปยังปลั๊กอินการฟังและอาจมีปลั๊กอินที่เปลี่ยนชื่อเอกสารเพื่อรวมเครื่องหมายดอกจัน


2
+1 สำหรับทางเลือก, -1 สำหรับคำจำกัดความและข้อโต้แย้งที่มีเพศสัมพันธ์ (ซึ่งไม่อยู่ แต่การมีเพศสัมพันธ์เป็นผลมาจากการออกแบบทางเลือกแล้วแต่จำนวนใดชื่อที่คุณให้กับระบบปลั๊กอินของคุณ)

5
ฉันคิดว่าคุณกำลังตั้งสมมติฐานเกี่ยวกับวิธีการที่เหตุการณ์เดินทางจากเครื่องกำเนิดไปยังผู้สังเกตการณ์ / ผู้ฟัง แท้ที่จริงแล้วมันเป็นสิ่งที่ตรงกันข้ามตะขอเป็นคู่อย่างแน่นหนาในขณะที่เหตุการณ์ไม่ได้
Ahmed Masud

3

เหตุการณ์ที่แน่นอนจะช่วยให้การนามธรรมที่จำเป็นอยู่แล้วในระดับสถาปัตยกรรม

อย่าคาดหวังว่าใครก็ตามที่เขียนปลั๊กอินจะทำเช่นนั้นตามที่ระบุไว้ในเอกสารหรือในทางที่ถูกต้อง ฉันยังคงรักษา API ที่มีเอกสารที่ดีกับผู้ใช้หลายล้านคนและฉันสามารถบอกคุณได้จากประสบการณ์ที่เจ็บปวดมากที่โดยทั่วไปไม่มีใครอ่านเอกสารและเกือบจะไม่มีใครใช้ API อย่างถูกต้อง

ทำตัวอย่างต่อไปนี้ด้วย hooks: คุณมีระบบที่ใช้งาน 20 plugins หนึ่งในปลั๊กอินเหล่านั้นเรียกfile_copyวิธีการในรูปแบบของเอกสารและคาดว่าผลลัพธ์จะได้รับการบันทึกไว้ แต่ปลั๊กอินอื่น ๆ บางอันมีฟังก์ชั่นดังกล่าวดังนั้นปัญหาข้อใดข้อหนึ่งต่อไปนี้จึงเป็นสาเหตุให้เกิดความผิดพลาดหรือความผิดปกติ:

  • ฟังก์ชั่นของ hook นั้นขัดข้อง ปลั๊กอินอื่น ๆ ทั้งหมดถูกขันในขณะนี้เพราะพวกเขาไม่สามารถ file_copy หรือฟังก์ชั่นการทำงานแตกต่างจากสิ่งที่คาดหวัง
  • อินพุตถูกต้องตามเอกสารประกอบ แต่ปลั๊กอินอื่นไม่คาดหวังและให้ผลลัพธ์หรือการขัดข้องที่ผิดปกติ
  • การเรียกใช้ทำงานได้ดี แต่ผลลัพธ์ไม่ได้เป็นไปตามที่กำหนดในเอกสารประกอบดังนั้นปลั๊กอินจึงล้มเหลวหรือล้มเหลว

หากคุณทำเช่นเดียวกับข้างต้นกับเหตุการณ์ที่มีปัญหาเดียวกันภายในปลั๊กอินเหล่านี้จะเกิดขึ้น:

  • ฟังก์ชันเหตุการณ์ของปลั๊กอิน X ล่ม แต่ส่วนอื่น ๆ ทั้งหมดทำงานได้ดี แต่เนื่องจากปลั๊กอินเหล่านั้นไม่เกี่ยวข้องกันคุณสามารถปิดการใช้งานปลั๊กอินหยุดทำงานนั้นได้ในขณะที่ปลั๊กอินอื่น ๆ ทำงานได้ดี
  • ฟังก์ชั่นของคุณสามารถจัดการอินพุตที่แปลกและคุณสามารถตรวจสอบสิ่งที่เป็นไปได้ทั้งหมดสำหรับแต่ละปลั๊กอินอย่างเหมาะสม นักพัฒนาปลั๊กอินในขณะนี้มีวิธีที่มั่นคงและเชื่อถือได้ในการทดสอบปลั๊กอินของเขาซึ่งช่วยให้เขามั่นใจได้ว่าถ้ามันทำงานให้เขามันจะทำงานสำหรับทุกคน หากมีปลั๊กอินหนึ่งที่ให้ข้อมูลที่ไม่ถูกต้องปลั๊กอินนั้นสามารถแยกออกจากปลั๊กอินนั้นได้
  • สามารถตรวจสอบและกำหนดผลลัพธ์ได้อย่างเท่าเทียมกันในทุกสถานการณ์ดังนั้นนักพัฒนาปลั๊กอินจึงมีคำตอบที่เสถียรและเชื่อถือได้จากฟังก์ชั่นนั้นที่เขา / เธอสามารถทดสอบได้

1

การสืบทอดอาจเป็นตัวเลือก

นอกเหนือจาก hooks แล้วการสืบทอดไม่ต้องการนิยามเพิ่มเติมของเมธอดและไม่มีการสูญเสียประสิทธิภาพสำหรับการเรียกเมธอดเปล่าในกรณีที่ไม่มีการเชื่อมต่อ

นอกเหนือจากเหตุการณ์แล้วการสืบทอดยังไม่จำเป็นต้องใช้รหัสเพิ่มเติมสำหรับการเรียกใช้กิจกรรม

อย่างไรก็ตามการสืบทอดจะทำงานได้ดีที่สุดหากมีเพียงปลั๊กอินเดียวที่แก้ไขพฤติกรรมประเภทหนึ่งได้ หากคุณต้องการปลั๊กอินจำนวนมากสิ่งที่สองต้องได้มาจากปลั๊กอินแรกซึ่งไม่เหมาะสม


-1 เพราะคุณใช้มรดกและจากนั้นเปลี่ยนรหัส instantiating ที่จะใช้สเปคและมรดกทางที่ผิดของคุณเป็นลักษณะการทำงานใหม่มีจุดประสงค์ที่แตกต่างกันเป็นโปรแกรมหลัก ...
SPARK

0

เหตุการณ์ที่แน่นอน ช่วยให้สถาปัตยกรรมของคุณสามารถปรับขยายได้กว้าง

ลองนึกภาพสิ่งที่จะเกิดขึ้นหากคุณต้องการวางปลั๊กอินของคุณไปยังเครื่องอื่นเช่น การใช้กิจกรรม - คุณเพียงแค่ต้องปรับเปลี่ยนโค้ดขนาดเล็กเพื่อสร้างเครือข่ายกิจกรรมของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.