ACIS::Web: реформа

Частичное описание незаконченых или только запланированных изменений.  Документ не полный и не окончательный.

Реформа охватывает или затрагивает:

Реформа будет сделана в два этапа.  Первый этап: в пределах пространства имён ACIS::Web и будет включать в себя реформу структуры user-data, структуры данных, передаваемых презентеру, и элементы работы с сессиями и аутентификации.  Второй этап: дальнейшая абстракция и перенос кода в Web::Skeleton (черновое название).

Структура user-data

Две основные ветки: owner и records.  owner описывает владельца данных, пользователя ACIS.  records содержит список записей, принадлежащих пользователю.

owner

записи, элементы списка records

Всякая запись представляет собой хэш, и имеет по крайней мере:

Структура, передаваемая презентеру

Основные ветки: system, request, response.  В квадратных скобках - названия соответствующих XSLT переменных.  Они должны быть определены в general/pages.xsl и использоваться всеми экранами вместо абсолютных XPath путей.

system

request [$request]

response [$response]

Методы ACIS::Web

Добавляем несколько методов для удобства обработчиков.  Эти методы позволят обработчикам писать в соответствующие части presenter-data.

XSLT

Кроме того, что все XSLT презентеры должны быть адаптированы к описанным выше изменениям, есть ещё кое-что:

Сессия

структура

Сессия содержит всего три стандартных элемента:

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

Каждому из этих элементов соответствует одноимённый read-accessor-метод (но без точки):

my $sid   = $session->id; 
my $type  = $session->type; 
my $owner = $session->owner; 

cоздание

my $session = $acis -> create_session( $owner, $type );

$owner - здесь это ссылка на хэш, содержащий ключи: name, login, type.

загрузка

my $session = $acis -> load_session();

или

обработчик ACIS::Web::load_session

В случае, если сессию невозможно загрузить, обработчик сделает $acis -> clear_process_queue, и, при необходимости, выставит соответствующий код ошибки: session-failure.

доступ к загруженной сессии

Как и раньше: my $session = $acis -> session();

сохранение

$acis -> save_session();

Аутентификация пользователя

my $userdata = $acis -> authenticate();

или

обработчик ACIS::Web::authenticate

Аутентификация не имеет смысла, если существует и загружена сессия.  Функция имеет соответствующую проверку и вернёт 0 в таком случае.

В случае, если аутентификация невозможна, обработчик сделает clear_process_queue, установит ошибку, запустит презентер экрана login или sorry (в зависимости от конкретной ситуации).

Имена переменных в обработчиках

Все обработчики получают в качестве параметра главный объект (ACIS::Web) и почти все они используют одни и те же его компоненты. Однако при этом они часто используют разные имена переменных для их обозначения.

Все обработчики должны начинаться именно так:


sub обработчик {
   my $app = shift;

   my $session = $app -> session;
   my $vars    = $app -> variables;
   my $record  = $session -> current_record;
   my $config  = $app -> config;

   my $request = $app -> request;
   my $cgi     = $request -> {CGI};

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

Ed.Note: дополнения принимаются

Путь дальше или Этап 2

Места для дальнейшего развития, абстрактизации — навалом. Главное в нём - не потеряться.

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

Почему это важно? Потому что некоторые экраны (и обработчики, и презентеры) имеют смысл только в контексте сессии определённого типа.  Далее: обработка закрытия сессии полностью зависит от её типа.

Можно сессии разных типов реализовывать разными классами. Создание и закрытие сессии тогда превратились бы в методы класса.  Осталось определить интерфейс, и сделать два соответствующих воплощения: ACIS::Web::Session::NewUser, ACIS::Web::Session::User.

Большой смысл есть в том, чтобы основать их на общем классе ACIS::Web::Session, который будучи вполне работоспособным, содержал бы только абстрактную часть работы с сессией.  Его, в принципе, можно было бы использовать в случаях, когда экрану нужна сессия, но не важен её тип. (Хотя пока такой экран я даже придумать не могу.)

Основные методы класса (и интерфейса) ACIS::Web::Session: (черновой черновик)

Тогда экраны нового пользователя (кроме new-user/initial) могли бы иметь в своей конфигурации обработчик ACIS::Web::Session::NewUser::load, а экраны зарегистрированного, соответственно, ACIS::Web::Session::User::load.

Однако, на самом деле тогда функция load() перестаёт быть методом класса, так как вызываться она будет вне объектно-ориентированного контекста (то есть просто как функция с одним параметром).

Поэтому полноценного, автоматического наследования от класса ACIS::Web::Session всё-равно не получается.  Хотя его можно заменить ручными вызывами.

На самом деле эти факторы важны и для user-data: можно предположить, что они тоже могут быть разных типов.  По-крайней мере, если мы хотим разделить общее и ACIS-специфичное, то нужно разделить общее и специфичное в структуре user-data.