비동기 작업이 잘못된 UX를 만드는 경우


9

필자는 IDE를 필사적으로 확장하는 COM 추가 기능을 작성 중입니다. 관련된 많은 기능이 있지만이 게시물을 위해 2로 좁 힙니다.

  • 사용자가 모듈과 해당 멤버를 탐색 할 수 있는 트리 보기를 표시 하는 코드 탐색기 도구 창이 있습니다.
  • 있다 코드 검사는 그 디스플레이한다 toolwindow DataGridView를 사용자 탐색 코드 문제를 수하고 자동으로 수정.

두 도구에는 열려있는 모든 프로젝트의 모든 코드를 구문 분석하는 비동기 작업을 시작하는 "새로 고침"버튼이 있습니다. 코드 탐색기를 빌드하기 위해 구문 분석 결과를 사용 트 리뷰를 하고, 코드 검사는 코드 문제를 발견하고 그것의 결과를 표시하는 구문 분석 결과를 사용 된 DataGridView를 .

내가 여기서하려고하는 것은 코드 탐색기가 새로 고쳐지면 코드 검사 가이를 알고 코드 탐색기가 방금 수행 한 구문 분석 작업을 다시 수행하지 않고도 자체적으로 새로 고칠 수 있도록 기능 간 구문 분석 결과를 공유하는 것입니다. .

그래서 내가 한 일은 파서 클래스를 기능이 등록 할 수있는 이벤트 공급자로 만들었습니다.

    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);
            }
        });
    }

그리고 작동합니다. 내가 겪고있는 문제는 ... 그것은 작동한다는 것입니다. 코드 검사가 새로 고쳐지면 파서는 코드 탐색기 (및 다른 모든 사람)에게 "친구, 누군가의 파싱, 당신이하고 싶은 일을하고 있습니까?"라고 말합니다. " -파싱이 완료되면 파서는 청취자에게 "얘들 아, 나는 당신을 위해 신선한 파싱 결과를 가지고있다.

이것이 만들어내는 문제를 설명하기 위해 예를 들어 보겠습니다.

  • 사용자는 코드 탐색기를 열어 사용자에게 "잠깐만 요, 여기서 일하고 있습니다"라고 알려줍니다. 사용자는 IDE에서 계속 작업하고 코드 탐색기가 다시 그려지고 인생은 아름답습니다.
  • 그런 다음 사용자는 코드 검사를 표시하여 사용자에게 "여기서 작업 중입니다"라고 알려줍니다. 파서는 코드 탐색기에 "친구, 누군가의 파싱, 당신이하고 싶은 일이 있습니까?" -코드 탐색기는 사용자에게 "잠깐만 요, 여기서 일하고 있습니다"라고 알려줍니다. 사용자는 여전히 IDE에서 작업 할 수 있지만 새로 고침되므로 코드 탐색기를 탐색 할 수 없습니다. 또한 코드 검사가 완료되기를 기다리고 있습니다.
  • 사용자는 해결하려는 검사 결과에서 코드 문제를 보게됩니다. 두 번 클릭하여 코드를 탐색하고 코드에 문제가 있는지 확인한 다음 "수정"단추를 클릭하십시오. 모듈이 수정되었고 다시 구문 분석되어야하므로 코드 검사가 진행됩니다. 코드 탐색기는 사용자에게 "잠깐만 요, 여기서 일하고 있어요"라고 알려줍니다.

어디로 가는지 봅니까? 나는 그것을 좋아하지 않으며, 사용자가 그것을 좋아하지 않을 것입니다. 내가 무엇을 놓치고 있습니까? 어떻게 기능 사이의 구문 분석 결과를 공유 가야하지만, 여전히 기능이시기의 제어에 사용자를 떠나야한다 그 일을 ?

