Причины и Цели
Начав изучать тему Web-framework'ов для Perl, я столкнулся с проблемой, что среди них нет того, который я считал бы эффективным в плане затрачиваемых ресурсов на разработку, поддержание работоспособности и, самое главное, адаптацию под изменившуюся со временем задачу.
Посмотрев русскую википедию, соединив информацию с английской википедией, плюс результаты из google, я просмотрел около десятка разных фреймворков. Самые распространённые, это Mojolicious и Catalyst, реализуют "классическую" MVC модель. Это современный стандарт в построении Web (и не только) приложений. Моя проблема в том, что в классическом варианте представлению (View) отводится пассивная роль: сгенерировать шаблон по предоставленным для этого данным. Если представлению отвести активную роль и дать возможность получать данные напрямую из модели, то это заметно упрощает код контроллеров, даёт бОльшую гибкость в адаптации представления под меняющуюся задачу. Часто бывает так, что приходится менять внешний вид приложения, но основной код модели и структуры данных при этом можно оставить прежние. Например, добавить на определённых страницах дополнительный блок информации, которая раньше уже существовала на других страницах. Для пассивного представления придётся добавить дополнительный код в контроллер, получающий эти данные, а затем добавить в соответствующие шаблоны обработку этих данных. В активном представлении нет нужды менять контроллеры, можно напрямую из модели взять необходимые данные.
Активное представление позволяет лучше разделить области ответственности. Занимаясь представлением, не приходится заниматься параллельным программированием контроллеров. Программист представления сам определяет какие данные ему необходимы и получает их из модели напрямую. Процесс передачи данных обратно в модель выглядит простой задачей, требующей некоторой формализации. Писать однотипные контроллеры для приёма данных утомляет, ведёт росту кода copy'n'paste, в который могут незаметно вкрадываться ошибки. В качестве выхода предлагается контроллеры не писать, а просто декларировать. Например:
---
params:
auth:
value: cookies.auth
max-size: 40
title:
max-size: 100
filter: [ s/</</g, s/>/>/g ]
content:
max-size: 4000
model: Article::add_article
expected:
- result: OK
id_article:
- result: NEED_LOGIN
answer:
Формат YAML выбран как самый "человечески-читаемый", который не только читать, но и писать человеком можно. Является ли это контроллером? В прямом смысле слова -- нет. По замыслу это больше на WDSL похоже, только реализация понятнее, проще и богаче возможностями.
Секция expected
является информационной для программиста представления, а так же, позволяет тестировать
приложение, проверяя совпадение декларированной структуры ответа с тем, что было возвращено на самом деле.
И так, с контроллеров сняли обязанности по приёму данных, они не нужны для получения данных в представлении, что осталось? Осталась логика интерфейса в плане перехода между страницами по фактам действия пользователя. Это, вобщем, тоже исправимо:
---
params:
login:
min-size: 4
max-size: 40
password:
min-size: 4
max-size: 40
model: Author::login
result:
OK:
redirect:
- TT form.back_url
- /
set-cookie:
auth:
value: TT response.auth
expires: TT response.expires
DEFAULT:
redirect: TT "/appLogin?message=${response.answer}" ~ (form.back_url? "&back_url=${form.back_url}":"")
unset-cookie: auth
expected:
- result: OK
expires:
auth:
- result: PASSWORD
answer:
Установки кук, заголовков ответов, редиректы -- это всё формализуется и так же поддаётся декларированию. В результате, контроллер можно редуцировать до простого формального описания.
Поскольку активному представлению не нужен контроллер для получения данных, то, с одной стороны, он мог бы пригодиться для вызова шаблона, но с другой стороны -- зачем? Программисту представления проще написать шаблон, положить его в папку с шаблонами и сразу получить результат. Таким образом, у каждого шаблона есть автоматически присвоенный ему URL. Механизм "маршрутов" позволяет переопределить внешнее представление URL в любой удобный вид.
Описание интерфейса модели выполняет сразу множество функций.
- Валидация параметров по легко читаемым правилам
- Описание способа вызова метода
- Декларативное описание действий по результатам вызова метода
- Документирование
- Тестирование
Валидация наглядно говорит программисту представления о том, какие данные ожидаются на входе, проще строить размеры полей, типы проверок на лету и подобного.
Декларативное описание действий даёт представление о логике работы интерфейса.
Беглый взгляд на параметры и типы возвращаемого значения позволяет реже обращаться к отдельной документации проекта.
Описание входящих параметров и возвращаемых значений позволяет автоматизировать тестирование по
Property
параметров с проверкой возвращаемой структуры.
Описание способа вызова позволяет указать функцию в локальном модуле или же модель может быть удалённой. Моделей можно иметь несколько. Например, одна модель для клиентов сайта, другая модель для его администрирования, третья для каких-то ещё специальных действий.
- Реализация активного представления. Программист представления сам решает какие данные из модели где и как использовать. Это позволяет чётко разделить обязанности между программистом представления и программистом модели.
- Обязанности контроллера частично автоматизированы, частично решаются декларативно. Необходимость в написании кода контроллера пропадает совсем.
- Моделей может быть несколько. Они могут быть реализованы удалённо.