Как стать автором
Обновить

Комментарии 33

Интересно было бы понять реальный выигрыш в мастабируемости с общепринятым сейчас подходом в стиле шаблона проектирования MVC. Или это другая плоскость?
К примеру механизмы в django очень похожи на конечный автомат :)
Какие именно, если не секрет? :)
Роутинг вызовов.
Роутинг вызовов там обычный; такой даже на прошлой работе в фирменном фреймворке водился. Адрес (route)соединяется с view(который вроде как контроллер), и там обрабатывается. Или я что-то не так понимаю в Django? Поправьте, если это так.

в данном случае все вызовы передаются в единый обработчик, скажем, index, который и занимается переходами между состояниями (вершинами графа переходов).
Адрес (route)соединяется с view(который вроде как контроллер), и там обрабатывается.

Конечно. Но есть первичный обработчик который выбирает какой из view запустить.

в данном случае все вызовы передаются в единый обработчик, скажем, index, который и занимается переходами между состояниями

Вы хотите сказать что отдельных процедур на обработку каждого состояния нет? :]

Может вы путаете понятия? Конечный автомат это алгоритм работы который сводится к конечности и определенности переходов. Django этому критерию удволетворяет (если вы конечно собственно ручно не закольцуете автомат).
Не путаю :) Тут ж речь о том, чтоб формализовать эти переходы.

См. urls.py у django.
Мне кажется, все-таки есть разница. Перейти можно по любому адресу (читай: «состоянию») в urls.py. В finite state machine такого быть не должно, не так ли?
Каждое обращение обрабатывается как конечный автомат. Он тут просто короткий.
Тогда любое вообще приложение, любой фреймворк — кучка небольших КА. В принципе, так и есть, спорить не буду.

Мне интересней, когда конечным автоматом становится все приложение.
Думаю нелишним будет заметить, что описанный код применен для вебинтерфейса однопользовательского приложения. Чтобы адаптировать для использования его в вебе, нужно как минимум:
— Скрестить его с сессиями
— Сделать класс КА и на каждую сессию порождать экземпляр объекта КА.
Если рассуждать в терминах MVC, то можно сказать, что в статье описан один из возможных способов реализации контроллера.
Давайте попытаемся «натянуть» на описанную программу шаблон MVC:
M — model (модель/данные) — ядро оригинальной программы. Данные, это некая структура объектов.
V — view (отображение) — функции, возвращающие код HTML страницы, шаблонизатор, веб-сервер.
C — controller (устройство управления) — в нашем случае КА (FSM), обеспечивающий передачу сигналов от пользователя к модели и логику управления моделью.
Выгода, насколько понимаю, заключается в концентрации всех
обработчиков в одном месте?
Это тоже, но не это главное. Концентрацию обеспечивает уже шаблон MVC. Но MVC не говорит о том как организовать контроллер. Описанный подход это как раз система организации контроллера. Что она дает?
1. Можно применять хорошо разработанный аппарат работы с КА
— Диаграммы
— таблицы
2. Если интерфейс написан с применением описанного механизма, то применяя диаграммы и таблицы при его тестировании, можно быть уверенным, что тестируются все ветки автомата.
3. Еще, если грамотно разбить на функции действия, осуществляемые в переходах, легче повторно использовать эти функции, т.е. комбинировать новые переходы из уже написанных функций.
4. Организация обработчика позволяет вынести все функции на один и тот же уровень вложенности. Что очень заметно облегчает читабельность кода.
Вот написал все это, а потом подумал, может ты это же самое и имел в виду.
1. Нахрен нужны эти префиксы fsm_?
2. Для списка методов есть уже готовая штука под названием «метод» к тому же там больше писанины
3. Для типа списков методов можно использовать декоратов
4. Итого, код можно сделать таким.

Вместо

self.fsm_trans = {
    # 1
    'init_logo':{'type':'Show','methods':[self.fsm_logo_show]},
    # 2
    'logo_logo':{'type':'Show','methods':[self.fsm_logo_show]},
    'pg1_prj_select_page':{'type':'Show','methods':[self.fsm_project_set_dir,
                                                self.fsm_diag_files_rm,
                                                self.fsm_project_page_algor_start,
                                                self.fsm_set_cur_page_algor_first_page,
                                                self.fsm_set_cur_block_first_block_of_page,
                                                self.fsm_create_cur_page_diag_files,
                                                self.fsm_page_show]},


@show
def init_logo(self):
    return self.logo_show()
@show
def logo_logo(self):
    return self.logo_show()
@show
def pg1_prj_select_page(self):
    self.project_set_dir()
    self.diag_files_rm()
    self.project_page_algor_start()
    self.set_cur_page_algor_first_page()
    self.set_cur_block_first_block_of_page()
    self.create_cur_page_diag_files()
    return self.page_show()


1. Просто в классе HomePage у меня не тольк FSM, а я люблю, чтобы было сразу видно, что к чему относится. Так легче навигация по методам. А в общем, конечно дело вкуса.
2. 3. Понятно, что можно по другому, я про это в посте упоминал. Но делает ли это лучше код? По мне, теряются главные идеи.
Для меня, как раз главная идея, уложить код в прозрачную и логичную СИСТЕМУ, которую можно легко нарисовать на бумажке и в которой будет легко ориентироваться.
1. префикс — это неймспейс для бедных. В питроне не хватает неймспейсов?

2. Это делает код лучше потому, что меньше всяких мусорных слов типа 'type' и 'methods' к тому же появляется возможность писать не только последовательность методов.

3. Мне кажется, чем меньше новых сущностей вводится, тем лучше.

Почему 'name':'x', 'type':'show', 'methods':[self.meth] проще нарисовать на бумажке чем
@show
def x():
    self.meth()
1. Вы рассматриваете префикс как замену namespace, я — просто как часть говорящего имени.
2. Для Вас это мусорные слова. Для меня это все говорящие слова, которые делают код продолжением документации.
3. А куда делось 'name':'x'? И это не просто 'name', а ключ, который вычисляется по правилу 'old state' + 'separator' + 'next state'
Вообще, Ваш делает в принципе то же самое, только в моем коде логика КА вынесена в данные, а в Вашем — будет глухо зашита в тело программы. Какой лучше? Смотря для чего. Когда логика зашита в данных, появляется возможность менять логику не меняя код. На мой взгляд это большой плюс.
1. Эта часть означает конкретное понятие, а это понятие может быть выражена в коде напрямую

2. Если уже есть существующее соглажение для обозначение имен и последовательнойстей методов, почему бы его не использовать

3.1 YAGNI
3.2 Ваши данные разве не часть тела пролграммы?
3.3 Клуч нарушает 1НФ :) нельзя ли жти три части выразить явно?
3.4 Можно ли привести программу с переходами состояний?
3.2 Не обязательно. Т.е. в принципе, можно немного переделать мой КА так, что логику можно будет загружать.
3.3 Если не три а две, т.к. разделитель не несет никакой информации, просто для удобства чтения, т.е. фактически ключ это 'previous state'+'next state'. Насчет работы без вычисления суммарного ключа я думал, но у меня получилось, что так самая простая реализация. Имейте в виду, что других ключей, кроме 'previous state'+'next state' не существует. Т.к. множество ключей тождественно множеству состояний.
3.4 Весь код? Нет, не могу, но приведенный код, это часть реального кода.
я не вижу ни одного type:act.

Кстати, не понял, что играет роль входного алфавита для КА.

То есть чем определяется переход — URL запроса должен совпадать с названием действия?

то есть с названием перехода?
Пример запроса:
URL=http://localhost?tostate=state1
Следующий запрос:
URL=http://localhost?tostate=state2
Очень сильно извиняюсь, читать надо так:
Пример запроса:
URL=http://localhost/index?tostate=state1
Следующий запрос:
URL=http://localhost/index?tostate=state2
> я не вижу ни одного type:act.
Добавил
При решении задачи важно применяйте системный подход удобный вам, подходящий к задаче и языку программирования. А что за подход это будет — Конечные автоматы, Объектная модель, алгоритмическая блок-схема или какая-нибудь SADT — не важно. Важно чтобы вы его понимали, решение хорошо вписывалось в его парадигму, ну и язык подходил.
Мораль — учим разные системные подходы.
«Не все йогурты одинаково полезны.» ©

> При решении задачи важно применяйте системный подход удобный вам, подходящий к задаче и языку программирования.
Тут соглашусь.

> что за подход это будет — Конечные автоматы, Объектная модель, алгоритмическая блок-схема или какая-нибудь SADT — не важно.

А вот тут не совсем. Хотя бы опотому, что перечисленные Вами подходы, они несколько разных уровней. Именно нужно, ИМХО, отталкиваясь от специфики задачи и других условий искать максимально эффективную для данной задачи комбинацию методов.
Так и решаемые задачи разных уровней. А если говорим о крупной системе, то весьма вероятно, что базовая декомпозиция будет в одной системе, а декомпозиция самих блоков в другой, в зависимости от специфики блока.
НЛО прилетело и опубликовало эту надпись здесь
Глянул, да, примерно тоже самое. Ну так КА известны давно и везде описаны. По-моему для таких задач это и есть самый естественный подход.
Доавил в статью пример диаграммы.
ну подход не нов, достаточно сходить почерпнуть идей в мир Java EE.
а именно посмотреть на Spring Web Flow или даже JBoss Seam + jBPM. более того с использованием их родных IDE, можно строить графы переходов в визуальном редакторе, которые автоматически нагенерит для них скелеты кода.

но даже более простые MVC-фреймворки используют подобную модель, в которой описывается откуда куда приходим и куда можно попасть. только адепты джанго считают такой подход менее гибким, чем матчить урлы по регэкспам — их тоже можно понять, каждому своё, а точнее нужно исходить из нужд конкретного проекта.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории