Машины состояний
Машины состояний (State-машины) в простейшем виде присутствует практически в любом Web или Win приложении. Собственно говоря, именно машина состояний придает приложению интеллектуальность, множественность форм его поведения, его ответных реакций на действия человека над приложением.
Вот скажем, в этой, написанной мною банковской системе независимых машин состояний сотни. С одной стороны - это машина состояний управления формами, глубже - машина состояний внутри каждой формы. С другой стороны, машина состояний данных - она защищает от пропадания денег и появления их ниоткуда. Эта машина сложная и многоуровневая, начиная с самого нижнего уровня - откат транзакций при сбоях, кончая самым верхним уровнем - типы операций, поддерживаемых этой финансовой системой, иx зависимости, обналичивания, обезналичивания, конвертации, права на операции, и пр. Но самый последний уровень машины состояний программисру приходится держать в голове у юзера, управляющего программой. Это и называется навыками того или иного юзера по общению с приложением. Скажем, для того чтобы произвести обналичивание денег со своего счета в кассу, надо не только перевести деньги в кассу, и выдать их из кассы кассиром, но пользователь банковской системы должен понимать, что сначала необходимо назначить кассиру права на доступ к кассе.
Для того, чтобы вообще понять способы программирования машин состояний - поясню на простейшем примере машины состояний одной из форм этого банковского приложения. Скажем на этой форме независмых машин состояний всего около десятка. Вот простейшая из них. При открытии формы - кнопка "ПЕРЕВЕСТИ" закрыта, и откроется только после выбора счета назначения перевода и суммы перевода. Другая машина состояний этой формы обеспечивает возврат контролов формы в исходное состояний после выполнения переводов. Еще одна независимая машина состояний работает по контекстному меню журнале операций. Еще одна машина состояний определяет выбранную операцию - обналичивание, например, или перевод денег и загружает в правое окно счетов назначения только те счета, которые пригодные для выполнения такой операции. Еще одна машина состояний контроллирует над разновалютные расчетами. Самая сложная машина состояний этой формы - определяет права юзера на выполнение запрошенной операции.
Рассмотренный тип машин состояний является распределенным - текст переходов между состояними размазан по форме тонким слоем и реализуется в каждом месте всего в несколько строк. При этом используются обычно две техники - либо машина флаговая - скажем в таком случае выставляется четыре флага, которые потом читают исполнительные механизмы формы. Либо же машина бесфлаговая, те при работе исполнительных механизмов формы используются непосредственные выборы пользователей на форме. Во второй технике мне однажды пришлось написать распределенную безфлаговую машину состояний длиной несколько сотен строк кода.
Совершенно иной вариант машины состояний - это централлизованная машина состояний, где исполнительные фрагменты просто обращаются с некому единому механизму, регулирующему состояние. Скажем вот в этом фрагменте единая машина состояний вызывается по NextStep.Invoke.
Но настоящее царство машин состояний - это Web-приложения. Редко в какой Web-страничке код управления состоянием странички составляет меньше 500-1000 строк. В сущности все Web-программирование - это сложнейшая и многоуровневая схема переходов отдельных элементов и приложения в целом из состояния в состояния.
- На самом нижнем уровне - машина состояний, чтобы ассоциировать конкретный HTTP-запрос с текущим состоянием странички, которое заливается на контролы странички между событиями INIT и LOAD, существует наследуемый класс SessionStateStoreProviderBase, который управляется из внешних настроек Web-приложения. Новое и удивительное новшество этого модуля в ASP2 - обходится без Cookie и порождать вот такие URL, в которых собственно и хранится состояние сеанса.
- На среднем уровне - это все отдельные методы хранения состояний, поддерживаемые собственно средой программирования ASP:
на стороне сервера предусмотрены обьекты:- Application
- Session
- Cashe (функциональность которого значительно расширена в ASP2)
- Собственные свойства своих контролов.
- Скрытые поля
- Cookie
- ViewState (В ASP2 можно даже писать свой механизм состояний контролов, который сериализуется во ViewState)
- На самом верхнем уровне - это собственно машина состояний приложения, работающая непосредственно с юзером, и придающая интеллект приложения. Например, юзер понимает, что он должен сначала добавить товар в корзину, а лишь потом его заказывать.
Существуют несколько распространенных техник программирования переходов в машине состояний верхнего уровня в Web-приложениях:
- Cпецконтрол для проектирования машин состояний формы как в VisualInterDev. Утапливание машины состояний в отдельный настраиваемый в дизан-тайме контрол - это очень распространенная техника не только в Web, но и в Win-приложениях. Скажем вот в таком редакторе отношений многие-ко-многим на форме расположены лишь кнопки, а сама функциональность машины состояний утоплена во внутрь контрола, который отслеживает направления связи многие-ко-многим.
- Вот на этой моей страничке существует еще четыре формы машин состояний. Первая - контроллирует последовательность действий юзера над формой. Это распредленная машина состояний с двумя крупными узлами. Один центральный узел находится в Page_Load, где производится множество ветвлений для разных причин начала загрузки этой страницы, другой узел находится Page_LoadComplete, где в необходимых случаях производится переход на формирование страницы заново.
- Вторая машина состояний управляет XML-фильтрами по выборам юзера в комбешниках. Эта машина строится непосредственно в дизайнере, позволяющим непосредственно подключится к обьекту SESSION. Ее текст находится непосредственно в HTML-коде.
- Третья выполняет динамическое XSTL-популирования дерева и запоминает его состояния. Эту машину я построил как централлизованную, но без обьектного интерфейса.
- И наконец, четвертая машина этой формы динамически добавляет контролы на рабочий стол и контроллирует действия юзера над рабочим столом. Она построена чисто по обьектной схеме как типизированная спецколекиция.
Третья и четвертая машины состояний этой формы насчитывают многие сотни строк кода. Поэтому трассировщик смены состояний такой машины - это не роскошь, а просто вынужденная необходимость, без которой такие приложения просто невозможно отладить, а уж внести через год какие-нибудь изменения и не наделать кучу ошибок невозможно совершенно.
Другой пример странички со сложной схемой смены состояний рассмотрен мною здесь. Это пример одноуровневой машины состояний, задача которой - правильно сформировать параметры для обращения к бизнес-обьекту и изменять свой внешний вид в зависимости от состояний. Код такой машины состояний составляет многие сотри строк.
Управляемые машины состояний приложения. В последнее время я пришел к идее настраиваемых машин состояний самого верхнего уровня в приложении. Эту идею я решил реализовать в менеджере MDI-цепочек. Он позволяет открыть в MDI-проложении несколько независимых последовательностей (цепочек) форм одновременно, а внутри каждой цепочки можно по каждому юзера определить модальные/немодальные/пропускаемые формы.
|