Я читал текст Уди Дахана о [разделении командных запросов и SOA][1]. Размышление о том, как я буду использовать это на практике в системе, над которой я сейчас работаю, вызвало некоторые вопросы...
1.
Рассмотрим следующую ситуацию, когда у меня есть клиентское приложение WPF, которое позволяет пользователю редактировать список записей:
Клиентское приложение запущено. При запуске он подписывается на службу команд, которая будет обрабатывать и публиковать изменения в записях, и запрашивает у службы WCF полный список записей. После получения списка записей любые изменения (другими клиентами), которые могли быть опубликованы в очереди клиентов, пока она была занята ожиданием ответа от WCF, объединяются в список.
Теперь мне кажется, что существует (вероятно, очень маленькая) вероятность того, что клиент подпишется сразу после обработки команды, ответственной за изменение, и что запрос службы WCS будет запущен непосредственно перед тем, как то же самое изменение будет зафиксировано в базе данных. В этой ситуации я получу неверные данные в моем клиенте, которые не синхронизируются (и никогда не будут синхронизированы) с базой данных (если клиентское приложение не будет перезапущено). Действительно ли существует эта проблема, и если да, то как ее решить?
2. Мой второй вопрос о том, как разработать/реализовать пользовательский интерфейс:
Теперь пользователь хочет изменить запись в списке; всплывающее окно, данные изменены и нажата кнопка ok: мы отправляем сообщение нашему обработчику команд для обработки этого изменения. Пользователь ожидает увидеть либо подтверждение (запись в списке изменится), либо сообщение об ошибке.
Теперь я могу попытаться обрабатывать вещи в пользовательском интерфейсе «синхронным» способом (позволить пользователю делать одно действие за раз и позволить ему дождаться успеха или неудачи, прежде чем ему будет разрешено делать что-либо еще) следующим образом:
- После того, как пользователь нажмет «ОК», отключите все элементы управления, чтобы дальнейшее редактирование было невозможно.
- Создать сагу с тайм-аутом, который ждет ...? Ответное сообщение? Опубликованное уведомление от командной службы? Оба?
- Когда получено ответное сообщение, данные в списке изменяются, элементы управления включаются, и все готово — или:
- Происходит тайм-аут. Командное сообщение было поставлено в очередь, поэтому изменение в конечном итоге будет выполнено, так что же делать? Показать пользователю сообщение ("это занимает больше времени, чем ожидалось..."), включить все элементы управления и изменить данные в клиенте после получения уведомления от службы команд? Но что, если возвращается ошибка? Пользователь мог начать делать что-то еще (возможно, редактируя другую запись), и всплывающее сообщение об ошибке из предыдущей попытки редактирования не кажется хорошей идеей.
Другой подход, вероятно, состоял бы в том, чтобы просто отправить команду и позволить пользователю продолжить делать то, что он хочет делать дальше. Может быть, показать все невыполненные команды в списке в пользовательском интерфейсе где-нибудь с индикатором успеха или неудачи и возможностью для пользователя отображать сообщение об ошибке в случае сбоя. Учитывая, что тайм-ауты, как мы надеемся, являются исключительными, и что ответы обычно должны быть получены в течение нескольких секунд, это будет означать, что в этом списке обычно должна быть не более 1 невыполненной команды. Это и тот факт, что я не могу вспомнить, что я когда-либо видел пользовательский интерфейс, делающий что-то таким образом, означает, что это, вероятно, не очень хорошая идея.
А твой вопрос? ;)
Ну, мне просто интересно, как другие люди решают это в своих пользовательских интерфейсах. Вероятно, есть лучшие способы обработки вещей в пользовательском интерфейсе, чем два, может быть, не очень умных способа, которые я придумал?
Извините за длинный текст и заранее спасибо за ответы.
[1]: http://www.udidahan.com/2008/08/11/command-query-separation-and-soa/"Разделение командных запросов и SOA"