Eşzamansız görevler kötü bir UX yaptığında


9

Umutsuzca ihtiyacı olan bir IDE genişleten bir COM eklentisi yazıyorum. İlgili birçok özellik var, ancak bu yazı uğruna 2'ye daraltalım:

  • Kullanıcının modüllerde ve üyelerinde gezinmesine olanak tanıyan bir treeview görüntüleyen bir Kod Gezgini araç penceresi vardır .
  • Kullanıcının kod sorunlarında gezinmesini ve bunları otomatik olarak düzeltmesini sağlayan bir veri görünümü gösteren bir Kod Denetimleri araç penceresi vardır .

Her iki araçta da, açılan tüm projelerde tüm kodu ayrıştıran zaman uyumsuz bir görevi başlatan bir "Yenile" düğmesi vardır; Kod Explorer inşa etmek ayrıştırma sonuçları kullanan ağaç ve Kod Denetimleri kodu sorunlarını bulup onun içinde sonuçlarını görüntülemek için ayrıştırma sonuçlarını kullanır DataGridView .

Burada yapmaya çalıştığım, Kod Gezgini yenilendiğinde, Kod Denetimleri bunu bilir ve Kod Gezgini'nin yaptığı ayrıştırma işlemini yeniden yapmak zorunda kalmadan kendini yenileyebilmesi için ayrıştırma sonuçlarını özellikler arasında paylaşmaktır. .

Ne yaptım, ayrıştırıcı sınıfımı özellikleri kayıt olabilir bir olay sağlayıcı yaptı:

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

Ve çalışıyor. Sahip olduğum sorun, bu ... işe yarıyor - Yani, kod denetimleri yenilendiğinde, ayrıştırıcı kod gezgini (ve herkes) söyler "ahbap, birisi ayrıştırma, bu konuda yapmak istediğiniz bir şey? " - ve ayrıştırma tamamlandığında, ayrıştırıcı dinleyicilerine "çocuklar, sizin için taze ayrıştırma sonuçlarım var, bu konuda yapmak istediğiniz herhangi bir şey var mı?"

Bunun yarattığı sorunu göstermek için size bir örnek vereyim:

  • Kullanıcı "bekle, ben burada çalışıyorum" söyleyen Kod Gezgini getirir; kullanıcı IDE üzerinde çalışmaya devam ediyor, Kod Gezgini kendini yeniden çiziyor, hayat güzel.
  • Kullanıcı daha sonra kullanıcıya "bekle, burada çalışıyorum" diyen Kod Denetimlerini getirir; Ayrıştırıcı Kod Gezgini'ne "dostum, birisi ayrışıyor, bu konuda yapmak istediğiniz herhangi bir şey?" - Kod Gezgini kullanıcıya "bekle, burada çalışıyorum"; kullanıcı IDE'de çalışmaya devam edebilir, ancak yenilendiği için Kod Gezgini'nde gezinemez. Kod denetimlerinin de tamamlanmasını bekliyor.
  • Kullanıcı ele almak istediği inceleme sonuçlarında bir kod sorunu görür; ona gitmek için çift tıklayın, kodla ilgili bir sorun olduğunu onaylayın ve "Düzelt" düğmesini tıklayın. Modül değiştirildi ve yeniden ayrıştırılması gerekiyor, bu nedenle kod denetimleri onunla devam ediyor; Kod Gezgini kullanıcıya "bekle, burada çalışıyorum", ...

Bunun nereye gittiğini görüyor musunuz? Sevmiyorum ve bahse girerim kullanıcılar da sevmez. Neyi kaçırıyorum? Ayrıştırma sonuçlarını özellikler arasında paylaşmaya nasıl devam etmeliyim, ancak yine de özelliğin ne zaman çalışması gerektiğini kontrol eden kullanıcıyı nasıl kontrol edebilirim ?

Sormamın nedeni, gerçek çalışmayı kullanıcı aktif olarak yenilemeye karar verene kadar ertelersem ve ayrıştırma sonuçlarını geldikçe "önbelleğe alsaydım ..." Muhtemelen eski bir ayrıştırma sonucundaki kod sorunlarını bulma ... kelimenin tam anlamıyla beni her bir özelliğin kendi ayrıştırma sonuçlarıyla çalıştığı bir kareye geri getiriyor: ayrıştırma sonuçlarını özellikler arasında paylaşabilmem ve güzel bir UX almamın bir yolu var mı?

Kod , ama kod aramıyorum, kavramları arıyorum .


2
Sadece bir FYI, aynı zamanda bir UserExperience.SE sitemiz de var . Bu konu üzerine inanıyorum çünkü kod tasarımı kullanıcı arayüzünden daha fazla tartışıyor, ancak değişikliklerinizin sorunun kod / tasarım tarafına değil, kullanıcı arayüzüne doğru kayması durumunda size bildirmek istedim.

Ayrıştırırken, bu bir ya hep ya hiç operasyonu mu? Örneğin: bir dosyadaki bir değişiklik tam bir onarımı mı tetikliyor, yoksa yalnızca bu dosya ve ona bağlı olanlar için mi?
Morgen

@Morgen iki şey var: VBAParserANTLR tarafından üretiliyor ve bana bir ayrıştırma ağacı veriyor, ancak özellikler bunu tüketmiyor. RubberduckParserAyrıştırma ağacını alır onu yürür ve sorunlar bir VBProjectParseResultiçerdiğini Declarationolan nesneleri tüm bunların Referencesçözülmesi - en o özellikler girişi için almak neyi .. bu yüzden evet, hemen hemen hepsi ya hiç bir durum. Yine RubberduckParserde değiştirilmemiş modülleri yeniden ayrıştırmayacak kadar akıllıdır. Ancak bir darboğaz varsa ayrıştırma ile değil, kod denetimleri ile.
Mathieu Guindon

4
Bence, bunu şöyle yaparım: Kullanıcı bir yenileme tetiklediğinde, bu araç penceresi ayrıştırmayı tetikler ve çalıştığını gösterir. Diğer araç pencereleri henüz bildirilmemiştir, eski bilgileri görüntülemeye devam ederler. Ayrıştırıcı bitene kadar. Bu noktada, ayrıştırıcı, yeni araçlarla görüşlerini yenilemek için tüm araç pencerelerini işaret eder. Ayrıştırıcı çalışırken kullanıcı başka bir araç penceresine giderse, bu pencere "çalışıyor ..." durumuna da girer ve bir yeniden ayrıştırma sinyali verir. Ayrıştırıcı daha sonra tüm pencerelere aynı anda güncel bilgi vermeye başlayacaktır.
cmaster - monica

2
@cmaster Bu yorumu da cevap olarak değerlendiririm.
RubberDuck

Yanıtlar:


7

Muhtemelen buna yaklaşma şeklim mükemmel sonuçlar vermeye daha az odaklanmak ve bunun yerine en iyi çaba yaklaşımına odaklanmak olacaktır. Bu, en azından aşağıdaki değişikliklerle sonuçlanır:

  • Şu anda yeniden ayrıştırma başlatan mantığı başlatma yerine isteğe dönüştürün.

    Yeniden ayrıştırma isteğinde bulunma mantığı şu şekilde görünebilir:

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

    Bu, ayrıştırıcıyı saran mantık ile eşleştirilir, bu şöyle görünebilir:

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

    Önemli olan, ayrıştırıcının en son yeniden ayrıştırma isteği yerine getirilinceye kadar çalıştırılmasıdır, ancak herhangi bir zamanda birden fazla ayrıştırıcı çalışmaz.

  • ParseStartedGeri aramayı kaldırın . Yeniden ayrıştırma istemek artık bir yangın ve unut operasyonudur.

    Alternatif olarak, GUI'nin kullanıcı etkileşimini engellemeyen bazı kısımlarında canlandırıcı bir gösterge göstermek dışında hiçbir şey yapmaya dönüştürmeyin.

  • Eski sonuçlar için minimum kullanım sağlamaya çalışın.

    Kod Gezgini'nde, kullanıcının gitmek istediği yöntem için makul sayıda satır yukarı ve aşağı veya tam bir ad bulunamamışsa en yakın yöntem aramak kadar basit olabilir.

    Kod Denetçisi için neyin uygun olacağını bilmiyorum.

Uygulama ayrıntılarından emin değilim, ancak genel olarak, bu NetBeans düzenleyicisinin bu davranışı nasıl ele aldığına çok benzer. Şu anda yenilendiğini belirtmek her zaman çok hızlıdır, ancak aynı zamanda işlevselliğe erişimi engellemez.

Eski sonuçlar genellikle yeterince iyidir - özellikle hiçbir sonuçla karşılaştırıldığında.


1
Mükemmel noktalar, ama bir sorum var: ParseStarted[Yenile] düğmesini ( Control.EnableRefresh(false)) devre dışı bırakmak için kullanıyorum . Bu geri aramayı kaldırır ve kullanıcının tıklatmasına izin verirsem ... o zaman kendimi ayrıştırma yaparken iki eşzamanlı görevimin olduğu bir duruma koyardım ... birisi iken diğer tüm işlevlerde yenilemeyi devre dışı bırakmadan nasıl önlerim ayrıştırma mı?
Mathieu Guindon

@ Mat'sMug Yanıtımı sorunun o yönünü içerecek şekilde güncelledim.
Morgen

Bu yaklaşıma katılıyorum, ancak ParseStartedUI'nin (veya başka bir bileşenin) bazen kullanıcıyı bir tamirin gerçekleştiği konusunda uyarmasına izin vermek istemeniz durumunda, yine de bir olayı saklıyorum. Tabii ki, deneyeceği belge arayanlar isteyebilirsiniz değil (olmak üzere) bayat akım ayrıştırma sonuçlarını kullanarak kullanıcıyı durdurun.
Mark Hurd
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.