내가 묻는 이유는 사용자가 적극적으로 새로 고침을 결정할 때까지 실제 작업을 연기하고 구문 분석 결과가 "캐시"될 때까지 파악하면 트리 뷰를 새로 고칠 것입니다. 말 그대로 각 기능은 자신의 구문 분석 결과와 함께 작동 원점으로, 저를 다시 가져 오는 가능성이 오래된 구문 분석 결과 ... 코드 문제를 위치 : 나는 기능과 구문 분석 결과를 공유 할 수있는 방법이 사랑스러운 UX를 가지고는?

코드는 이지만 코드를 찾지 않고 개념을 찾고 있습니다.


2
참고로 UserExperience.SE 사이트도 있습니다. 나는 이것이 사용자 인터페이스 보다 코드 디자인에 대해 논의하기 때문에 여기에 주제가 있다고 생각 하지만 변경 사항이 문제의 코드 / 디자인 측면이 아닌 UI쪽으로 더 많이 드리프트하는 경우 알려 드리고자합니다.

구문 분석 할 때이 작업이 전혀 또는 전혀없는 작업입니까? 예를 들어, 파일을 변경하면 전체 재분석이 트리거됩니까? 아니면 해당 파일과 파일에 종속 된 파일 만 다시 실행됩니까?
Morgen

@ Morgen 두 가지가 있습니다 : VBAParserANTLR에 의해 생성되고 구문 분석 트리를 제공하지만 기능은 그것을 소비하지 않습니다. 는 RubberduckParser, 구문 분석 트리를 취를 산책하고, 발행 VBProjectParseResult포함 된 Declaration이 객체를 모든 References해결 - 의 것이 특징은 입력을 가지고 무슨 일이 ... 그래서 그래, 그것은 꽤 많이 모 아니면도 상황이다. 는 RubberduckParser하지만 수정되지 않았을 다시 구문 분석 모듈을 스마트 충분하다. 그러나 병목 현상이 발생하면 구문 분석이 아닌 코드 검사가 필요합니다.
Mathieu Guindon

4
사용자가 새로 고침을 트리거하면 해당 도구 창이 구문 분석을 트리거하고 작동하고 있음을 보여줍니다. 다른 도구 창에는 아직 알림이 표시되지 않고 이전 정보가 계속 표시됩니다. 파서가 끝날 때까지. 이 시점에서 파서는 모든 정보창에 새로운 정보로 화면을 갱신하라는 신호를 보냅니다. 파서가 작동하는 동안 사용자가 다른 도구 창으로 이동하면 해당 창이 "작업 중 ..."상태가되어 재분석을 알립니다. 그러면 파서는 모든 창에 동시에 최신 정보를 전달하기 위해 다시 시작합니다.
cmaster-monica reinstate

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 Inspector에 무엇이 적합한 지 잘 모르겠습니다.

구현 세부 정보는 확실하지 않지만 전반적으로 NetBeans 편집기 가이 동작을 처리하는 방식과 매우 유사합니다. 현재 새로 고침 중이지만 기능에 대한 액세스를 차단하지는 않는다는 점을 항상 매우 빠르게 알 수 있습니다.

오래된 결과는 종종 충분합니다. 특히 결과가없는 것과 비교할 때 더욱 좋습니다.


1
훌륭한 점이지만 질문이 있습니다. ParseStarted[새로 고침] 버튼 ( Control.EnableRefresh(false)) 을 비활성화하는 데 사용하고 있습니다. 콜백을 제거하고 사용자가 클릭하도록하면 파싱을 수행하는 두 개의 동시 작업이있는 상황에 처하게됩니다. 파싱 ​​중입니까?
Mathieu Guindon

@ Mat'sMug 문제의 그 측면을 포함하도록 답변을 업데이트했습니다.
Morgen

ParseStartedUI (또는 다른 구성 요소)가 때때로 사용자에게 재분석이 발생하도록 경고하도록 허용하려는 경우 이벤트를 계속한다는 점을 제외 하고는이 접근법에 동의 합니다. 물론, 발신자가 사용자가 (현재 예정된) 오래된 구문 분석 결과를 사용 하지 못하도록 시도해서는 안됩니다 .
Mark Hurd
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.