กลยุทธ์ที่ดีที่สุดสำหรับการรายงานความคืบหน้าสู่ UI - การโทรกลับจะเกิดขึ้นได้อย่างไร


11

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

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

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

  1. ส่งผ่านวัตถุที่ไม่แน่นอนไปยังส่วนหลังและให้ส่วนหลังเปลี่ยนแปลงอยู่ระหว่างดำเนินการ วัตถุแจ้ง Front-end เมื่อมีการเปลี่ยนแปลงเกิดขึ้น

  2. ผ่านฟังก์ชั่นโทรกลับของแบบฟอร์มvoid f(ProgressObject)หรือProgressObject -> unitว่าส่วนหลังเรียกใช้ ในกรณีนี้ back-end สร้างProgressObjectและมันแฝงอย่างสมบูรณ์ มันจะต้องสร้างวัตถุใหม่ทุกครั้งที่ต้องการรายงานความคืบหน้าฉันถือว่า

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

มีเทคนิคที่แตกต่างอย่างสิ้นเชิงจากการรายงานความก้าวหน้าที่ฉันมองข้ามไปหรือไม่?


1
เกี่ยวกับความผันแปรไม่ได้และไม่เปลี่ยนรูปข้อดีและข้อเสียเหมือนกันกับทุกที่ เกี่ยวกับวัตถุความคืบหน้าสิ่งนี้อาจเบามาก สามารถทำได้ง่ายเพียงตัวเลขเดียว: เปอร์เซ็นต์
Robert Harvey

@RobertHarvey ขนาดของวัตถุความคืบหน้ามักขึ้นอยู่กับข้อกำหนดของ UI ดูตัวอย่างไดอะล็อก Windows copy ฉันคิดว่ามันต้องใช้ข้อมูลจำนวนมาก
GregRos

1
@ RobertHarvey นั่นเป็นข่าวสำหรับฉัน มันคืออะไร?
GregRos

1
ฉันจะกัด เราใช้BackgroundWorkerRH ที่กล่าวถึง ห่อในคลาสที่กำหนดเองพร้อมกับ "แบบฟอร์มความคืบหน้า" ฯลฯ และกลไกที่ง่ายสำหรับการสื่อสารข้อยกเว้น - BackgroundWorkerตามการออกแบบทำงานในเธรดแยกต่างหาก เท่าที่เราใช้คุณสมบัติของมันในวิธีที่แนะนำโดย. Net จากนั้นอาจกล่าวได้ว่าเป็นสำนวน และในบริบทของภาษา / กรอบที่กำหนด "สำนวน" อาจดีที่สุด
Radarbob

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

คำตอบ:


8

ส่งผ่านวัตถุที่ไม่แน่นอนไปยังส่วนหลังและให้ส่วนหลังเปลี่ยนแปลงอยู่ระหว่างดำเนินการ วัตถุแจ้ง Front-end เมื่อมีการเปลี่ยนแปลงเกิดขึ้น

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

ผ่านฟังก์ชั่นโทรกลับของโมฆะแบบฟอร์ม f (ProgressObject) หรือ ProgressObject -> หน่วยที่ back-end เรียกใช้ ในกรณีนี้ back-end จะสร้าง ProgressObject ขึ้นมาและมันจะเป็นแบบพาสซีฟอย่างสมบูรณ์ มันจะต้องสร้างวัตถุใหม่ทุกครั้งที่ต้องการรายงานความคืบหน้าฉันถือว่า

ฉันไม่ได้รับความแตกต่างที่นี่มากนัก

มีเทคนิคที่แตกต่างอย่างสิ้นเชิงจากการรายงานความก้าวหน้าที่ฉันมองข้ามไปหรือไม่?

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


2

นี่คือความแตกต่างระหว่างกลไกการแจ้งเตือนแบบพุชและพูล

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

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

โดยทั่วไปแล้วการแจ้งเตือนแบบพุชจะดีกว่าเพราะมันจะทำงานได้ก็ต่อเมื่อจำเป็นต้องทำงาน


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

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

The mutable object (the pull) will need to be repeatably polled by the UI and synchronized if you expect the back-end task to be executed in a background/worker thread.- ไม่ใช่ถ้าวัตถุที่ไม่แน่นอนเป็นไดอะล็อกตัวเองหรือส่วนต่อประสานที่ใช้งานได้ แน่นอนว่าจำนวนเงินที่โทรกลับอยู่แล้ว
Robert Harvey

1
ฮะ? OP อธิบายอย่างชัดเจนถึงสองรูปแบบที่แตกต่างกันของกลไกการพุช
Doc Brown

0

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


0

คุณพูดถึง "สองวิธี" ของคุณราวกับว่าพวกเขาเป็นแนวคิดที่แยกจากกัน แต่ฉันต้องการที่จะผลักดันกลับไปเล็กน้อย

  1. ส่งผ่านวัตถุที่ไม่แน่นอนไปยังส่วนหลังและให้ส่วนหลังเปลี่ยนแปลงอยู่ระหว่างดำเนินการ วัตถุแจ้ง Front-end เมื่อมีการเปลี่ยนแปลงเกิดขึ้น

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

สำหรับประโยชน์และข้อเสีย ...

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

จุดแข็งสำหรับวิธีการ (1) คือการมีหลายวิธีบนอินเทอร์เฟซง่ายกว่าการจัดการกับการเรียกกลับหลายวิธี (2) หรือการโทรกลับครั้งเดียวด้วยคำสั่งสลับสำหรับบริบทหลายรายการ


-2

เทคนิคที่คุณใช้อาจแตกต่างกันมาก

ฉันพยายามคิดด้วยสถานการณ์ที่แตกต่างกัน

  • ขอ db
  • ดาวน์โหลดไฟล์

คำร้องขอเข้าสู่ระบบอย่างง่ายไปยัง db (หมายถึงการตอบสนองจาก db ด้วย one elemt) ไม่ต้องการความคืบหน้าของรายงาน async หรือ backgroundworker ที่นี่คุณเพียงแค่ต้องการโทรกลับหนึ่งครั้งเพื่อให้ได้ผลลัพธ์

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

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

ในแนวทางของฉันฉันใช้ตรรกะความก้าวหน้าทางธุรกิจของฉันกับลูกค้าของฉันเท่านั้นหลีกเลี่ยงการแบ่งปันวัตถุอื่น ๆ กับจุดสิ้นสุด


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