InfoCity
InfoCity - виртуальный город компьютерной документации
Реклама на сайте







Размещение сквозной ссылки

 

Оптимизация процесса разработки и проектирования сценариев взаимодействия с Web-компонентами на основе технологии Servlet.


Евгений Игумнов, Developers.com.ua


Проблема
Используем MVC
Вид отделяем от действий
Пример простого сценария
Действия помещаем в Command
В основу берем Dispatcher
Используем Mapper
Применяем Decorator
Собираем Content с помощью Composite
Получаем Content, трансформируя XML
Заключение

Проблема


По моим наблюдениям, основная масса программистов пишут CGI-скрипты, как попало и не заботятся о последствиях. И чаще всего программист начинает писать скрипты, даже точно не зная, что у него в конечном итоге получится. Например, если Вы попросите добавить или изменить имеющуюся web-систему, то программист, скорее всего, будет просто несчастлив, так как ему придется перерывать гору исходников, в которых чёрт ногу сломит. К тому же возникает проблема, когда необходимо распараллелить написание web-сайта между несколькими программистами. К сожалению, я тоже раньше так программировал, но теперь я предпочитаю сначала все спроектировать, а уже потом браться за реализацию или за раздачу работы программистам.

В данной статье я излагаю свой материал и демонстрирую примеры на технологии Servlet, но на самом деле, описанные мной идеи легко можно использовать в Perl или PHP.

Используем MVC


Существует такой популярный шаблон проектирования Model - View - Controller. Идея его заключается в следующем. Существует модель (Model) предметной области приложения, например структура базы данных. Существуют способы отображения (View) этой модели для пользователя, например HTML-странички. Существуют набор действий (Controller), которые производятся с моделью и чаще всего изменяют состояние этой модели, т.е. содержимое БД или генерируют HTML-код. Обычно View реагирует на внешние события, такие как метод Post или Get из Netscape и на каждое такое внешнее воздействие определяет свою команду (Controller). На самом деле MVC немного сложнее, но в нашем случае мы возьмем только выше описанные идеи. Шаблон MVC изображен на рис.1


Рис.1

В нашем случае событие model_was_changed не может произойти, так как события между Netscape и CGI-скриптом идут только в сторону CGI-скрипта, т.е. CGI-скрипт по своему желанию не может в любой момент времени сообщить в Netscape о том, что была изменена модель. Не работающая связь изображена на рис.2.


Рис.2

Вид отделяем от действий


Самая главная ошибка, которую совершают программисты - это совмещение кода, изменяющего базу данных и генерация HTML. Предлагаю это разделить и назвать контроллером взаимодействия с БД и котроллером генерации HTML. Ниже на рис.3 показано это разделение.


Рис.3

Первый овал - это код, который меняет состояние таблиц БД, т.е. Cotroller. Второй генерирует HTML, т.е. опять Controller. Третий овал с черточкой - это представление HTML в Netscape на стороне пользователя, т.е. View. А Model является структурой БД, как говорилось выше.

Пример простого сценария


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


Рис.4

Выше нарисован пример простой гостевой книги. Гостевая книга представляет собой один скрипт. Ему обычно передаются параметры action, commit и rollback. В action указывается контроллер, который необходимо запустить. Если указан параметр commit, то в случае успешного выполнения контроллера в action, следующим запускается контроллер в commit, а если порождается исключение при выполнении контроллера из action, то запускается контроллер, указанный в rollback. Если action не указан, то выполняется контроллер, определенный по умолчанию. Используя такой подход, Вы можете заранее нарисовать весь сценарий взаимодействия пользователя с web и по полученным кружочкам понять, сколько Вам необходимо написать контроллеров для своей задачи.

Действия помещаем в Command


Для того, чтобы было легко раздать работу по написанию Ваших контроллеров нескольким программистам, я предлагаю Вам использовать шаблон проектирования под названием Command. Определяем интерфейс MyCommand и наследуем от него все наши команды (конроллеры). Таким образом, Вы налагаете на всех программистов единый стиль. Шаблон Command изображен на рис.5.


Рис.5

Некоторые программисты пишут один большой Servlet и каждый контроллер определяют просто методом, как делает, например, мой знакомый. У него получается один здоровый файл с кучей методов (каждый метод - это контроллер). А теперь давайте представим, что не хватает времени реализовать все контроллеры и мы ему в помощь даем 3-х программистов и они все вместе начинают редактировать один его большой Servlet. Думаю, ничего хорошего из этого не выйдет. Давно уже пора понять, что проекты делаются группой разработчиков и каждый разработчик должен писать ни как ему лично удобно, а как удобно всей группе программистов.

В основу берем Dispatcher


Желательно иметь один такой класс, который занимается только тем, что управляет сценарием работы нашего web-сайта. Пример работы такого диспетчера изображен на рис.6.


Рис.6

