Sunday, October 26, 2008

Порталы: От приложений к сервисам


Давайте продолжим не так давно начатый цикл статей про разработку порталов. В первой статье я обозначил ряд вопросов, ответы на которые помогут взять верное направление с самого начала. К сожалению, я сам себе эти вопросы задал примерно через полтора месяца после начала разработки. В итоге мы месяц потратили на переписывание проекта под новую архитектуру.



В этой заметке я расскажу, какие ответы я нашел на заданные вопросы. В связи с тем, что мы ведем разработку на Ruby on Rails, многие методики ориентируются в первую очередь на эту платформу. Однако, я уверен, что на других платформах тоже возможно решить задачу тем же путем. Итак, давайте смотреть:



Вопрос №1: Из каких частей состоит проект?



Так как я занимаюсь разработкой системы управления, не привязанной к какому-то конкретному проекту, то в моем случае разумно делить проект на функциональные составляющие. Четко можно выделить следующие ключевые модули:




Паспорт - управление регистрацией и авторизацией пользователей, редактирование персональной информации, используемой во всех частях системы, просмотр профилей, управление правами доступа;
Публикации - размещение текстовых материалов, видео- и графических материалов администраторами и штатными журналистами сайта
Комментарии - обсуждение тех или иных материалов, размещенных в различных модулях системы
Рейтинги - выставление оценок материалам, размещенным в различных модулях
Изображения - управление загрузкой графических материалов и их привязка к материалам из других модулей, упорядочивание и редактирование изображений


Я не буду утомлять вас перечислением всех модулей, ключевых достаточно чтобы уловить суть. Если вам интересен полный список (и интерес не праздный) - милости просим в контакты. :)



Вопрос №2: Каким образом разделены части проекта?



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



Варианта в конечном итоге образовалось два - делать сервисы в виде “приложения в приложении” (с помощью Engines или Desert) либо каждый сервис выносить в виде отдельного приложения. Первый вариант меня не устроил тем, что и Engines, и Desert не являются официально поддерживаемым решением для разделения приложения на части (как, например, с этим обстоит в Django). На практике это означает что с выходом изменений в рельсах придется какое-то время ждать пока разработчики плагина адаптируют его к внесенным изменениям. Например, для Engines время ожидания доходило до нескольких недель после официального выхода новой версии.



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



Вопрос №3: Какой функционал является общим и как он используется?



Наверное, самый сложный вопрос. Путем проб и ошибок я пришел к выводу, что общим для всех сервисов является следующее:




Конфигурация - позволяет сервисам знать друг о друге (адреса, порты, пароли), хранение общих настроек
Методика авторизации - схема получения информации о текущем авторизованном пользователе, ограничение доступа к закрытым разделам
Общие классы - например, ресурсы, которые используются сервисами для работы друг с другом
Расширения - модули acts_as_*, подключаемые в модели и контроллеры
Хелперы - общий набор, используемый во всех сервисах; например, хелперы для вывода информации о пользователе, блока комментариев и прочие.


В первоначальном варианте общий функционал был оформлен в виде плагина, который подключался как submodule встроенными средствами git. Однако, такая практика дает побочный эффект: при внесении изменений в плагин приходится руками обновлять его во всех сервисах. Это нудно и периодически возникает расхождение версий плагина и сервиса. с которым идет работа.



Чтобы избавиться от этого бестолкового геморроя, я решил оформить функционал в формате gem’а, который подключается на ранних стадиях загрузки rails-приложения (до вызова boot.rb). Сразу посли подключения гема становится доступна конфигурация - набор констант, разбитых по модулям. Эти константы используются при инициализации приложения, например, при задании ключа для хранения сессий и прочих рельсовых настроек. А после того, как приложение инициализированно, вызывается метод, который подключает хелперы, методы для контроллеров и моделей.



Gem хорош тем, что он ставится на сервер и становится доступен всем сервисам, работающим на этом сервере. Плюс появляется возможность задавать требования к версии.



Задайте себе эти вопросы, и очень может быть, что вы найдете способ более правильно организовать ваши приложения.





No comments: