Конечные автоматы и работа Пользовательского интерфейса — какие-либо примеры/опыт?

Как насчет:

public override int GetHashCode()
{
    return string.Format("{0}_{1}_{2}", prop1, prop2, prop3).GetHashCode();
}

Предполагая, что производительность не является проблемой:)

30
задан John Topley 27 February 2009 в 17:16
поделиться

9 ответов

Это не UI, который должен быть смоделирован как конечный автомат; это - объекты, отображаемые, что может быть полезно смоделировать как конечные автоматы. Ваш UI тогда становится (упрощение) набором обработчиков событий для изменения состояния в различных объектах.

Это - изменение от:

DoSomethingToTheFooObject();  
UpdateDisplay1();  // which is the main display for the Foo object  
UpdateDisplay2();  // which has a label showing the Foo's width,
                   // which may have changed  
...  

к:

Foo.DoSomething();  

void OnFooWidthChanged() { UpdateDisplay2(); }  
void OnFooPaletteChanged() { UpdateDisplay1(); }  

Взгляды о том, какие изменения в данных Вы отображаете, должны вызвать то, что перекрашивание может разъяснять, и от клиента сторона UI и от сервера сторона Foo.

, Если Вы находите, что, 100 штук UI, которые, возможно, должны быть перекрашены, когда изменения состояния Foo, все они должны быть перерисованы, когда палитра изменяется, но только 10, когда ширина изменяется, она могла бы предложить что-то о том, о чем должны сигнализировать события/изменения состояния Foo. Если Вы находите, что у Вас есть большой обработчик событий OnFooStateChanged (), который посылает багажом свойства многого Foo для наблюдения то, что изменилось в попытке минимизировать обновления UI, он предлагает что-то о гранулярности модели событий Foo. Если Вы находите, что хотите записать немного автономного виджета UI, который можно использовать в нескольких местах в UI, но что он должен знать, когда Foo изменяется, и Вы не хотите включать весь код, который реализация Foo приносит с ним, он предлагает что-то об организации Вас данные относительно Вашего UI, где Вы используете классы по сравнению с интерфейсами, и т.д. Существенно, он заставляет Вас думать более серьезно о том, что Ваш уровень представления, более серьезно, чем "весь код в моих классах формы".

- ПК

9
ответ дан Frank Krueger 11 October 2019 в 13:10
поделиться

Я в настоящее время работаю с (собственной) платформой, которая предоставляет себя хорошо UI-as-state-machine парадигме, и она может определенно уменьшить (но не устранить), проблемы со сложными и непредвиденными взаимодействиями между элементами UI.

основное преимущество - то, что это позволяет Вам думать в более высоком уровне абстракции при более высокой гранулярности. Вместо того, чтобы думать, "Если кнопка A нажимается тогда, заблокировано поле комбинированного списка B, текстовое поле C очищено и и Кнопка D разблокирована", Вы думаете, что "Нажимающая кнопка A помещает приложение в ПРОВЕРЕННОЕ состояние" - и ввод того состояния означает, что определенные вещи происходят.

я не думаю, что это полезно (или даже возможно) смоделировать весь UI как единственный конечный автомат, все же. Вместо этого обычно существует много конечных автоматов меньшего размера, что каждый обрабатывает одну часть UI (состоящий из нескольких средств управления, которые взаимодействуют и принадлежат вместе концептуально), и один (возможно, больше чем один) "глобальный" конечный автомат, который обрабатывает более основные проблемы.

30
ответ дан Michael Borgwardt 11 October 2019 в 13:10
поделиться

Эй Morgan, мы создаем пользовательскую платформу в AS3 здесь в Radical и используем парадигму конечного автомата для включения любого фронтэнда действие UI.

у Нас есть установка конечного автомата для всех событий кнопки, всех событий дисплея и т.д.

AS3, будучи управляемым событиями языком, делает это очень привлекательной опцией.

, Когда определенные события пойманы, состояния кнопок / экранные объекты автоматически изменяются.

Наличие обобщенного набора состояний могло определенно помочь de-spaghttify Ваш код!

2
ответ дан Praveen Sharma 11 October 2019 в 13:10
поделиться

Каждый интерфейсный объект это представлено пользователю, может перейти к другому состоянию от текущего. В основном необходимо создать карту того, что кнопка может привести к какой другое состояние.