Как видно из рисунка, Servlet передает управление диспетчеру, а тот, в свою очередь, анализирует содержимое переменной action и вызывает соответствующий контроллер и, если после выполнения контроллера из action порождается исключение, то он вызывает контроллер определенный в rollback, а в случае успешного выполнения контроллера из action, диспетчер вызывает контроллер определенный в commit.

Используем Mapper


На самом деле, выше описанный Dispatcher у нас получился не очень хороший. Недостаток на лицо. В случае изменения сценария взаимодействия с Web, необходимо лезть руками в Dispatcher и исправлять код. Я привел такую реализацию Dispatcher'а только для того, чтобы продемонстрировать логику его работы. Кстати, вышеупомянутый знакомый реализует диспетчер именно так.

Существует более изящное решение этой проблемы. Мне его подсказал Антон Патрушев (mcgregor@mail.ru). Необходимо определить текстовой файл, в котором хранятся имена наших контроллеров, который мы указываем в action, commit и rollback. И каждому имени контроллера указать имя класса, который его реализует. А потом воспользоваться java.lang.ClassLoader. ClassLoader позволяет загружать класс по имени и делать с него объект. На самом деле, если немного подумать дальше, то в такой конфигурационный файл можно не только зашить соответствия контроллер - класс, но и описание всего сценария. Так вот, механизм отображение контроллер - класс называется Mapper.

Применяем Decorator


Желательно Servlet'ы писать так, чтобы не повторять один и тот же код, а повторно его использовать, и потом можно будет менять один код в одном месте, а не во многих местах, как чаще всего происходит. Предлагаю применять шаблон Decorator. Диаграмма классов изображена на рис.7.


Рис.7

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

Идея заключается в следующем. Определяем интерфейс View с методом, который рисует наш компонент. От интерфейса наследуем наш компонент и его декораторы. И в конструкторах определяем возможность передачи ссылки на вложенный объект, который надо декорировать, так сказать. Получается следующая картина на рис.8.


Рис.8

Сначала объясню, что делает каждый декоратор. Border - просто рисует обрамление вокруг любого элемента. WindowHead - рисует подобие заголовка как у всех приложений Windows с кнопочками свернуть и закрыть. NewHead - рисует серенькое поле, а в нем пишет название новости. NewBody - рисует саму новость. Другими словами, заходите на web, а там новости оформлены в виде Windows окошек. Некоторые новостные сайты такое практикуют. А теперь вернемся к рис.8. Как видно b1 обрамляет wh1, wh1 содержит b2, b2 обрамляет nh, nh содержит b3, а b3 обрамляет nb. Как работает весь этот механизм изображено на рис.9.


Рис.9

Приведу пример кода:
Border b1= new Border( new WindowsHead( new Border ( new NewsHead ( new Border ( new NewsBody() ) ) ) ));
b1.doPost(...);

Собираем Content с помощью Composite


Шаблон Composite очень похож на Decorator, но он относится к несколько другому аспекту. У декоратора чисто рекурсивная вложенность, а у композиции присутствует как рекурсия, так и очередь. Даже можно сказать, что в компоненты, построенные по шаблону композиции можно добавлять несколько других подобных компонентов. Диаграмма шаблона Composite изображена на рис.10.


Рис.10

В шаблоне Decorator мы через конструктор передавали ссылку на вложенный объект, а здесь мы используем для этого метода AddComponent. Естественно не все компоненты могут добавлять в себя другие компоненты.

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


Рис.11

Как видно у нас есть один компонент (назовем его контейнер) в котором по очереди хранятся другие вложенные компоненты. Механизм работы изображен на рис. 12.


Рис.12

Создаём наш контейнер, а потом помещаем туда нужные элементы и заставляем его нарисовать себя, т.е. сформировать HTML-код.

Получаем Content, трансформируя XML


Иногда необходимо иметь гибкий механизм смены способов представления информации. Для этого необходимо разделить способ представления информации и саму информацию. Для этого удобно использовать XML. Давайте представим, что Ваши Servlet'ы будут формировать не HTML, а XML, который вы жёстко задекларируете. И этот XML будете обрабатываться другим скриптом, который содержит в себе правила преобразования вашего XML в HTML-код. И если Вам захочется поменять внешний вид своего сайта, Вам будет достаточно изменить правила отображения XML в HTML. Вы также сможете написать свой Applet, который будет общаться с сервером, получать от него XML и отображать его другим способом в браузере клиента. Другими словами, Вы формируете один и тот же XML, а он может представляться в HTML и в виде Applet'а. Думаю побочные (положительные) эффекты, которые приносит использование XML не помешают при разработки системы, которая имеет разнородные клиентские приложения.

Заключение


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

Домашняя страничка: http://ejbcorba.euro.ru


Реклама на InfoCity

Яндекс цитирования



Финансы: форекс для тебя








1999-2009 © InfoCity.kiev.ua