การจัดการความซับซ้อน

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

เรียบง่ายและซับซ้อน

ในการพูดคุยเรื่อง Simple Made Easy นั้น Rich Hickey จะมาพูดถึงคุณสมบัติของสิ่งที่เรียบง่ายและซับซ้อน เขาอธิบายง่ายๆ ว่ากำลังโฟกัสที่:

"หนึ่งบทบาท หนึ่งงาน หนึ่งแนวคิด หรือหนึ่งมิติ"

แต่เน้นย้ำว่าความเรียบง่ายนั้นไม่ได้เกี่ยวข้องกับสิ่งต่อไปนี้

"มี 1 อินสแตนซ์หรือดำเนินการ 1 รายการ"

ความเรียบง่ายนั้นเกี่ยวข้องกับความเชื่อมโยงระหว่างกันหรือไม่

ความซับซ้อนมาจากการผูก การถักทอ หรือการใช้คำของ Rich ในการเรียบเรียงสิ่งต่างๆ เข้าด้วยกัน คุณสามารถคำนวณความซับซ้อนได้ด้วยการนับจำนวนบทบาท งาน แนวคิด หรือมิติข้อมูลที่บางอย่างจัดการ

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

การจัดการความซับซ้อนของ PWA

JavaScript ทั้งหมดที่เราเขียนสำหรับเว็บจะแตะเทรดหลัก ณ จุดหนึ่ง แต่เทรดหลักนั้นมีความซับซ้อนอย่างมาก ซึ่งคุณในฐานะนักพัฒนาซอฟต์แวร์ไม่สามารถควบคุมได้

เทรดหลักคือ

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

ดังที่ Surma ได้กล่าวไว้ในงานพูดคุยเรื่อง Chrome Dev Summit ประจำปี 2019 ว่าเทรดหลักทำงานหนักเกินไปและได้รับเงินน้อยกว่าเดิม

อย่างไรก็ตาม โค้ดของแอปพลิเคชันส่วนใหญ่ก็อยู่ในเทรดหลักเช่นกัน

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

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

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

การแยกข้อกังวล

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

  • แตะ DOM โดยตรง
  • ใช้ API แตะความสามารถของอุปกรณ์ เช่น การแจ้งเตือนหรือการเข้าถึงระบบไฟล์
  • แตะข้อมูลประจำตัว เช่น คุกกี้ของผู้ใช้ พื้นที่เก็บข้อมูลในเครื่อง หรือพื้นที่เก็บข้อมูลของเซสชัน
  • จัดการสื่อ เช่น รูปภาพ เสียง หรือวิดีโอ
  • มีปัญหาด้านความปลอดภัยที่ผู้ใช้ต้องอนุมัติ เช่น Web Serial API

การทำงานที่ไม่ใช้ UI อาจรวมถึงสิ่งต่อไปนี้

  • การคำนวณทั้งหมด
  • การเข้าถึงข้อมูล (ดึงข้อมูล, IndexedDB ฯลฯ)
  • คริปโต
  • การรับส่งข้อความ
  • การสร้างหรือการจัดการ BLOB หรือสตรีม

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

มุ่งเน้นที่งานเดียว

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

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

ขอบเขตแรกที่ชัดเจนคือ ระหว่างการทำงานของ UI และการทำงานที่ไม่ใช่ UI จะต้องมีการเรียกเพื่อตัดสิน เช่น การสร้างและแยกวิเคราะห์คำขอ API 1 หรือ 2 งานหรือไม่ หากการเปลี่ยนแปลง DOM ใช้ไม่ได้กับ UI การเปลี่ยนแปลงนั้นจะมาพร้อมกับงาน API ไหม ในชุดข้อความเดียวกันใช่ไหม หากอยู่ในชุดข้อความอื่น ระดับการแยกที่เหมาะสมที่นี่เป็นกุญแจสำคัญในการลดความซับซ้อนของฐานโค้ดและการย้ายส่วนต่างๆ ออกจากเทรดหลักได้สำเร็จ

