เมื่องานอะซิงโครนัสทำให้ UX ไม่ดี


9

ฉันกำลังเขียน COM add-in ที่ขยาย IDE ที่ต้องการอย่างยิ่ง มีคุณสมบัติหลายอย่างที่เกี่ยวข้อง แต่ให้แคบลงเป็น 2 เพื่อประโยชน์ของโพสต์นี้:

  • มีเครื่องมือExplorer ในหน้าต่างที่แสดงมุมมองแบบต้นไม้ที่ช่วยให้ผู้ใช้นำทางโมดูลและสมาชิกของพวกเขา
  • มีเครื่องมือตรวจสอบรหัสหน้าต่างที่แสดงDataGridviewที่ให้ผู้ใช้สำรวจปัญหารหัสและแก้ไขให้โดยอัตโนมัติ

เครื่องมือทั้งสองมีปุ่ม "รีเฟรช" ที่เริ่มงานแบบอะซิงโครนัสที่แยกวิเคราะห์รหัสทั้งหมดในโครงการที่เปิดอยู่ทั้งหมด รหัส Explorer ที่ใช้ผลการแจงการสร้างTreeViewและรหัสการตรวจสอบการใช้ผลการแจงที่จะพบปัญหารหัสและแสดงผลลัพธ์ในของDataGridView

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

ดังนั้นสิ่งที่ฉันทำฉันทำให้ parser class เป็นผู้ให้บริการเหตุการณ์ที่คุณสมบัติสามารถลงทะเบียนได้ที่:

    private void _parser_ParseCompleted(object sender, ParseCompletedEventArgs e)
    {
        Control.Invoke((MethodInvoker) delegate
        {
            Control.SolutionTree.Nodes.Clear();
            foreach (var result in e.ParseResults)
            {
                var node = new TreeNode(result.Project.Name);
                node.ImageKey = "Hourglass";
                node.SelectedImageKey = node.ImageKey;

                AddProjectNodes(result, node);
                Control.SolutionTree.Nodes.Add(node);
            }
            Control.EnableRefresh();
        });
    }

    private void _parser_ParseStarted(object sender, ParseStartedEventArgs e)
    {
        Control.Invoke((MethodInvoker) delegate
        {
            Control.EnableRefresh(false);
            Control.SolutionTree.Nodes.Clear();
            foreach (var name in e.ProjectNames)
            {
                var node = new TreeNode(name + " (parsing...)");
                node.ImageKey = "Hourglass";
                node.SelectedImageKey = node.ImageKey;

                Control.SolutionTree.Nodes.Add(node);
            }
        });
    }

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

ให้ฉันแนะนำคุณผ่านตัวอย่างเพื่ออธิบายปัญหาที่เกิดขึ้น:

  • ผู้ใช้เปิดตัว Code Explorer ซึ่งจะบอกผู้ใช้ว่า "หยุดฉันทำงานที่นี่"; ผู้ใช้ยังคงทำงานใน IDE, Code Explorer วาดตัวเองใหม่, ชีวิตมีความสวยงาม
  • จากนั้นผู้ใช้จะเปิดตัวการตรวจสอบโค้ดซึ่งบอกผู้ใช้ว่า "หยุดฉันทำงานที่นี่"; โปรแกรมแยกวิเคราะห์บอก Code Explorer ว่า "เพื่อนการแยกวิเคราะห์ของใครบางคนคุณต้องการทำอะไรกับมัน" - Code Explorer บอกผู้ใช้ว่า "หยุดฉันทำงานที่นี่"; ผู้ใช้ยังคงสามารถทำงานใน IDE ได้ แต่ไม่สามารถนำทาง Code Explorer ได้เนื่องจากมันกำลังรีเฟรช และเขากำลังรอการตรวจสอบโค้ดให้เสร็จสมบูรณ์ด้วย
  • ผู้ใช้เห็นปัญหารหัสในผลลัพธ์การตรวจสอบที่พวกเขาต้องการที่อยู่ พวกเขาคลิกสองครั้งเพื่อนำทางไปยืนยันว่ามีปัญหากับรหัสและคลิกปุ่ม "แก้ไข" โมดูลได้รับการแก้ไขและจำเป็นต้องมีการวิเคราะห์คำซ้ำดังนั้นการตรวจสอบโค้ดจะดำเนินการต่อไป Code Explorer บอกผู้ใช้ว่า "หยุดฉันทำงานที่นี่" ...

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

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

รหัสแต่ฉันไม่ได้มองหารหัสฉันกำลังมองหาแนวคิด


2
เพียงแค่ FYI เรายังมีไซต์UserExperience.SEอีกด้วย ฉันเชื่อว่านี่เป็นหัวข้อในที่นี้เพราะพูดถึงการออกแบบรหัสมากกว่าส่วนติดต่อผู้ใช้แต่ฉันต้องการแจ้งให้คุณทราบในกรณีที่การเปลี่ยนแปลงของคุณเลื่อนไปทางด้าน UI มากกว่าไม่ใช่ด้านรหัส / การออกแบบของปัญหา

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

@ Morgen มีสองสิ่ง: VBAParserสร้างขึ้นโดย ANTLR และให้ต้นไม้การแยกวิเคราะห์ แต่คุณลักษณะไม่ใช้สิ่งนั้น RubberduckParserใช้เวลาต้นไม้แยกที่เดินมันและปัญหาVBProjectParseResultที่มีDeclarationวัตถุที่มีทั้งหมดของพวกเขาReferencesได้รับการแก้ไข - ว่าสิ่งที่มีคุณสมบัติใช้สำหรับการป้อนข้อมูล .. เพื่อใช่ก็สวยมากทุกสถานการณ์หรือไม่มีอะไร RubberduckParserฉลาดพอที่จะไม่โมดูลใหม่แจงที่ยังไม่ได้รับการแก้ไข แต่ แต่ถ้ามีคอขวดไม่ได้อยู่ในการแยกวิเคราะห์ก็คือการตรวจสอบโค้ด
Mathieu Guindon

4
ฉันคิดว่าฉันจะทำเช่นนี้: เมื่อผู้ใช้ทริกเกอร์การรีเฟรชเครื่องมือดังกล่าวเรียกใช้การแยกวิเคราะห์และแสดงว่ามันใช้งานได้ เครื่องมืออื่น ๆ หน้าต่างยังไม่ได้รับแจ้งพวกเขายังคงแสดงข้อมูลเก่า จนกว่าตัวแยกวิเคราะห์จะเสร็จสิ้น ณ จุดนั้นโปรแกรมแยกวิเคราะห์จะส่งสัญญาณเครื่องมือเรียกหน้าต่างทั้งหมดเพื่อรีเฟรชมุมมองด้วยข้อมูลใหม่ หากผู้ใช้ไปที่เครื่องมืออื่น ๆ ในขณะที่ตัวแยกวิเคราะห์ทำงานหน้าต่างนั้นจะเข้าสู่สถานะ "กำลังทำงาน ... " และส่งสัญญาณวิเคราะห์ข้อมูลใหม่ โปรแกรมแยกวิเคราะห์จะเริ่มต้นใหม่เพื่อส่งข้อมูลที่เป็นปัจจุบันไปยังหน้าต่างทั้งหมดในเวลาเดียวกัน
cmaster - คืนสถานะโมนิก้า

2
@cmaster ฉันจะโหวตความคิดเห็นนั้นเป็นคำตอบด้วย
RubberDuck

คำตอบ:


7

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

  • แปลงตรรกะที่ขณะนี้เริ่มการวิเคราะห์คำใหม่เพื่อร้องขอแทนการเริ่มต้น

    ตรรกะสำหรับการขอให้วิเคราะห์คำใหม่อาจสิ้นสุดลงโดยมีลักษณะดังนี้:

    IF parseIsRunning IS false
      startParsingThread()
    ELSE
      SET shouldParse TO true
    END
    

    สิ่งนี้จะจับคู่กับลอจิกการแยกโปรแกรมแยกวิเคราะห์ซึ่งอาจมีลักษณะดังนี้:

    SET parseIsRunning TO true
    DO 
      SET shouldParse TO false
      doParsing()
    WHILE shouldParse IS true
    SET parseIsRunning TO false
    

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

  • ลบการParseStartedโทรกลับ การขอให้วิเคราะห์คำใหม่เป็นไฟและลืมการทำงานไปแล้ว

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

  • พยายามให้การจัดการที่น้อยที่สุดสำหรับผลลัพธ์ที่ค้าง

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

    ฉันไม่แน่ใจว่าอะไรจะเหมาะสมสำหรับผู้ตรวจสอบรหัส

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

ผลลัพธ์ที่ค้างมักจะดีพอ - โดยเฉพาะเมื่อเปรียบเทียบกับผลลัพธ์ที่ไม่มี


1
คะแนนยอดเยี่ยม แต่ฉันมีคำถาม: ฉันใช้ParseStartedเพื่อปิดการใช้งานปุ่ม [รีเฟรช] ( Control.EnableRefresh(false)) ถ้าฉันลบการติดต่อกลับนั้นและให้ผู้ใช้คลิกมัน ... จากนั้นฉันจะทำให้ตัวเองอยู่ในสถานการณ์ที่ฉันมีงานสองอย่างพร้อมกันในการแยกวิเคราะห์ ... ฉันจะหลีกเลี่ยงสิ่งนี้ได้อย่างไรโดยไม่ต้องปิดใช้งานการรีเฟรช กำลังแยก?
Mathieu Guindon

@ Mat'sMug ฉันอัปเดตคำตอบเพื่อรวมแง่มุมของปัญหาแล้ว
Morgen

ฉันเห็นด้วยกับวิธีการนี้ยกเว้นว่าฉันจะยังคงเก็บParseStartedเหตุการณ์ไว้ในกรณีที่คุณต้องการอนุญาตให้ UI (หรือส่วนประกอบอื่น ๆ ) เตือนผู้ใช้ว่าบางครั้งเกิดการแยกวิเคราะห์ซ้ำ แน่นอนคุณอาจต้องการเอกสารผู้โทรควรพยายามที่จะไม่หยุดผู้ใช้จากการใช้ (กำลังจะ) ผลการแยกวิเคราะห์ปัจจุบันค้าง
Mark Hurd
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.