Как строить асинхронное приложение?

  • Приложение работает сразу с несколькими удалёнными веб-сервисами, ответы от которых поступают не мгновенно;
  • В интерфейсе приложения используются мини-анимации, занимающие время (напр. выезд панели);
  • Действия пользователя-невротика могут быть хаотичными и непредсказуемыми (как пример-гипербола: ребёнок уселся за папин комп или мы просто тестируем апп, подавая шум случайных кликов на вход для тестирования защиты от дурака — в общем, пользователь не всегда дожидается окончания длительной процедуры).

Как строить такое приложение: оптимально, прозрачно, «правильно» — чтобы учитывать все возможные комбинации состояниий каждого из элементов?

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

Второй вопрос: покажите, пожалуйста, удачный пример визуализированной схемы алгоритма такого приложения — будь то UML диаграмма, или карандашный скетч с ромбиками Если — Да — Нет.
  • Вопрос задан
  • 5242 просмотра
Решения вопроса 1
rfq
@rfq
Программист
В общем это dataflow граф, где узлы срабатывают, когда по всем входящим дугам пришли данные (как в (раскрашенных) сетях Петри). С этой точки зрения callback — это дуга, переданная в сообщении и в которую надо отправить ответ.

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

Для actionscript готовых решений не знаю, знаю только для java — df4j (сам написал, очень простая).

en.wikipedia.org/wiki/Flow-based_programming

Модель_акторов:
ru.wikipedia.org/wiki/%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B0%D0%BA%D1%82%D0%BE%D1%80%D0%BE%D0%B2
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
taliban
@taliban
php программист
ru.wikipedia.org/wiki/Callback_(программирование) Не в паттернах дело, грубо говоря при начале какого-то действия, отдавайте в него же калбак, который должен выполниться по завершению, и при выполнении калбака смотрите, нужно ли еще это действие. Так приложение будет работать асинхронно, и не будет перетирать данные других действий, если человек недождался предидущего и нажал что-то новое.
Ответ написан
@dsd_corp
Может есть смысл завести массив запрашиваемых наборов данных и заполнять их по мере приема, а из кусков интерфейса периодически проверять, не появились ли данные для текущего представления?
Что-то вроде массива или структуры:
struct my_data {
  bool received;
  uint32 request_time;
  uint32 receive_time;
  uint8 *buff;
  data_struct unpacked_data;
  ...
};

struct my_data_storage {
  struct my_data *main_data;
  struct my_data *section1_data;
  struct my_data *section2_data;
  ...
};

Соответственно при открытии любого интерфейсного блока(section) он запрашивает свои данные у… назовем это «контроллер коммуникации» — поток или объект, отвечающий за работу с удаленными серверами. Далее интерфейсный блок ждет, периодически проверяя готовность данных и отображая что там вы отображаете(крутящееся колесо или пустую табличку или еще что).

Можно контролировать таймауты приема, устаревание данных и т.п., поля request_time и receive_time у структуры блока данных в помощь.

Пример алгоритма:
— Пользователь открывает в интерфейсе блок section1.
— Показываем этот кусок интерфейса пустым или с крутящимся колесом.
— Смотрим в хранилище данных данных на поле section1_data.
— — Если оно NULL, интерфейс шлет запрос данных контроллеру коммуникации, тот в свою очередь шлет запрос данных к серверу, создавая и инициализируя начальными значениями в этом поле структуру my_data.
— — Если оно не NULL, смотрим на поле received(данные приняты и распарсены полностью). Если данные еще не приняты, ждем дальше. Если данные приняты, смотрим по receive_time их актуальность, если еще актуальны(таймаут устаревания не прошел), то отображаем, если нет — перезапрашиваем еще раз(при этом поле section1_data обнуляется и пересоздается заново, либо просто переинициализируется).
Контроллер коммуникации например может сам контролировать таймаут приема данных и выставлять флаг неудачного запроса.
Ну и т.п.
Многое зависит от того, на чем вы пишете, под какую систему, от реализации интерфейса и т.п. Как это все вместе соединить, вам решать под себя.

То есть суть в том, что каждый элемент интерфейса работает независимо от других: лезет в хранилище за своим набором данных, инициирует их запрос с сервера, заведует отображением и т.п.
Вот как-то так. Не судите строго, это просто первое, что пришло в голову по прочтении вашего вопроса.
Ответ написан
grossws
@grossws
Кроме callback'ов стоить вспомнить про continuation. Некое его подобие в AS его скорее всего можно реализовать.
Ответ написан
Комментировать
sergiks
@sergiks Автор вопроса, куратор тега Алгоритмы
♬♬
На SO дельно порекомендовали фреймворк pureMVC — в основной реализации написан под AS3, есть порты под JS, C, JAVA, PHP, Ruby и другие языки. Если не использовать сходу, то хотя бы оценить грамотность реализации можно, посмотрев вводные презентации об устройстве фреймворка. Автор говорит несколько монотонно, поэтому запаситесь кофе. Но сделал он действительно умную штуку: MVC, обёрнутая за Facade'ом, возможность много-сущностных модульных конструкций. Вдохновляет. Вполне вероятно, буду использовать — и для серверного бэкенда и для Flash/Air клиентов.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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