ความสามารถในการประกอบ

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

  • จัดหมวดหมู่ประเภทของงานที่แอปพลิเคชันทำ
  • การสร้างอินเทอร์เฟซอินพุตและเอาต์พุตทั่วไป

ตัวอย่างเช่น งานการเรียก API ทั้งหมดจะดำเนินการในปลายทาง API และแสดงผลอาร์เรย์ของออบเจ็กต์มาตรฐาน และฟังก์ชันการประมวลผลข้อมูลทั้งหมดรับและส่งคืนอาร์เรย์ของออบเจ็กต์มาตรฐาน

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

ดังนั้น คุณสามารถสร้างไลบรารีของฟังก์ชัน Composable ได้ด้วยการจัดหมวดหมู่โค้ดและสร้างอินเทอร์เฟซ I/O ทั่วไปสำหรับหมวดหมู่เหล่านั้น โค้ดที่ประกอบกันได้เป็นเอกลักษณ์ของฐานของโค้ดอย่างง่าย นั่นคือ ชิ้นส่วนที่ต่อกันอย่างหลวมและสลับสับเปลี่ยนได้ ซึ่งวางอยู่ติดกันและต่อยอดจากกันและกันได้ ซึ่งตรงข้ามกับโค้ดที่ซับซ้อนซึ่งเชื่อมโยงถึงกันอย่างลึกซึ้ง ซึ่งทำให้ไม่สามารถแยกออกจากกันได้โดยง่าย และในเว็บ โค้ดที่เขียนได้อาจหมายถึงความแตกต่างระหว่างการทำงานมากเกินไปในเทรดหลัก

เมื่อมีโค้ด Composable อยู่ในมือแล้ว ก็ถึงเวลานำโค้ดบางส่วนออกจากเทรดหลัก

ใช้ Web Worker เพื่อลดความซับซ้อน

ผู้ปฏิบัติงานเกี่ยวกับเว็บซึ่งเป็นความสามารถบนเว็บที่มักมีการใช้งานไม่ค่อยดีแต่มีการใช้งานในวงกว้าง ช่วยให้คุณย้ายงานออกจากเทรดหลักได้

เว็บผู้ปฏิบัติงานอนุญาตให้ PWA เรียกใช้ JavaScript (บางส่วน) นอกเทรดหลักได้

ผู้ปฏิบัติงานมี 3 ประเภท

ผู้ปฏิบัติงานเฉพาะ หรือสิ่งที่คนมักนึกถึงเมื่ออธิบายเกี่ยวกับ Web Worker สามารถใช้กับสคริปต์ตัวเดียวในอินสแตนซ์ที่ทำงานอยู่ของ PWA รายการเดียว หากเป็นไปได้ ควรย้ายงานที่ไม่มีการโต้ตอบกับ DOM ไปไว้ที่ Web Worker เพื่อปรับปรุงประสิทธิภาพ

ผู้ปฏิบัติงานที่แชร์คล้ายกับผู้ปฏิบัติงานเฉพาะด้าน แต่สคริปต์หลายรายการจะแชร์ผู้ปฏิบัติงานได้ในหลายหน้าต่าง ซึ่งมีประโยชน์สำหรับผู้ปฏิบัติงานที่ได้รับมอบหมายโดยเฉพาะ แต่จะแสดงสถานะที่ใช้ร่วมกันและบริบทภายในระหว่างหน้าต่างและสคริปต์

ตัวอย่างเช่น พนักงานที่แชร์อาจจัดการการเข้าถึงและธุรกรรมสำหรับ IndexedDB ของ PWA และประกาศผลธุรกรรมในสคริปต์การเรียกใช้ทั้งหมดเพื่อตอบสนองต่อการเปลี่ยนแปลงต่างๆ

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

ลองดูเอง

ได้เวลาเขียนโค้ดแล้ว! สร้าง PWA ใหม่ตั้งแต่ต้นโดยอิงจากทุกอย่างที่ได้เรียนรู้ในโมดูลนี้

แหล่งข้อมูล