คำนำ
ในบทนี้เราจะอธิบายบทที่ห้าของการดำเนินการตามหลักการสำคัญห้าประการของภาษาจาวาสคริปต์ที่เป็นของแข็งซึ่งเป็น LSP (หลักการผกผันของการพึ่งพา)
ข้อความภาษาอังกฤษต้นฉบับ: http://freshbrewedcode.com/derekgreeer/2012/01/22/solid-javascript-the-dependency-inverenciple-principle/
หลักการการผกผัน
คำอธิบายของหลักการของการผกผันการพึ่งพาคือ:
A. โมดูลระดับสูงไม่ควรขึ้นอยู่กับโมดูลระดับต่ำ ทั้งสองควรขึ้นอยู่กับ abstractions
โมดูลระดับสูงไม่ควรขึ้นอยู่กับโมดูลระดับต่ำทั้งคู่ควรพึ่งพาสิ่งที่เป็นนามธรรม
B. abstractions ไม่ควรขึ้นอยู่กับรายละเอียด รายละเอียดควรขึ้นอยู่กับ abstractions
บทคัดย่อไม่ควรขึ้นอยู่กับรายละเอียดรายละเอียดควรขึ้นอยู่กับนามธรรม
ปัญหาที่สำคัญที่สุดของหลักการของการผกผันในการพึ่งพาคือเพื่อให้แน่ใจว่าองค์ประกอบหลักของแอปพลิเคชันหรือกรอบงานจะถูกแยกออกจากรายละเอียดการดำเนินการขององค์ประกอบพื้นฐานที่ไม่สำคัญซึ่งจะทำให้มั่นใจได้ว่าส่วนที่สำคัญที่สุดของโปรแกรมจะไม่ได้รับผลกระทบจากการเปลี่ยนแปลงและการปรับเปลี่ยนองค์ประกอบระดับต่ำ
ส่วนแรกของหลักการนี้เกี่ยวกับการมีเพศสัมพันธ์ระหว่างโมดูลระดับสูงและโมดูลระดับต่ำ ในสถาปัตยกรรมการแบ่งแบบดั้งเดิมโมดูลระดับสูง (ห่อหุ้มตรรกะธุรกิจหลักของโปรแกรม) มักจะพึ่งพาโมดูลระดับต่ำบางส่วน (บางจุดพื้นฐาน) เมื่อมีการใช้หลักการของการผกผันการพึ่งพาความสัมพันธ์จะกลับด้าน ซึ่งแตกต่างจากโมดูลระดับสูงที่ขึ้นอยู่กับโมดูลระดับต่ำการผกผันในการพึ่งพาทำให้โมดูลระดับต่ำขึ้นอยู่กับอินเทอร์เฟซที่กำหนดไว้ในโมดูลระดับสูง ตัวอย่างเช่นหากคุณต้องการคงข้อมูลสำหรับโปรแกรมการออกแบบแบบดั้งเดิมคือโมดูลหลักขึ้นอยู่กับ API ของโมดูลถาวร หลังจากการสร้างใหม่ตามหลักการของการผกผันการพึ่งพาโมดูลหลักจำเป็นต้องกำหนดอินเทอร์เฟซ API แบบถาวรจากนั้นอินสแตนซ์การใช้งานแบบถาวรจำเป็นต้องใช้อินเตอร์เฟส API ที่กำหนดโดยโมดูลหลัก
ส่วนที่สองของหลักการนี้อธิบายถึงความสัมพันธ์ที่ถูกต้องระหว่างนามธรรมและรายละเอียด การทำความเข้าใจกับส่วนนี้มีประโยชน์มากขึ้นโดยการทำความเข้าใจภาษา C ++ เนื่องจากการบังคับใช้นั้นชัดเจนยิ่งขึ้น
ซึ่งแตกต่างจากภาษาที่พิมพ์แบบคงที่ C ++ ไม่ได้ให้แนวคิดระดับภาษาเพื่อกำหนดอินเทอร์เฟซ ความสัมพันธ์ระหว่างนิยามคลาสและการใช้งานชั้นเรียนคืออะไร? ใน C ++ คลาสจะถูกกำหนดไว้ในรูปแบบของไฟล์ส่วนหัวซึ่งกำหนดวิธีการสมาชิกคลาสและตัวแปรที่ไฟล์ต้นฉบับจำเป็นต้องใช้ เนื่องจากตัวแปรทั้งหมดและวิธีการส่วนตัวถูกกำหนดไว้ในไฟล์ส่วนหัวจึงสามารถใช้เป็นนามธรรมและแยกแยะได้ก่อนที่จะมีการใช้รายละเอียด แนวคิดของอินเทอร์เฟซถูกนำมาใช้โดยการกำหนดวิธีนามธรรมเท่านั้น (คลาสพื้นฐานพื้นฐานใน C ++) ใช้เพื่อใช้คลาส
จุ่มและจาวาสคริปต์
เนื่องจาก JavaScript เป็นภาษาแบบไดนามิกจึงไม่จำเป็นต้องเป็นนามธรรมสำหรับการ decoupling ดังนั้นสิ่งที่เป็นนามธรรมไม่ควรพึ่งพารายละเอียด การเปลี่ยนแปลงนี้ไม่ได้มีผลกระทบมากนักใน JavaScript แต่โมดูลระดับสูงไม่ควรพึ่งพาโมดูลระดับต่ำ แต่มีผลกระทบอย่างมาก
เมื่อพูดถึงหลักการของการผกผันการพึ่งพาในบริบทของภาษาที่พิมพ์แบบคงที่แนวคิดของการมีเพศสัมพันธ์รวมถึงความหมายและทางกายภาพ ซึ่งหมายความว่าหากโมดูลระดับสูงขึ้นอยู่กับโมดูลระดับต่ำมันไม่เพียง แต่เป็นคู่อินเทอร์เฟซความหมายเท่านั้น แต่ยังรวมถึงอินเทอร์เฟซทางกายภาพที่กำหนดไว้ในโมดูลพื้นฐาน กล่าวอีกนัยหนึ่งโมดูลระดับสูงจะต้องไม่เพียง แต่จะถูกแยกออกจากห้องสมุดบุคคลที่สามเท่านั้น แต่ยังมาจากโมดูลระดับต่ำเนทีฟ
เพื่ออธิบายสิ่งนี้ลองจินตนาการว่าโปรแกรม. NET อาจมีโมดูลระดับสูงที่มีประโยชน์มากซึ่งต้องอาศัยโมดูลถาวรระดับต่ำ เมื่อผู้เขียนจำเป็นต้องเพิ่มอินเทอร์เฟซที่คล้ายกันในการคงอยู่ของ API ไม่ว่าจะใช้หลักการการผกผันของการพึ่งพาหรือไม่หรือไม่โมดูลระดับสูงจะไม่สามารถนำกลับมาใช้ใหม่ได้ในโปรแกรมอื่น ๆ
ใน JavaScript การบังคับใช้หลักการของการผกผันการพึ่งพานั้น จำกัด อยู่ที่การมีเพศสัมพันธ์ทางความหมายระหว่างโมดูลระดับสูงและโมดูลระดับต่ำ ตัวอย่างเช่น DIP สามารถเพิ่มอินเทอร์เฟซตามต้องการแทนการเชื่อมต่ออินเทอร์เฟซโดยนัยที่กำหนดโดยโมดูลระดับต่ำ
เพื่อให้เข้าใจสิ่งนี้ลองดูตัวอย่างต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
$ .fn.trackMap = ฟังก์ชั่น (ตัวเลือก) {
var defaults = {
/ * ค่าเริ่มต้น */
-
ตัวเลือก = $ .extend ({}, ค่าเริ่มต้น, ตัวเลือก);
var mapoptions = {
ศูนย์: ใหม่ google.maps.latlng (ตัวเลือก. latitude, opotions.longitude),
ซูม: 12,
MapTypeId: google.maps.maptypeid.roadmap
-
map = ใหม่ google.maps.map (นี้ [0], mapoptions),
pos = ใหม่ google.maps.latlng (ตัวเลือก. latitude, opotions.longitude);
var marker = ใหม่ google.maps.marker ({
ตำแหน่ง: POS,
ชื่อเรื่อง: ตัวเลือก
ไอคอน: ตัวเลือก
-
marker.setMap (แผนที่);
ตัวเลือก feed.update (ฟังก์ชั่น (ละติจูด, ลองจิจูด) {
marker.setMap (null);
var newLatlng = ใหม่ google.maps.latlng (ละติจูด, ลองจิจูด);
marker.position = newLatlng;
marker.setMap (แผนที่);
map.setCenter (newlatlng);
-
คืนสิ่งนี้;
-
var updater = (function () {
// คุณสมบัติส่วนตัว
กลับ {
อัปเดต: ฟังก์ชั่น (การโทรกลับ) {
updateMap = การโทรกลับ;
-
-
-
$ ("#map_canvas"). trackmap ({
ละติจูด: 35.044640193770725
ลองจิจูด: -89.98193264007568
ไอคอน: 'http://bit.ly/zjngde'
ชื่อเรื่อง: 'หมายเลขติดตาม: 12345'
ฟีด: updater
-
ในรหัสข้างต้นมีไลบรารีคลาส JS ขนาดเล็กที่แปลง DIV เป็นแผนที่เพื่อแสดงข้อมูลตำแหน่งที่ติดตามในปัจจุบัน ฟังก์ชั่น trackmap มี 2 การพึ่งพา: Google แผนที่ API และฟีดตำแหน่งของบุคคลที่สาม ความรับผิดชอบของวัตถุฟีดคือการโทรกลับการโทรกลับ (ให้ในการเริ่มต้น) เมื่อตำแหน่งไอคอนได้รับการอัปเดตและผ่านในละติจูดละติจูดและลองจิจูดที่แม่นยำ Google Maps API ใช้เพื่อแสดงผลอินเทอร์เฟซ
อินเทอร์เฟซของวัตถุฟีดอาจขึ้นอยู่กับการติดตั้งหรือไม่ได้ออกแบบตามข้อกำหนดของฟังก์ชั่นการติดตั้งแทร็กติดตาม ในความเป็นจริงบทบาทของมันนั้นง่ายมากโดยมุ่งเน้นไปที่การใช้งานที่แตกต่างกันอย่างง่ายและไม่จำเป็นต้องพึ่งพา Google Maps มากนัก ความหมายของแทร็กแมปนั้นเชื่อมต่อกับ Google Maps API หากคุณต้องการเปลี่ยนไปใช้ผู้ให้บริการแผนที่ที่แตกต่างกันคุณต้องเขียนฟังก์ชั่น trackmap ใหม่เพื่อให้สามารถปรับให้เข้ากับผู้ให้บริการที่แตกต่างกัน
ในการพลิกข้อต่อความหมายของไลบรารีคลาส Google Maps เราจำเป็นต้องเขียนฟังก์ชั่นการออกแบบแทร็กแมปใหม่เพื่อเชื่อมต่อความหมายของอินเทอร์เฟซโดยนัย (นามธรรมอินเตอร์เฟสของผู้ให้บริการแผนที่) นอกจากนี้เรายังต้องการวัตถุการใช้งานที่ปรับให้เข้ากับ Google Maps API ต่อไปนี้เป็นฟังก์ชั่น trackmap refactored:
การคัดลอกรหัสมีดังนี้:
$ .fn.trackMap = ฟังก์ชั่น (ตัวเลือก) {
var defaults = {
/ * ค่าเริ่มต้น */
-
ตัวเลือก = $ .extend ({}, ค่าเริ่มต้น, ตัวเลือก);
ตัวเลือก provider.showmap (
[0]
ตัวเลือก
ตัวเลือกความยาว
ตัวเลือก
ตัวเลือก title);
ตัวเลือก feed.update (ฟังก์ชั่น (ละติจูด, ลองจิจูด) {
ตัวเลือก provider.updateMap (ละติจูด, ลองจิจูด);
-
คืนสิ่งนี้;
-
$ ("#map_canvas"). trackmap ({
ละติจูด: 35.044640193770725
ลองจิจูด: -89.98193264007568
ไอคอน: 'http://bit.ly/zjngde'
ชื่อเรื่อง: 'หมายเลขติดตาม: 12345'
ฟีด: updater,
ผู้ให้บริการ: trackmap.googlemapsprovider
-
ในเวอร์ชันนี้เราได้ออกแบบฟังก์ชั่น trackmap และอินเทอร์เฟซผู้ให้บริการแผนที่ที่จำเป็นแล้วย้ายรายละเอียดการใช้งานไปยังส่วนประกอบ googlemapsprovider แยกต่างหากซึ่งอาจถูกห่อหุ้มอย่างอิสระลงในโมดูล JavaScript แยกต่างหาก นี่คือการใช้งาน googlemapsprovider ของฉัน:
การคัดลอกรหัสมีดังนี้:
trackmap.googlemapsprovider = (function () {
เครื่องหมาย var, แผนที่;
กลับ {
showmap: ฟังก์ชัน (องค์ประกอบ, ละติจูด, ลองจิจูด, ไอคอน, ชื่อ) {
var mapoptions = {
ศูนย์: ใหม่ google.maps.latlng (ละติจูด, ลองจิจูด),
ซูม: 12,
MapTypeId: google.maps.maptypeid.roadmap
-
pos = ใหม่ google.maps.latlng (ละติจูด, ลองจิจูด);
MAP = ใหม่ google.maps.map (องค์ประกอบ, mapoptions);
marker = ใหม่ google.maps.marker ({
ตำแหน่ง: POS,
ชื่อเรื่อง: ชื่อ
ไอคอน: ไอคอน
-
marker.setMap (แผนที่);
-
updateMap: ฟังก์ชั่น (ละติจูด, ลองจิจูด) {
marker.setMap (null);
var newLatlng = ใหม่ google.maps.latlng (ละติจูด, ลองจิจูด);
marker.position = newLatlng;
marker.setMap (แผนที่);
map.setCenter (newlatlng);
-
-
-
หลังจากทำการเปลี่ยนแปลงข้างต้นฟังก์ชั่น trackmap จะมีความยืดหยุ่นมากและไม่จำเป็นต้องพึ่งพา Google Maps API แต่ผู้ให้บริการแผนที่รายอื่นสามารถถูกแทนที่ได้ตามต้องการนั่นคือผู้ให้บริการแผนที่ใด ๆ สามารถปรับให้เข้ากับความต้องการของโปรแกรมได้
การฉีดขึ้นอยู่กับการพึ่งพาเมื่อไหร่?
มันค่อนข้างไม่เกี่ยวข้อง ในความเป็นจริงแนวคิดของการฉีดพึ่งพามักจะผสมกับหลักการของการผกผันการพึ่งพา เพื่อชี้แจงความแตกต่างนี้จำเป็นต้องอธิบาย:
การฉีดขึ้นอยู่กับการพึ่งพาเป็นรูปแบบพิเศษของการผกผันการควบคุมและการผกผันหมายถึงวิธีการที่ส่วนประกอบได้รับการอ้างอิง การฉีดพึ่งพาหมายถึง: การพึ่งพามีให้กับส่วนประกอบแทนที่จะเป็นส่วนประกอบเพื่อให้ได้การพึ่งพาซึ่งหมายถึงการสร้างอินสแตนซ์ของการพึ่งพาการร้องขอการพึ่งพาผ่านโรงงานและขอการพึ่งพาผ่านตัวระบุตำแหน่งบริการหรือส่วนประกอบเอง หลักการผกผันการพึ่งพาและการฉีดพึ่งพาอาศัยกันนั้นมุ่งเน้นไปที่การพึ่งพาและใช้สำหรับการผกผัน อย่างไรก็ตามหลักการของการผกผันการพึ่งพาไม่ได้มุ่งเน้นไปที่วิธีการที่ส่วนประกอบได้รับการอ้างอิง แต่เฉพาะวิธีการที่โมดูลระดับสูงถูกแยกออกจากโมดูลระดับต่ำ ในแง่หนึ่งหลักการของการผกผันการพึ่งพาเป็นอีกรูปแบบหนึ่งของการผกผันควบคุม ที่นี่การผกผันเป็นโมดูลที่กำหนดอินเทอร์เฟซ (กำหนดจากระดับล่างการผกผันถึงระดับที่สูงขึ้น)
สรุป
นี่เป็นบทความสุดท้ายของหลักการสำคัญห้าประการ ในบทความ 5 บทความนี้เราจะเห็นว่ามีการใช้งานของแข็งใน JavaScript อย่างไร หลักการที่แตกต่างกันถูกอธิบายจากมุมที่แตกต่างกันใน JavaScript (ลุงหมายเหตุ: อันที่จริงฉันคิดว่าถึงแม้ว่ามันจะไม่เหมาะสมเล็กน้อยจากมุมมองอื่น แต่หลักการทั่วไปนั้นเหมือนกันในภาษาต่างๆ