ที่อยู่ดาวน์โหลด ppt ppt: http://www.slideshare.net/jibyjohnc/jqquerysummit-largescale-javascript-application-architecture
หมายเหตุ: ในระหว่างกระบวนการเรียงลำดับฉันพบว่าความคิดของผู้เขียนซ้ำแล้วซ้ำอีกดังนั้นเขาจึงลบบางส่วน หากภาษาอังกฤษของคุณดีโปรดอ่าน PPT ภาษาอังกฤษโดยตรง
ต่อไปนี้เป็นบทหลักของบทความนี้:
1. "โปรแกรมขนาดใหญ่ JavaScript" คืออะไร?
2. พิจารณาสถาปัตยกรรมโปรแกรมปัจจุบัน
3. การพิจารณาระยะยาว
4. ระดมสมอง
5. สถาปัตยกรรมที่แนะนำ
5.1 รูปแบบการออกแบบ
5.1.1 ทฤษฎีโมดูล
5.1.1.1 ภาพรวม
5.1.1.2 โหมดโมดูล
5.1.1.3 ขนาดใบหน้าของตัวเอง
5.1.1.4 โมดูล CommonJS
5.1.2 โหมดซุ้ม
5.1.3 โหมดสื่อกลาง
5.2 ใช้กับสถาปัตยกรรมของคุณ
5.2.1 ซุ้ม - เป็นนามธรรมหลัก
5.2.2 Mediator - โปรแกรมหลัก
5.2.3 ทำงานอย่างใกล้ชิด
6. เผยแพร่ Pub/Sub Extension: กิจกรรมการลงทะเบียนอัตโนมัติ
7. ถาม - ตอบ
8. กิตติกรรมประกาศ
"โปรแกรมขนาดใหญ่ JavaScript" คืออะไร?
ก่อนที่เราจะเริ่มให้กำหนดว่าไซต์ JavaScript ขนาดใหญ่คืออะไร ผู้เชี่ยวชาญด้านการพัฒนา JS ที่มีประสบการณ์หลายคนก็ถูกท้าทายเช่นกัน บางคนบอกว่ารหัส JavaScript มากกว่า 100,000 บรรทัดถือว่ามีขนาดใหญ่และบางคนบอกว่ารหัส JavaScript ต้องมีขนาดมากกว่า 1MB ในความเป็นจริงไม่ถูกต้องเนื่องจากจำนวนรหัสไม่สามารถวัดได้ว่าเป็นจำนวนรหัสที่ติดตั้ง รหัส JS เล็กน้อยจำนวนมากสามารถเกิน 100,000 บรรทัดได้อย่างง่ายดาย
คำจำกัดความของฉันเกี่ยวกับ "ใหญ่" มีดังนี้ แม้ว่ามันอาจจะไม่ถูกต้อง แต่ก็ควรจะใกล้ชิด:
โดยส่วนตัวแล้วฉันคิดว่าโปรแกรม JavaScript ขนาดใหญ่ควรมีความสำคัญมากและรวมความพยายามของนักพัฒนาที่โดดเด่นจำนวนมากในการประมวลผลข้อมูลเฮฟวี่เวทและแสดงไปยังเบราว์เซอร์
ตรวจสอบสถาปัตยกรรมโปรแกรมปัจจุบัน
ฉันไม่สามารถเน้นว่าปัญหานี้สำคัญแค่ไหน นักพัฒนาที่มีประสบการณ์หลายคนมักจะพูดว่า "รูปแบบความคิดสร้างสรรค์และการออกแบบที่มีอยู่ทำงานได้ดีในโครงการขนาดกลางก่อนหน้าของฉันดังนั้นจึงควรใช้พวกเขาอีกครั้งในโปรแกรมที่ใหญ่กว่าเล็กน้อยใช่มั้ย" มันเป็นความจริงในบางโปรแกรม แต่อย่าลืมว่าเนื่องจากเป็นโปรแกรมขนาดใหญ่ ฉันอธิบายสั้น ๆ ว่าต้องใช้เวลาในการตรวจสอบสถาปัตยกรรมโปรแกรมที่ทำงานมานานแล้ว ในกรณีส่วนใหญ่สถาปัตยกรรมโปรแกรม JavaScript ปัจจุบันควรมีลักษณะเช่นนี้ (โปรดทราบว่าเป็นสถาปัตยกรรม JS ไม่ใช่สิ่งที่ทุกคนมักเรียกว่า ASP.NET MVC):
วิดเจ็ตที่กำหนดเอง
แบบจำลอง
มุมมอง
ผู้ควบคุม
เทมเพลต
ห้องสมุด/ชุดเครื่องมือ
แกนแอปพลิเคชัน
นอกจากนี้คุณยังสามารถห่อหุ้มโปรแกรมไว้ในหลายโมดูลเพียงอย่างเดียวหรือใช้รูปแบบการออกแบบอื่น ๆ ซึ่งยอดเยี่ยม แต่ถ้าโครงสร้างเหล่านี้แสดงถึงสถาปัตยกรรมของคุณอย่างสมบูรณ์อาจมีปัญหาที่อาจเกิดขึ้น มาดูประเด็นสำคัญสองสามข้อ:
1. มีกี่สิ่งในสถาปัตยกรรมของคุณที่สามารถนำออกและนำกลับมาใช้ใหม่ได้ทันที?
มีโมดูลแยกต่างหากที่ไม่ได้ขึ้นอยู่กับรหัสอื่นหรือไม่? มันอยู่ในตัวเองหรือไม่? ถ้าฉันไปที่ฐานรหัสที่คุณใช้แล้วเลือกรหัสโมดูลบางอย่างและวางไว้ในหน้าใหม่จะสามารถใช้งานได้ทันทีหรือไม่? คุณอาจบอกว่าหลักการก็โอเค ฉันขอแนะนำให้คุณวางแผนเป็นเวลานาน หาก บริษัท ของคุณได้พัฒนาโปรแกรมที่สำคัญหลายอย่างมาก่อนวันหนึ่งมีคนบอกว่าโมดูลแชทในโครงการนี้ดีลองนำมันออกมาและนำไปใช้ในโครงการอื่น คุณสามารถใช้มันได้โดยไม่ต้องแก้ไขรหัสได้หรือไม่?
2. ระบบต้องพึ่งพาโมดูลอื่นกี่โมดูล?
โมดูลทั้งหมดของระบบคู่กันแน่นหรือไม่? ก่อนที่ฉันจะใช้คำถามนี้เป็นข้อกังวลฉันจะอธิบายก่อน ไม่ใช่ว่าโมดูลทั้งหมดจะต้องไม่มีการพึ่งพาใด ๆ ตัวอย่างเช่นฟังก์ชั่นเนื้อละเอียดอาจขยายออกจากฟังก์ชันพื้นฐาน ปัญหาของฉันแตกต่างจากสถานการณ์นี้ ฉันกำลังพูดถึงการพึ่งพาก่อนโมดูลการทำงานที่แตกต่างกัน ในทางทฤษฎีโมดูลการทำงานที่แตกต่างกันทั้งหมดไม่ควรมีการพึ่งพามากเกินไป
3. หากมีอะไรผิดปกติกับส่วนหนึ่งของโปรแกรมของคุณส่วนอื่น ๆ จะยังทำงานอยู่หรือไม่?
หากคุณสร้างโปรแกรมที่คล้ายกับ Gmail คุณจะพบว่ามีโมดูลจำนวนมากใน Gmail โหลดแบบไดนามิกเช่นโมดูลแชทแชทซึ่งไม่ได้โหลดเมื่อเริ่มต้นหน้าเว็บและแม้ว่าจะมีข้อผิดพลาดเกิดขึ้นหลังจากโหลดส่วนอื่น ๆ ของหน้าสามารถใช้งานได้ตามปกติ
4. คุณสามารถทดสอบโมดูลของคุณด้วยวิธีที่ง่ายมากได้หรือไม่?
แต่ละโมดูลของคุณอาจใช้ในไซต์ขนาดใหญ่ที่มีผู้ใช้หลายล้านคนหรือแม้กระทั่งหลาย ๆ ไซต์ใช้ดังนั้นโมดูลของคุณจำเป็นต้องยืนการทดสอบนั่นคือไม่ว่าจะเป็นภายในหรือภายนอกสถาปัตยกรรมพวกเขาควรจะสามารถทดสอบได้ง่ายๆรวมถึงการยืนยันส่วนใหญ่ที่สามารถส่งผ่านในสภาพแวดล้อมที่แตกต่างกัน
การพิจารณาระยะยาว
เมื่อจัดโครงสร้างโปรแกรมขนาดใหญ่สิ่งที่สำคัญที่สุดคือการคาดการณ์ล่วงหน้า คุณไม่สามารถพิจารณาสถานการณ์ได้เพียงหนึ่งเดือนหรือหนึ่งปีต่อมา คุณควรพิจารณาความเป็นไปได้ของการเปลี่ยนแปลงในระยะเวลานานหรือไม่? นักพัฒนามักจะผูกรหัสการดำเนินงาน DOM และโปรแกรมให้แน่นเกินไปแม้ว่าบางครั้งพวกเขาจะมีตรรกะที่แยกออกจากกันในโมดูลที่แตกต่างกัน ลองคิดดูว่าทำไมมันถึงไม่ดีมากในระยะยาว
เพื่อนร่วมงานของฉันเคยกล่าวไว้ว่าสถาปัตยกรรมที่ถูกต้องอาจไม่เหมาะสำหรับสถานการณ์ในอนาคตและบางครั้งก็ถูกต้อง แต่เมื่อคุณต้องทำคุณจะจ่ายเงินเป็นจำนวนมาก ตัวอย่างเช่นคุณอาจต้องเลือกที่จะแทนที่ Dojo, JQuery, Zepto และ Yui เพื่อประสิทธิภาพการรักษาความปลอดภัยและเหตุผลการออกแบบ ในเวลานี้มีปัญหา โมดูลส่วนใหญ่มีการพึ่งพาซึ่งต้องใช้เงินเวลาและผู้คนใช่ไหม?
ไม่เป็นไรสำหรับเว็บไซต์เล็ก ๆ บางแห่ง แต่ไซต์ขนาดใหญ่จำเป็นต้องมีกลไกที่ยืดหยุ่นมากขึ้นโดยไม่ต้องกังวลเกี่ยวกับปัญหาต่าง ๆ ระหว่างโมดูลต่างๆ สิ่งนี้ช่วยประหยัดเงินและเวลา
ในการสรุปตอนนี้คุณสามารถแน่ใจได้ว่าคุณสามารถแทนที่ไลบรารีคลาสบางส่วนโดยไม่ต้องเขียนโปรแกรมทั้งหมดใหม่หรือไม่? ถ้าไม่เช่นนั้นสิ่งที่เราจะพูดถึงด้านล่างนั้นเหมาะสมกว่าสำหรับคุณ
นักพัฒนาจาวาสคริปต์ที่มีประสบการณ์หลายคนได้รับบันทึกสำคัญบางประการ:
Justin Meyer ผู้แต่ง JavaScriptMVC กล่าวว่า:
ความลับที่ยิ่งใหญ่ที่สุดในการสร้างโปรแกรมขนาดใหญ่คือคุณไม่เคยสร้างโปรแกรมขนาดใหญ่ แต่แบ่งโปรแกรมออกเป็นโมดูลขนาดเล็กเพื่อให้โมดูลขนาดเล็กแต่ละตัวทดสอบได้มากขนาดใหญ่แล้วรวมเข้ากับโปรแกรม
JavaScript เว็บไซต์ประสิทธิภาพสูงผู้แต่ง Nicholas, Zakas:
"กุญแจสำคัญคือการรับทราบตั้งแต่เริ่มต้นว่าคุณไม่รู้ว่าสิ่งนี้จะเติบโตได้อย่างไรเมื่อคุณยอมรับว่าคุณไม่รู้ทุกอย่างคุณเริ่มออกแบบระบบป้องกันคุณระบุพื้นที่สำคัญที่อาจเปลี่ยนแปลงซึ่งมักจะง่ายมากเมื่อคุณใช้เวลาเล็กน้อย -
ปัญหาข้อความมากมายลำบากเกินไป โดยสรุปแล้วทุกอย่างสามารถเปลี่ยนแปลงได้ดังนั้นจึงต้องเป็นนามธรรม
JQUERY FUINDAMENTALS REBECCA MURPHEY:
ยิ่งการเชื่อมต่อระหว่างแต่ละโมดูลใกล้เข้ามามากเท่าไหร่ก็ยิ่งสามารถนำกลับมาใช้ใหม่ได้น้อยลงและยิ่งมีความยากลำบากในการเปลี่ยนแปลงมากขึ้นเท่านั้น
มุมมองที่สำคัญข้างต้นเป็นองค์ประกอบหลักของการสร้างสถาปัตยกรรมและเราต้องจดจำพวกเขาตลอดเวลา
การระดมสมอง
มาระดมสมองกันเถอะ เราต้องการสถาปัตยกรรมคู่ที่หลวมโดยไม่มีการพึ่งพาระหว่างโมดูลแต่ละโมดูลและโปรแกรมสื่อสารจากนั้นเลเยอร์กลางจะเข้ามาแทนที่และประมวลผลข้อความที่เกี่ยวข้อง
ตัวอย่างเช่นหากเรามีจาวาสคริปต์สร้างโปรแกรมเบเกอรี่ออนไลน์โมดูลจะส่งข้อความที่อาจเป็น "มี 42 รอบที่ต้องส่งมอบ" เราใช้เลเยอร์เลเยอร์ที่แตกต่างกันเพื่อประมวลผลข้อความที่ส่งโดยโมดูลและทำสิ่งต่อไปนี้:
โมดูลไม่สามารถเข้าถึงแกนโปรแกรมโดยตรง
โมดูลไม่โทรโดยตรงหรือส่งผลกระทบต่อโมดูลอื่น ๆ
สิ่งนี้จะป้องกันไม่ให้เราทำผิดพลาดในโมดูลทั้งหมดเนื่องจากข้อผิดพลาดในโมดูลที่แน่นอน
ปัญหาอีกประการหนึ่งคือความปลอดภัย สถานการณ์ที่แท้จริงคือคนส่วนใหญ่ไม่คิดว่าความปลอดภัยภายในเป็นปัญหา เราพูดในใจของเราว่าโปรแกรมถูกสร้างขึ้นด้วยตัวเอง ฉันรู้ว่าคนไหนเป็นของสาธารณะและเป็นส่วนตัว ไม่มีปัญหาเกี่ยวกับความปลอดภัย แต่คุณมีวิธีกำหนดโมดูลใดในการเข้าถึงโปรแกรมหลักของโปรแกรมหรือไม่? ตัวอย่างเช่นมีโมดูลแชทแชทที่ฉันไม่ต้องการให้เรียกโมดูลผู้ดูแลระบบหรือฉันไม่ต้องการให้เรียกโมดูลที่มีการอนุญาตให้เขียนฐานข้อมูลเนื่องจากมีความเปราะบางระหว่างพวกเขาและเป็นเรื่องง่ายที่จะทำให้เกิดการโจมตี XSS แต่ละโมดูลไม่สามารถทำทุกอย่างได้ แต่รหัส JavaScript ในสถาปัตยกรรมส่วนใหญ่ในปัจจุบันมีปัญหานี้ จัดเตรียมเลเยอร์ระดับกลางเพื่อควบคุมโมดูลที่สามารถเข้าถึงส่วนที่ได้รับอนุญาตนั่นคือโมดูลสามารถบรรลุส่วนที่เราได้รับอนุญาตมากที่สุดเท่านั้น
สถาปัตยกรรมที่แนะนำ
จุดเน้นของบทความของเราคือเวลานี้สถาปัตยกรรมที่เราเสนอใช้รูปแบบการออกแบบที่เราทุกคนเป็นที่รู้จักกันดี: โมดูลอาคารและผู้ไกล่เกลี่ย
ซึ่งแตกต่างจากโมเดลดั้งเดิมเพื่อแยกแต่ละโมดูลเราปล่อยให้โมดูลเผยแพร่เหตุการณ์บางอย่างเท่านั้น โหมดสื่อกลางสามารถรับผิดชอบในการสมัครรับข้อความข้อความจากโมดูลเหล่านี้จากนั้นควบคุมการตอบสนองการแจ้งเตือน ผู้ใช้โหมดด้านหน้า จำกัด การอนุญาตของแต่ละโมดูล
ต่อไปนี้เป็นส่วนที่เราต้องใส่ใจ:
1 รูปแบบการออกแบบ
1.1 ทฤษฎีโมดูล
1.1.1 ภาพรวม
1.1.2 โหมดโมดูล
1.1.3 ขนาดหน้าตาตัวเอง
1.1.4 โมดูล CommonJS
1.2 โหมดซุ้ม
1.3 โหมดสื่อกลาง
2 ใช้กับสถาปัตยกรรมของคุณ
2.1 ซอง - นามธรรมหลัก
2.2 Mediator - Program Core
2.3 ทำงานร่วมกันอย่างใกล้ชิด
ทฤษฎีโมดาล
ทุกคนอาจใช้รหัสโมดูลาร์ไม่มากก็น้อย โมดูลเป็นส่วนหนึ่งของสถาปัตยกรรมโปรแกรมที่สมบูรณ์และมีประสิทธิภาพ แต่ละโมดูลถูกสร้างขึ้นเพื่อวัตถุประสงค์แยกต่างหาก กลับไปที่ Gmail มาเป็นตัวอย่าง โมดูลแชทแชทดูเหมือนจะเป็นส่วนที่แยกต่างหาก แต่ในความเป็นจริงมันมี submodules แยกต่างหากมากมาย ตัวอย่างเช่นโมดูลนิพจน์ภายในนั้นเป็น submodule แยกต่างหากซึ่งใช้ในหน้าต่างเพื่อส่งอีเมล
อีกประการหนึ่งคือโมดูลสามารถโหลดลบและแทนที่แบบไดนามิก
ใน JavaScript เรามีหลายวิธีในการใช้โมดูล ทุกคนคุ้นเคยกับรูปแบบโมดูลและตัวอักษรวัตถุ หากคุณคุ้นเคยกับสิ่งเหล่านี้แล้วโปรดเพิกเฉยต่อส่วนนี้และข้ามไปยังส่วน CommonJS โดยตรง
โหมดโมดูล
รูปแบบโมดูลเป็นรูปแบบการออกแบบที่ค่อนข้างเป็นที่นิยม มันสามารถห่อหุ้มตัวแปรส่วนตัววิธีการและสถานะผ่านการจัดฟัน โดยการห่อเนื้อหาเหล่านี้โดยทั่วไปวัตถุทั่วโลกไม่สามารถเข้าถึงได้โดยตรง ในรูปแบบการออกแบบนี้มีการส่งคืน API เพียงครั้งเดียวและเนื้อหาอื่น ๆ ทั้งหมดจะถูกห่อหุ้มเป็นส่วนตัว
นอกจากนี้รูปแบบนี้คล้ายกับการแสดงออกของฟังก์ชั่นที่ดำเนินการด้วยตนเอง ความแตกต่างเพียงอย่างเดียวคือโมดูลส่งคืนวัตถุในขณะที่นิพจน์ฟังก์ชั่นที่ดำเนินการด้วยตนเองส่งคืนฟังก์ชัน
อย่างที่เราทราบกันดีว่า JavaScript ไม่ต้องการให้ภาษาอื่นมีตัวดัดแปลงการเข้าถึงและไม่สามารถประกาศตัวดัดแปลงส่วนตัวและสาธารณะสำหรับแต่ละฟิลด์หรือวิธีการ แล้วเราจะใช้รูปแบบนี้ได้อย่างไร? นั่นคือการส่งคืนวัตถุรวมถึงวิธีการสาธารณะบางอย่างซึ่งมีความสามารถในการเรียกวัตถุภายใน
ดูรหัสด้านล่าง รหัสนี้เป็นรหัสที่ดำเนินการด้วยตนเอง การประกาศรวมถึงวัตถุทั่วโลก batterymodule อาร์เรย์ตะกร้าเป็นส่วนตัวดังนั้นโปรแกรมทั้งหมดของคุณจึงไม่สามารถเข้าถึงอาร์เรย์ส่วนตัวนี้ได้ ในเวลาเดียวกันเราส่งคืนวัตถุซึ่งมี 3 วิธี (เช่น addItem, getItemCount, getTotal) 3 วิธีเหล่านี้สามารถเข้าถึงอาร์เรย์ตะกร้าส่วนตัวได้
var basketModule = (function () {var basket = []; // privatereturn {// สัมผัสกับ public additem: ฟังก์ชัน (ค่า) {basket.push (ค่า);}, getItemCount: function () {return basket.length;}, getTotal: function () } return p;}}} ());นอกจากนี้โปรดทราบว่าวัตถุที่เราส่งคืนจะถูกกำหนดโดยตรงไปยัง BasketModule ดังนั้นเราจึงสามารถใช้มันได้ดังต่อไปนี้:
// BasketModule เป็นวัตถุที่มีคุณสมบัติซึ่งสามารถเป็น methodsbasketModule.additem ({item: 'ขนมปัง' ราคา: 0.5}); basketmodule.additem ({item: 'butter', ราคา: 0.3}); console.log (basketmodule.getItemCount ()); console.log (basketmodule.getTotal ()); // อย่างไรก็ตามสิ่งต่อไปนี้จะไม่ทำงาน: console.log (basketmodule.basket); // (ไม่ได้กำหนดว่าไม่อยู่ในวัตถุที่ส่งคืน) console.log (ตะกร้า); // (มีอยู่ภายในขอบเขตของการปิดเท่านั้น)ดังนั้นในห้องสมุดชั้นเรียนยอดนิยมที่หลากหลาย (เช่น Dojo, jQuery) ได้อย่างไร?
โดโจ
Dojo พยายามใช้ dojo.declare เพื่อให้วิธีการประกาศสไตล์ชั้นเรียน เราสามารถใช้มันเพื่อใช้รูปแบบโมดูล ตัวอย่างเช่นหากคุณต้องการประกาศวัตถุตะกร้าใต้เนมสเปซร้านค้าคุณสามารถทำได้:
// ร้านค้า Wayvar แบบดั้งเดิม = window.store || {}; store.basket = store.basket || - // การใช้ dojo.setObjectDojo.setObject ("store.basket.Object", (function () {var basket = []; function privateMethod () {console.log (ตะกร้า);} return {publicmethod: function () {privateMethod ();}};มันมีพลังมากเมื่อรวมกับ dojo.rovide
Yui
รหัสต่อไปนี้คือการใช้งานดั้งเดิมของ YUI:
yahoo.store.basket = function () {// ตัวแปร "ส่วนตัว": var myprivatevar = "ฉันสามารถเข้าถึงได้เฉพาะภายใน yahoo.store.basket"; // วิธีการ "ส่วนตัว": var myPrivateMethod = function () {yahoo.log ("ฉันสามารถเข้าถึงได้จากภายใน yahoo.store.basket"); } return {MyPublicProperty: "ฉันเป็นทรัพย์สินสาธารณะ", MyPublicMethod: function () {yahoo.log ("ฉันเป็นวิธีการสาธารณะ"); // ภายในตะกร้าฉันสามารถเข้าถึง vars และวิธีการส่วนตัว "และวิธีการ: yahoo.log (myprivatevar); yahoo.log (myprivateMethod ()); // ขอบเขตดั้งเดิมของ MyPublicMethod เป็นร้านค้าเพื่อให้เราสามารถ // เข้าถึงสมาชิกสาธารณะโดยใช้ "this": yahoo.log (this.mypublicProperty); -jQuery
มีการใช้งานรูปแบบโมดูลมากมายใน jQuery ลองมาดูตัวอย่างที่แตกต่างกัน ฟังก์ชั่นไลบรารีประกาศไลบรารีใหม่ จากนั้นเมื่อสร้างไลบรารีเมธอด init จะถูกดำเนินการโดยอัตโนมัติใน document.ready
ฟังก์ชั่นไลบรารี (โมดูล) {$ (ฟังก์ชัน () {if (module.init) {module.init ();}}); return module;} var mylibrary = library (function () {return {init: function () { /*การใช้งาน* /}};} ());ขนาดหน้าเอง
การวัดการวัดใบหน้าด้วยตนเองของวัตถุถูกประกาศในวงเล็บปีกกาและไม่จำเป็นต้องใช้คำหลักใหม่เมื่อใช้งาน หากคุณไม่สนใจเกี่ยวกับฟิลด์สาธารณะ/ส่วนตัวของฟิลด์แอตทริบิวต์ในโมดูลคุณสามารถใช้วิธีนี้ได้ แต่โปรดทราบว่าวิธีนี้แตกต่างจาก JSON วัตถุขนาดตัวเองขนาด: var item = {ชื่อ: "tom", ค่า: 123} json: var item = {"name": "tom", "value": 123}
var mymodule = {myProperty: 'somevalue', // ตัวอักษรวัตถุสามารถมีคุณสมบัติและวิธีการ // ที่นี่วัตถุอื่นถูกกำหนดไว้สำหรับการกำหนดค่า // วัตถุประสงค์: myConfig: {usecaching: true, ภาษา: 'en'}, // วิธีพื้นฐานมาก mymethod: function () {console.log ('ฉันสามารถฟังก์ชั่น HAZ ได้?'); }, // ส่งออกค่าตามการกำหนดค่าปัจจุบัน myMethod2: function () {console.log ('แคชคือ:' + (this.myconfig.usecaching)? 'เปิดใช้งาน': 'ปิดใช้งาน'); }, // แทนที่การกำหนดค่าปัจจุบัน myMethod3: ฟังก์ชั่น (newConfig) {ถ้า (typeof newConfig == 'object') {this.myconfig = newConfig; console.log (this.myconfig.language); - mymodule.mymethod (); // ฉันสามารถฟังก์ชั่น HAZ MyModule.MyMetHod2 (); // outputs enabledMyModule.mymethod3 ({ภาษา: 'fr', usecaching: false}); // frสามัญชน
ฉันจะไม่พูดถึงการแนะนำของ CommonJs ที่นี่ บทความจำนวนมากได้แนะนำมาก่อน สิ่งที่เราต้องการพูดถึงที่นี่คือมีการส่งออกพารามิเตอร์ที่สำคัญสองตัวและต้องการในมาตรฐาน CommonJS การส่งออกแสดงถึงโมดูลที่จะโหลดและต้องการหมายความว่าโมดูลที่โหลดเหล่านี้จำเป็นต้องพึ่งพาโมดูลอื่น ๆ และต้องโหลดด้วย
/*ตัวอย่างของการบรรลุความเข้ากันได้กับ AMD และมาตรฐาน CommonJs โดยการวางหม้อต้มรอบรูปแบบโมดูล CommonJS มาตรฐาน:*/(ฟังก์ชั่น (กำหนด) {define (ฟังก์ชั่น (ต้องการ, การส่งออก) {// เนื้อหาโมดูล var dep1 = ต้องการ ("dep1"); define == "function"? define: ฟังก์ชั่น (โรงงาน) {โรงงาน (ต้องการ, การส่งออก)});มีการใช้งานโมดูลมาตรฐาน CommonJS มากมาย สิ่งที่ฉันชอบคือต้องการ Js มันสามารถโหลดโมดูลและโมดูลการพึ่งพาที่เกี่ยวข้องได้ดีมากหรือไม่? มาเป็นตัวอย่างง่ายๆ ตัวอย่างเช่นหากคุณต้องการแปลงภาพเป็นรหัส ASCII เราจะโหลดโมดูลตัวเข้ารหัสก่อนจากนั้นรับวิธี encodetoascii ในทางทฤษฎีรหัสควรมีดังนี้:
var encodetoascii = ต้องการ ("encoder"). encodetoascii; exports.encodesomesource = function () {// หลังจากการดำเนินการอื่น ๆ จากนั้นเรียก encodetoascii}อย่างไรก็ตามรหัสข้างต้นไม่ทำงานเนื่องจากฟังก์ชั่น encodetoascii ไม่ได้ใช้เพื่อแนบกับวัตถุหน้าต่างดังนั้นจึงไม่สามารถใช้งานได้ นี่คือสิ่งที่การปรับปรุงรหัสต้องทำ:
กำหนด (ฟังก์ชั่น (ต้องการ, การส่งออก, โมดูล) {var encodetoascii = ต้องการ ("encoder"). encodetoascii; exports.encodesomesource = function () {// กระบวนการจากนั้นเรียกใช้ encodetoascii}});CommonJS มีศักยภาพที่ดี แต่เนื่องจากลุงไม่คุ้นเคยกับมันมากฉันจะไม่แนะนำมันมากนัก
โหมดซุปเปอร์
โมเดลด้านหน้ามีบทบาทสำคัญในสถาปัตยกรรมของรุ่นนี้ ไลบรารีหรือเฟรมเวิร์กคลาส JavaScript จำนวนมากสะท้อนให้เห็นในรุ่นนี้ ฟังก์ชั่นที่ใหญ่ที่สุดคือการรวม API ของระดับสูงเพื่อซ่อนการใช้งานเฉพาะ ซึ่งหมายความว่าเราจะเปิดเผยอินเทอร์เฟซเท่านั้นและเราสามารถทำการตัดสินใจของการใช้งานภายในด้วยตัวเองซึ่งหมายความว่ารหัสการใช้งานภายในสามารถแก้ไขและปรับปรุงได้อย่างง่ายดาย ตัวอย่างเช่นวันนี้คุณใช้ jQuery เพื่อนำไปใช้และพรุ่งนี้คุณต้องการเปลี่ยน Yui ซึ่งสะดวกมาก
ในตัวอย่างต่อไปนี้เราจะเห็นว่าเรามีวิธีการส่วนตัวมากมายจากนั้นเปิดเผย API อย่างง่ายเพื่อให้โลกภายนอกดำเนินการและเรียกใช้วิธีการภายใน:
var module = (function () {var _private = {i: 5, get: function () {console.log ('ค่าปัจจุบัน:' + this.i);}, set: function (val) {this.i = val;}, run: function () {console.log ( ฟังก์ชั่น (args) {_private.set (args.val); _private.get ();ความแตกต่างระหว่างซุ้มและสิ่งที่เรากำลังพูดถึงด้านล่างคือด้านหน้านั้นมีฟังก์ชั่นที่มีอยู่เท่านั้นในขณะที่ผู้ไกล่เกลี่ยสามารถเพิ่มฟังก์ชั่นใหม่ได้
โหมดสื่อกลาง
ก่อนที่จะพูดคุยเกี่ยวกับผู้ดัดแปลงให้ยกตัวอย่าง ระบบควบคุมการบินสนามบินซึ่งเป็นหอคอยในตำนานมีพลังงานแน่นอน มันสามารถควบคุมเวลาบินขึ้นและลงจอดและสถานที่ของเครื่องบินใด ๆ เครื่องบินและเครื่องบินไม่ได้รับอนุญาตให้สื่อสารมาก่อนซึ่งหมายความว่าหอคอยเป็นแกนหลักของสนามบินและผู้ไกล่เกลี่ยเทียบเท่ากับหอคอยแห่งนี้
ผู้ไกล่เกลี่ยใช้เพื่อมีหลายโมดูลในโปรแกรมและคุณไม่ต้องการให้แต่ละโมดูลมีการอ้างอิงจากนั้นโหมดสื่อกลางสามารถบรรลุวัตถุประสงค์ของการควบคุมส่วนกลาง ในสถานการณ์จริงผู้ไกล่เกลี่ยห่อหุ้มโมดูลจำนวนมากที่พวกเขาไม่ต้องการทำทำให้พวกเขาสามารถเชื่อมต่อผ่านผู้ไกล่เกลี่ยและคู่กันอย่างหลวม ๆ เพื่อให้พวกเขาต้องสื่อสารผ่านผู้ไกล่เกลี่ย
แล้วข้อดีของโหมดสื่อกลางคืออะไร? นั่นคือ decoupling หากคุณมีความเข้าใจที่ดีเกี่ยวกับรูปแบบผู้สังเกตการณ์มาก่อนมันจะค่อนข้างง่ายที่จะเข้าใจแผนภาพสื่อกลางด้านล่าง รูปต่อไปนี้เป็นแผนภาพรูปแบบตัวกลางระดับสูง:
คิดเกี่ยวกับมันแต่ละโมดูลเป็นสำนักพิมพ์และผู้ไกล่เกลี่ยเป็นทั้งสำนักพิมพ์และสมาชิก
โมดูล 1 ออกอากาศสิ่งที่เกิดขึ้นจริงไปยังผู้ไกล่เกลี่ยโดยพูดบางสิ่งบางอย่างที่ต้องทำ
หลังจากผู้ไกล่เกลี่ยจับข้อความให้เริ่มโมดูล 2 ทันทีที่ต้องใช้ในการประมวลผลข้อความ หลังจากการประมวลผลโมดูล 2 เสร็จสมบูรณ์ให้ส่งคืนข้อมูลไปยังผู้ไกล่เกลี่ย
ในเวลาเดียวกันผู้ไกล่เกลี่ยก็เริ่มโมดูล 3 และบันทึกไปยังโมดูล 3 โดยอัตโนมัติเมื่อได้รับข้อความส่งคืนของโมดูล 2
จะเห็นได้ว่าไม่มีการสื่อสารระหว่างโมดูล นอกจากนี้ผู้ไกล่เกลี่ยยังสามารถใช้ฟังก์ชั่นของการตรวจสอบสถานะของแต่ละโมดูล ตัวอย่างเช่นหากมีข้อผิดพลาดในโมดูล 3 ผู้ไกล่เกลี่ยสามารถต้องการโมดูลอื่นได้ชั่วคราวเท่านั้นจากนั้นรีสตาร์ทโมดูล 3 จากนั้นดำเนินการต่อเพื่อดำเนินการต่อ
เมื่อมองย้อนกลับไปเราจะเห็นได้ว่าข้อได้เปรียบของผู้ไกล่เกลี่ยคือโมดูลคู่แบบหลวมถูกควบคุมโดยผู้ไกล่เกลี่ยเดียวกัน โมดูลจำเป็นต้องออกอากาศและฟังเหตุการณ์เท่านั้นและไม่จำเป็นต้องเชื่อมต่อโดยตรงระหว่างโมดูล นอกจากนี้สามารถใช้โมดูลหลายโมดูลสำหรับการประมวลผลข้อมูลในแต่ละครั้งซึ่งยังช่วยให้เราเพิ่มโมดูลใหม่ลงในตรรกะการควบคุมที่มีอยู่ในอนาคต
เป็นที่แน่นอนว่าเนื่องจากโมดูลทั้งหมดไม่สามารถสื่อสารได้โดยตรงอาจมีประสิทธิภาพลดลงเล็กน้อยในทุก ๆ แต่ฉันคิดว่ามันคุ้มค่า
มาใช้การสาธิตอย่างง่ายตามคำอธิบายข้างต้น:
var mediator = (function () {var subscribe = function (channel, fn) {ถ้า (! mediator.channels [channel]) mediator.channels [channel] = []; mediator.channels [channel] .push ({บริบท: นี่, callback: fn}); array.prototype.slice.call (อาร์กิวเมนต์, 1); สมัครสมาชิก: สมัครสมาชิก: ฟังก์ชั่น (obj) {obj.subscribe = สมัครสมาชิก OBJ.Publish = เผยแพร่;จากนั้นมี 2 โมดูลที่เรียกว่า:
// pub/sub บน mediator mediator.name = "tim"; mediator.subscribe ('namechange', ฟังก์ชั่น (arg) {console.log (this.name); this.name = arg; console.log (this.name);}); Mediator.publish ('Namechange', 'David'); // tim, david // pub/sub ผ่านบุคคลที่สาม mediator var obj = {ชื่อ: 'sam'}; mediator.installto (obj); obj.subscribe ('namechange', ฟังก์ชั่น (arg) {console.log (this.name); obj.publish ('namechange', 'John'); // แซมจอห์นแอปพลิเคชันซุ้ม: สิ่งที่เป็นนามธรรมของแกนกลางของแอปพลิเคชัน
ด้านหน้าทำงานเป็นนามธรรมของแกนแอปพลิเคชันและรับผิดชอบการสื่อสารระหว่างผู้ไกล่เกลี่ยและโมดูล แต่ละโมดูลสามารถสื่อสารกับแกนโปรแกรมผ่านด้านหน้านี้ได้เท่านั้น ความรับผิดชอบในฐานะที่เป็นนามธรรมคือเพื่อให้แน่ใจว่าโมดูลเหล่านี้สามารถให้กับอินเทอร์เฟซที่สอดคล้องกันได้ตลอดเวลาซึ่งคล้ายกับบทบาทของคอนโทรลเลอร์ Sendbox ส่วนประกอบโมดูลทั้งหมดสื่อสารกับผู้ไกล่เกลี่ยผ่านมันดังนั้นด้านหน้าจะต้องเชื่อถือได้และน่าเชื่อถือ ในเวลาเดียวกันเป็นฟังก์ชั่นในการจัดหาอินเทอร์เฟซกับโมดูลหน้าต้องมีบทบาทอื่นนั่นคือการควบคุมความปลอดภัยนั่นคือเพื่อกำหนดว่าส่วนใดของโปรแกรมสามารถเข้าถึงได้โดยโมดูล ส่วนประกอบโมดูลสามารถเรียกใช้วิธีการของตนเองเท่านั้นและไม่สามารถเข้าถึงเนื้อหาที่ไม่ได้รับอนุญาตใด ๆ ตัวอย่างเช่นโมดูลอาจออกอากาศ datavalidationcompletedWriteToDB ซึ่งการตรวจสอบความปลอดภัยจำเป็นต้องตรวจสอบให้แน่ใจว่าโมดูลมีสิทธิ์เขียนไปยังฐานข้อมูล
ในระยะสั้นผู้ไกล่เกลี่ยสามารถดำเนินการประมวลผลข้อมูลหลังจากการตรวจจับการอนุญาตด้านหน้า
แอปพลิเคชันสื่อกลาง: แกนกลางของแอปพลิเคชัน
ผู้ไกล่เกลี่ยทำงานเป็นบทบาทหลักของแอปพลิเคชันเรามาพูดคุยสั้น ๆ เกี่ยวกับความรับผิดชอบของเขา งานหลักที่สุดคือการจัดการวงจรชีวิตของโมดูล เมื่อหลักนี้จับข้อมูลใด ๆ มันจำเป็นต้องตัดสินว่าโปรแกรมจัดการได้อย่างไร - นั่นคือเพื่อตัดสินใจว่าโมดูลใดที่จะเริ่มต้นหรือหยุด เมื่อโมดูลเริ่มต้นมันควรจะสามารถดำเนินการโดยอัตโนมัติได้โดยไม่ต้องใช้แกนแอปพลิเคชันเพื่อตัดสินใจว่าควรดำเนินการ (ตัวอย่างเช่นไม่ว่าควรจะดำเนินการหรือไม่เมื่อ DOM พร้อม) ดังนั้นโมดูลนั้นจำเป็นต้องพิจารณา
คุณอาจมีคำถามภายใต้สถานการณ์ใดโมดูลจะหยุด? เมื่อโปรแกรมตรวจพบว่าโมดูลล้มเหลวหรือทำผิดพลาดโปรแกรมจะต้องตัดสินใจที่จะป้องกันวิธีการในโมดูลจากการดำเนินการต่อเพื่อดำเนินการเพื่อให้ส่วนประกอบสามารถเริ่มต้นใหม่โดยมีวัตถุประสงค์หลักในการปรับปรุงประสบการณ์ผู้ใช้
นอกจากนี้แกนกลางควรจะสามารถเพิ่มหรือลบโมดูลแบบไดนามิกโดยไม่ส่งผลกระทบต่อฟังก์ชั่นอื่น ๆ ตัวอย่างทั่วไปคือโมดูลไม่สามารถใช้งานได้ที่จุดเริ่มต้นของการโหลดหน้าเว็บ แต่หลังจากผู้ใช้ทำงานแล้วจะต้องโหลดโมดูลแบบไดนามิกแล้วดำเนินการ เช่นเดียวกับฟังก์ชั่นการแชทใน Gmail ควรเข้าใจง่ายจากจุดประสงค์ของการเพิ่มประสิทธิภาพประสิทธิภาพ
การจัดการข้อผิดพลาดข้อยกเว้นยังได้รับการจัดการโดยแกนแอปพลิเคชัน นอกจากนี้เมื่อแต่ละโมดูลออกอากาศข้อมูลมันยังออกอากาศข้อผิดพลาดใด ๆ ไปยังแกนกลางเพื่อให้แกนโปรแกรมสามารถหยุด/รีสตาร์ทโมดูลเหล่านี้ตามสถานการณ์ นี่เป็นส่วนสำคัญของสถาปัตยกรรมคู่ที่หลวม เราไม่จำเป็นต้องเปลี่ยนโมดูลใด ๆ ด้วยตนเอง เราสามารถทำได้โดยใช้การเผยแพร่/สมัครสมาชิกผ่านสื่อกลาง
รวมตัวกัน
แต่ละโมดูลมีฟังก์ชั่นต่าง ๆ ในโปรแกรม เมื่อพวกเขามีข้อมูลที่จะดำเนินการพวกเขาจะออกข้อมูลแจ้งโปรแกรม (นี่เป็นความรับผิดชอบหลักของพวกเขา) ส่วน QA ต่อไปนี้กล่าวว่าโมดูลสามารถพึ่งพาวิธีการใช้งานเครื่องมือ DOM บางอย่าง แต่ไม่ควรขึ้นอยู่กับโมดูลอื่น ๆ ของระบบ โมดูลไม่ควรให้ความสนใจกับเนื้อหาต่อไปนี้:
1. วัตถุหรือโมดูลใดที่สมัครรับข้อมูลที่เผยแพร่โดยโมดูลนี้
2. วัตถุเหล่านี้เป็นไคลเอนต์หรือวัตถุฝั่งเซิร์ฟเวอร์
3. มีวัตถุจำนวนเท่าใดที่สมัครข้อมูลของคุณ
แกนหลักของแอปพลิเคชัน Abstraction ของหน้าหลีกเลี่ยงการสื่อสารโดยตรงระหว่างโมดูล มันสมัครรับข้อมูลจากแต่ละโมดูลและยังรับผิดชอบในการตรวจจับการอนุญาตเพื่อให้มั่นใจว่าแต่ละโมดูลมีการอนุญาตแยกต่างหาก
Mediator (Application Core) ใช้โหมด Mediator เพื่อเล่นบทบาทของตัวจัดการการเผยแพร่/สมัครสมาชิกรับผิดชอบในการจัดการโมดูลและการดำเนินการเริ่มต้น/หยุดโมดูลและสามารถโหลดและรีสตาร์ทโมดูลแบบไดนามิกด้วยข้อผิดพลาด
ผลลัพธ์ของสถาปัตยกรรมนี้คือไม่มีการพึ่งพาระหว่างโมดูลเนื่องจากแอพพลิเคชั่นคู่กันอย่างหลวม ๆ พวกเขาสามารถทดสอบและบำรุงรักษาได้อย่างง่ายดายแต่ละโมดูลสามารถนำกลับมาใช้ใหม่ได้อย่างง่ายดายในโครงการอื่น ๆ หรือสามารถเพิ่มและลบได้แบบไดนามิกโดยไม่ส่งผลกระทบต่อโปรแกรม
เผยแพร่ Pub/Sub Extension: การลงทะเบียนกิจกรรมอัตโนมัติ
เกี่ยวกับการลงทะเบียนเหตุการณ์อัตโนมัติจำเป็นต้องมีการติดตามข้อกำหนดการตั้งชื่อบางอย่าง ตัวอย่างเช่นหากโมดูลเผยแพร่เหตุการณ์ที่ชื่อว่า MessageUpdate แล้วโมดูลทั้งหมดที่มีเมธอด MessageUpdate จะถูกดำเนินการโดยอัตโนมัติ มีประโยชน์และข้อดีและข้อเสีย สำหรับวิธีการใช้งานที่เฉพาะเจาะจงคุณสามารถดูโพสต์อื่นจากฉันได้: JQuery Custom Binding เวอร์ชันเวทมนตร์ที่ได้รับการอัพเกรด
QA
1. เป็นไปได้ไหมที่จะไม่ใช้โหมดซุปเปอร์หรือโหมดแซนด์บ็อกซ์ที่คล้ายกัน?
แม้ว่าโครงร่างของสถาปัตยกรรมเสนอว่าหน้าสามารถใช้ฟังก์ชั่นการตรวจสอบการอนุญาต แต่ก็เป็นไปได้ทั้งหมดที่ผู้ไกล่เกลี่ยสามารถทำได้ สิ่งที่สถาปัตยกรรมแสงต้องทำเกือบจะเหมือนกันนั่นคือการแยกและทำให้มั่นใจว่าแต่ละโมดูลสื่อสารโดยตรงกับแกนกลางของแอปพลิเคชันนั้นดี
2. คุณได้ปรับปรุงว่าโมดูลไม่สามารถขึ้นอยู่กับได้โดยตรง หมายความว่ามันไม่สามารถพึ่งพาห้องสมุดบุคคลที่สามใด ๆ (เช่น jQuery)
นี่เป็นปัญหาสองด้าน ดังที่เราได้กล่าวไว้ข้างต้นโมดูลอาจมี submodules หรือโมดูลพื้นฐานบางอย่างเช่นคลาสเครื่องมือการทำงาน DOM พื้นฐาน ฯลฯ ในระดับนี้เราสามารถใช้ไลบรารีของบุคคลที่สาม แต่โปรดตรวจสอบให้แน่ใจว่าเราสามารถแทนที่ได้อย่างง่ายดาย
3. ฉันชอบสถาปัตยกรรมนี้และต้องการเริ่มใช้สถาปัตยกรรมนี้ มีตัวอย่างรหัสใดบ้างที่สามารถใช้อ้างอิงได้หรือไม่?
ฉันวางแผนที่จะสร้างตัวอย่างรหัสสำหรับการอ้างอิงของคุณ แต่ก่อนหน้านั้นคุณสามารถอ้างถึงการเขียนโพสต์ของ Andrew Burgees 'Modular JavaScript
4. เป็นไปได้หรือไม่หากโมดูลจำเป็นต้องสื่อสารโดยตรงกับแกนแอปพลิเคชัน?
ในทางเทคนิคไม่มีเหตุผลว่าทำไมโมดูลไม่สามารถสื่อสารโดยตรงกับแกนแอปพลิเคชันในขณะนี้ แต่สำหรับประสบการณ์การใช้งานส่วนใหญ่ยังไม่ได้รับอนุญาต เนื่องจากคุณได้เลือกสถาปัตยกรรมนี้คุณต้องปฏิบัติตามกฎที่กำหนดโดยสถาปัตยกรรม
กิตติกรรมประกาศ
ขอบคุณ Nicholas Zakas สำหรับโพสต์ต้นฉบับเพื่อสรุปความคิดร่วมกันไปยัง Andree Hansson สำหรับการทบทวนทางเทคนิคเพื่อรีเบคก้าเมอร์ฟีย์จัสตินเมเยอร์จอห์นฮันน์ปีเตอร์มิชเกอซ์พอลไอริชและอเล็กซ์เซกซ์ตันทั้งหมดให้ข้อมูลมากมายที่เกี่ยวข้องกับเซสชั่นนี้