Это отображение позволит Вам видеть неиспользованные состояния или, куда несколько кнопок или путей могут привести к тому же состоянию и никаким другим (которые могут быть объединены).

2
ответ дан Jeremy L 11 October 2019 в 13:10
поделиться

Конечный автомат - что-то, что позволяет коду работать с другими конечными автоматами. Конечный автомат является просто логикой, которая имеет память прошедших событий.

Поэтому люди являются конечными автоматами, и часто они ожидают, что их программное обеспечение будет помнить то, что они сделали в прошлом так, чтобы они могли продолжиться.

, Например, можно поместить весь обзор на одной странице, но люди более довольны несколькими меньшими страницами вопросов. То же с регистрациями пользователя.

Так конечный автомат имеют партия из применимости для пользовательских интерфейсов.

Они должны быть поняты прежде чем быть развернутым, тем не менее, и весь дизайн должен быть завершен, прежде чем код будет написан - конечный автомат может, быть, и будет неправильно использован, и если у Вас нет очень четкого представления о том, почему Вы используете один, и какова цель, можно закончить оказывающиеся в худшем положении, чем другие методы.

-Adam

1
ответ дан Adam Davis 11 October 2019 в 13:10
поделиться

Конечные автоматы являются слишком обычно низким уровнем, чтобы помочь Вам думать о пользовательском интерфейсе. Они делают хороший выбор реализации для инструментария UI, но существует только слишком много состояний и переходов для описания в нормальном приложении для Вас для описания их вручную.

мне нравится думать о UIs с продолжениями. (Google это - термин является достаточно конкретным, что Вы получите много высококачественных хитов.)

Вместо моих приложений, находящихся в различных состояниях, представленных флагами состояния и режимами, я использую продолжения для управления тем, что приложение делает затем. Является самым легким объяснить с примером. Скажите, что Вы хотите открыть диалоговое окно подтверждения прежде, чем послать электронное письмо. Шаг 1 создает электронное письмо. Шаг 2 получает подтверждение. Шаг 3 посылает электронное письмо. Большинство инструментариев UI требует, чтобы Вы пасовали назад управление к циклу событий после каждого шага, который делает это действительно ужасным, при попытке представить его с конечным автоматом. С продолжениями Вы не думаете с точки зрения шагов силы инструментария на Вас - это - весь один процесс создания и отправки электронного письма. Однако, когда для процесса нужно подтверждение, Вы получаете состояние своего приложения в продолжении и вручаете то продолжение кнопке OK на диалоговом окне подтверждения. Когда хорошо нажимается, Ваше приложение продолжается от того, где это было.

Продолжения относительно редки на языках программирования, но к счастью можно получить вид версии бедного человека с помощью закрытий. Возвращение к электронной почте, отправляющей пример, в точке, необходимо получить подтверждение, которое Вы пишете остальной части процесса как закрытие и затем вручаете то закрытие кнопке OK. Закрытия являются видом подобных анонимных вложенных подпрограмм, которые помнят значения всех Ваших локальных переменных в следующий раз, когда их называют.

, Надо надеяться, это дает Вам некоторые новые направления для размышления о. Я попытаюсь возвратиться позже с реальным кодом, чтобы показать Вам, как он работает.

Обновление: вот полный пример с QT в Ruby. Интересные части находятся в ConfirmationButton и MailButton. Я не QT или эксперт Ruby, таким образом, я ценил бы любые улучшения, которые можно предложить.

require 'Qt4'

class ConfirmationWindow < Qt::Widget
  def initialize(question, to_do_next)
    super()

    label = Qt::Label.new(question)
    ok = ConfirmationButton.new("OK")
    ok.to_do_next = to_do_next
    cancel = Qt::PushButton.new("Cancel")

    Qt::Object::connect(ok, SIGNAL('clicked()'), ok, SLOT('confirmAction()'))
    Qt::Object::connect(ok, SIGNAL('clicked()'), self, SLOT('close()'))
    Qt::Object::connect(cancel, SIGNAL('clicked()'), self, SLOT('close()'))

    box = Qt::HBoxLayout.new()
    box.addWidget(label)
    box.addWidget(ok)
    box.addWidget(cancel)

    setLayout(box)
  end
end

class ConfirmationButton < Qt::PushButton
  slots 'confirmAction()'
  attr_accessor :to_do_next
  def confirmAction()
    @to_do_next.call()
  end
end

class MailButton < Qt::PushButton
  slots 'sendMail()'
  def sendMail()
    lucky = rand().to_s()
    message = "hello world. here's your lucky number: " + lucky
    do_next = lambda {
      # Everything in this block will be delayed until the
      # the confirmation button is clicked. All the local
      # variables calculated earlier in this method will retain
      # their values.
      print "sending mail: " + message + "\n"
    }
    popup = ConfirmationWindow.new("Really send " + lucky + "?", do_next)
    popup.show()
  end
end

app = Qt::Application.new(ARGV)

window = Qt::Widget.new()
send_mail = MailButton.new("Send Mail")
quit = Qt::PushButton.new("Quit")

Qt::Object::connect(send_mail, SIGNAL('clicked()'), send_mail, SLOT('sendMail()'))
Qt::Object::connect(quit, SIGNAL('clicked()'), app, SLOT('quit()'))

box = Qt::VBoxLayout.new(window)
box.addWidget(send_mail)
box.addWidget(quit)

window.setLayout(box)
window.show()
app.exec()
10
ответ дан Ken Fox 11 October 2019 в 13:10
поделиться

Не действительно проблема UI, чтобы быть честным.

я сделал бы следующее:

  1. Определяют Ваши состояния
  2. , Определяют Ваш transiations - какие состояния доступны от который другие?
  3. , Как эти переходы инициированы? Каковы события?
  4. Запись Ваш конечный автомат - хранит текущее состояние, получает события, и если то событие может вызвать допустимый переход от текущего состояния, тогда изменяют состояние соответственно.
3
ответ дан PaulJWilliams 11 October 2019 в 13:10
поделиться

На эту тему есть книга. К сожалению, он распродан, а доступные редко используемые б / у стоят очень дорого.

Constructing the User Interface with Statecharts
by Ian Horrocks, Addison-Wesley, 1998
7
ответ дан 27 November 2019 в 23:27
поделиться

Я получил презентацию о шаблоне, который я назвал "State First".

Это комбинация MPV / IoC / FSM, и я успешно использовал ее в .Net / WinForms, .Net / Silverlight и Flex (на данный момент).

Вы начинаете с написания кода вашего FSM:

class FSM
    IViewFactory ViewFactory;
    IModelFactory ModelFactory;
    Container Container; // e.g. a StackPanel in SL
    ctor((viewFactory,modelFactory,container) {
        ...assignments...
        start();
    }

    start() {
        var view = ViewFactory.Start();
        var model = ModelFactory.Start();
        view.Context = model;
        view.Login += (s,e) => {
            var loginResult = model.TryLogin(); // vm contains username/password now
            if(loginResult.Error) {
                // show error?
            } else {
                loggedIn(loginResult.UserModel); // jump to loggedIn-state
            }
        };
        show(view);
    }


    loggedIn(UserModel model) {
        var view = ViewFactory.LoggedIn();
        view.Context = model;
        view.Logout += (s,e) => {
            start(); // jump to start
        };
        show(view);
    }

Затем вы создаете свои IViewFactory и IModelFactory (ваш FSM позволяет легко увидеть, что вам нужно)

public interface IViewFactory {
    IStartView Start();
    ILoggedInView LoggedIn();
}

public interface IModelFactory {
    IStartModel Start();
}

Теперь все, что вам нужно сделать, это реализовать IViewFactory , IModelFactory , IStartView , ILoggedInView и модели. Преимущество здесь в том, что вы можете видеть все переходы в FSM, вы получаете сверхнизкую связь между представлениями / моделями, высокую тестируемость и (если ваш язык позволяет) большое количество безопасных типов.

Один важный момент в использовании FSM - это то, что вам нельзя • просто переходите между состояниями - вы также должны переносить все данные о состоянии при переходе (в качестве аргументов см. loggedIn выше). Это поможет вам избежать глобальных состояний, которые обычно засоряют графический код.

Вы можете посмотреть презентацию по адресу http://prezi.com/bqcr5nhcdhqu/ , но на данный момент она не содержит примеров кода.

1127160]

3
ответ дан 27 November 2019 в 23:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: