Some documentation

portnov [2009-07-10 19:19:03]
Some documentation
Filename
README.ru
TODO
diff --git a/README.ru b/README.ru
index 91a18a6..8484bb3 100644
--- a/README.ru
+++ b/README.ru
@@ -14,3 +14,43 @@
  * Подсистема обработки форм (генерация HTML формы по объекту, валидация форм, показ недозаполненной формы)

 Для соединения с БД используется пул соединений, тот же модуль используется для соединений с cache backend.
+
+## Общие замечания об архитектуре
+
+Архитектура фреймворка в общих чертах соответствует MVC. Модели описывают таблицы в БД (но могут иметь дополнительные поля, не хранящиеся в БД). В качестве слоя View выступает система шаблонов TEngine. Контроллеры занимаются выбором нужных данных и передачей этих данных в шаблоны.
+
+Приложение обычно будет импортировать из фреймворка модули Framework.API и Framework.Utils. Модуль API ре-экспортирует интерфейсы некоторых внутренних модулей фреймворка и экспортирует "обёртки" для других модулей.
+
+## Диспетчер URL
+
+Диспетчер URL конфигурируется с помощью типа URLConfig. Значение этого типа составляется с помощью операторов-комбинаторов, экспортируемых модулем Framework.Urls (и ре-экспортируемых модулем Framework.API).
+
+Обработка URL в диспетчере происходит следующим образом. Сначала URL разбивается на части, разделённые косой чертой. Далее диспетчер проходит по конфигурации, пытаясь отождествить текущий фрагмент URL с "кусочком" конфигурации, и если это удаётся - вызывается указанный в конфигурации контроллер.
+
+Например, конфигурация "blog" --> allposts означает, что все URL, начинающиеся с /blog/, будет обрабатывать контроллер allposts. А конфигурация "blog" // "archive" --> archive означает, что URL, начинающиеся с /blog/archive/, обрабатывает контроллер archive. Оператор <|> комбинирует конфигурации по принципу "если не первое, то второе". Например,
+
+urlconf = "blog" // "archive" --> archive
+      <|> "blog" --> allposts
+
+будет работать следующим образом: сначала будет проверено, не начинается ли URL с /blog/archive/; Если начинается, то будет вызван контроллер archive; Если же нет - контроллер allposts. При этом любой контроллер может "отвергнуть" переданный ему URL (см. ниже); Тогда диспетчер будет пробовать сопоставлять url со следующими правилами в конфигурации. Если ни одно правило не подошло (или все подходящие контроллеры отвергли этот url), будет порождена ошибка HTTP 404.
+
+## Контроллеры
+
+Контроллеры приложения (и некоторые другие части) выполняются в монаде Controller. Controller является экземпляром классов Monad, MonadIO и MonadReader. Тип Controller имеет три типа-параметра: тип передаваемой конфигурации (обычно это ActionConfig или StaticConfig) и два возможных типа возвращаемого значения.
+
+Контроллеры (Controller s r a) можно комбинировать (monadic bind) тремя способами. Во-первых, просто выполнение действий одно за другим, как в монаде IO. Такой контроллер возвращает тип a (третий тип-параметр). Во-вторых, контроллер (действие) может завершиться вызовом функции returnNow вместо return, тогда последующие контроллеры (действия) в цепочке не будут вычисляться, а вся цепочка вернёт значение типа r (второй тип-параметр). И в-третьих, в любой момент можно прервать вычисление вызовом действия reject. В контроллере приложения это будет означать "Я не буду обрабатывать этот URL".
+
+Контроллеры приложения возвращают тип Controller ActionConfig HttpResponse HttpResponse, для которого определено сокращение HttpController. Т.е. в качестве конфигурации они принимают ActionConfig (см. ниже) и в любом случае возвращают HttpResponse (сформированный объект-ответ).
+
+Контроллеры-действия, определённые в фреймворке, часто имеют тип AController a, что раскрывается как Controller ActionConfig HttpResponse a. Т.е. они используют ActionConfig в качестве конфигурации, а возвращают либо HttpResponse, либо некий тип a. Например, действие tryReturnFromCache имеет тип AController (), т.е. оно может вернуть либо уже сформированный ответ (при этом последующие действия в цепочке не будут выполняться, контроллер вернёт этот ответ), либо "ничего", т.е. () (и будет продолжено выполнение остальных действий в цепочке).
+
+## Конфигурация
+
+Параметры, которые могут понадобиться контроллеру или другой части приложения, можно разделить на две группы. Параметры первой группы не меняются во время работы приложения. Это, например, путь к статическим файлам, параметры соединения с БД и др. Параметры второй группы свои для каждой обработки HTTP-запроса. Это, например, собственно объект запроса HttpRequest, открытое соединение с БД, канал для лога и др. Параметры первой группы (статические) содержатся в структуре StaticConfig. Бòльшая их часть читается из файла конфигурации. Параметры второй группы содержатся в структуре ActionConfig, равно как и указатель на структуру StaticConfig.
+
+Т.к. Controller является экземпляром MonadReader, то доступ к конфигурации можно получить с помощью стандартных действий ask и asks, например:
+
+controller = do
+    rq <- asks request        -- Получить объект-запрос
+    doSomethingWith rq
+    ...
diff --git a/TODO b/TODO
index 986776d..609f739 100644
--- a/TODO
+++ b/TODO
@@ -6,7 +6,6 @@ TODO
  * Более высокоуровневый интерфейс для кэша - чтоб было легко закэшировать результат всей функции;
  * Соответственно, простые средства для инвалидации кэша;
  * Более продвинутые и высокоуровневые функции генерации SQL;
- * (?) Чтение конфига из файла либо удобный EDSL для конфига;
  * (?) Слой абстракции от диалекта SQL;
  * (?) Генерация структуры Form по Model (с возможностью переопределить, или просто не использовать);
  * (?) Автоматические CRUD-контроллеры;
@@ -14,6 +13,7 @@ TODO
  * (!) Документация ко всей этой красоте.
  * Протестировать поддержку PUT web-сервером;

+ * [DONE] Чтение конфига из файла либо удобный EDSL для конфига;
  * [DONE] Перенести текущий правленный Network.Shed.Httpd в дерево проекта (написать свой?);
  * [DONE] Лучше интегрировать Httpd в движок, в частности - чтоб средствами движка писал логи итп;
  * [DONE] Лучше формализовать формат запроса (reqMethod=="GET" -> reqMethod==GET итп), вероятно, следует привести в соответствие с Network.HTTP;
ViewGit