Оптимізація процесу розробки і проектування сценаріїв взаємодії з Web-компонентами на основі технології Servlet.Также застосовно для Perl, PHP, ASP та ін, CGI, Інтернет-технології, статті

Євген Ігумнов (Геокад Плюс (Новосибірськ))
www.citforum.ru

Зміст

Проблема

За моїми спостереженнями, основна маса програмістів пишуть CGI-скрипти як попало, і ефективність такої системи їх зовсім не турбує – "аби працювало". І найчастіше програміст починає писати сценарії, навіть точно не знаючи, що у нього в кінцевому підсумку вийде. Наприклад, якщо ви попросите додати або змінити наявну web-систему, то програміст, швидше за все, буде просто нещасливий, тому що йому доведеться переривати гору вихідного, в яких "чорт ногу зломить". До того ж виникає проблема при розпаралелювання роботи зі створення сайту між кількома програмістами. На жаль, раніше і я був серед таких горе-програмістів, але тепер волію спочатку все спроектувати, а вже потім братися за реалізацію (як поодинці, так і командою).

У даній статті я викладаю свій досвід і демонструю приклади на технології Servlet, але описані тут ідеї легко можна використовувати в Perl або PHP.

Використовуємо MVC

Існує популярний шаблон проектування Model – View – Controller. Ідея його полягає в наступному. Існує модель (Model) предметної області додатки, наприклад структура бази даних. Існують способи відображення (View) цієї моделі для користувача, наприклад HTML-сторінки. Існує набір дій (Controller), які виробляються з моделлю (наприклад, зміна стану моделі, тобто вмісту БД, або генерація HTML-коду). Зазвичай View реагує на зовнішні події, такі як метод Post або Get з браузера користувача, і на кожне таке зовнішній вплив визначає свою команду (Controller). Насправді MVC трохи складніше, але в нашому випадку ми візьмемо тільки вище описані ідеї. Шаблон MVC зображений на рис.1

Рис.1

У нашому випадку подія model_was_changed не може відбутися, тому що події між броузером і CGI-скриптом (Controller) йдуть тільки у бік CGI-скрипта, тобто CGI-скрипт не може в будь-який момент часу повідомити користувача про те, що була змінена модель. Не працююча зв'язок зображена на рис.2.

Рис.2

Вид відокремлюємо від дій

Найбільш суттєва помилка, яку здійснюють програмісти – це поєднання коду, що змінює базу даних та генерація HTML. Пропоную це розділити і назвати відповідні програмні модулі контролером взаємодії з БД і контролером генерації HTML. Нижче показано цей поділ.

Рис.3

Перший овал – це код, який змінює стан таблиць БД, тобто Controller. Другий генерує HTML, тобто знову Controller. Третій овал з рискою – це подання HTML в браузері на стороні користувача, тобто 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 і викликає відповідний контролер. Якщо після виконання контролера породжується виняток, то він викликає контролер, визначений у rollback, а в разі успішного виконання контролера з action диспетчер викликає контролер, визначений у commit.

Використовуємо Mapper

Насправді, вище описаний диспетчер у нас вийшов не дуже хороший. Недолік на обличчя. У разі зміни сценарію взаємодії з Web, необхідно лізти руками в Dispatcher і виправляти код. Я навів таку реалізацію Dispatcher'а тільки для того, щоб продемонструвати логіку його роботи. До речі, вищезгаданий знайомий реалізує диспетчер саме так.

Існує більш витончене рішення цієї проблеми. Мені його підказав Антон Патрушев (mcgregor@mail.ru). Необхідно визначити текстовий файл, в якому зберігаються імена наших контролерів, які ми вказуємо в action, commit і rollback. І кожному імені контролера вказати ім'я класу, який його реалізує. А потім скористатися java.lang.ClassLoader. ClassLoader дозволяє завантажувати клас по імені і робити з нього об'єкт. Якщо думати далі, то в такій конфігураційний файл можна не тільки зашити відповідності контролер – клас, а й опис всього сценарію. Так от, механізм відображення контролер – клас називається Mapper.

Застосовуємо Decorator

Програми бажано писати так, щоб не повторювати один і той самий код, а повторно його використовувати. І потім можна буде змінювати код в одному місці, а не в багатьох, як найчастіше відбувається. Пропоную застосовувати шаблон Decorator. Діаграма класів зображена на рис.7.

Рис.7

Ідея полягає в тому, що у вас є якийсь візуалізується елемент і ви хочете його доповнити деяким набором розширень. Причому в різних ситуаціях ви плануєте навішувати різні "фенечки". Зазвичай наводять приклад кнопочки, потім до неї додають перекреслює лінію, а потім блимання. І в разі потреби миготіння або лінію можна прибрати.

Ідея полягає в наступному. Визначаємо інтерфейс View з методом, який малює наш компонент. Від інтерфейсу успадковуємо наш компонент і його декоратори. І в конструкторах визначаємо можливість передачі посилання на вкладений об'єкт, який треба декорувати, так сказати. Виходить наступна картина на рис.8.

Рис.8

Спочатку поясню, що робить кожен декоратор. Border – просто малює обрамлення навколо будь-якого елементу. WindowHead – малює подобу заголовка як у всіх додатків Windows з кнопочками згорнути й закрити. NewsHead – малює сіреньке поле, а в нього пише назву новини. NewsBody – малює саму новину. Іншими словами, заходите на сайт, а там новини оформлені у вигляді 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, можна сказати, що Decorator є окремим випадком Composite. У декоратора чиста рекурсивна вкладеність, а у композиції присутня як рекурсія, так і черга. Навіть можна сказати, що в компоненти, побудовані за шаблоном композиції можна додавати декілька інших подібних компонентів. Діаграма шаблону Composite зображена на рис.10.

Рис.10

У шаблоні Decorator ми за допомогою конструктора передавали посилання на вкладений об'єкт, а тут ми використовуємо для цього методу AddComponent. Природно, не всі компоненти можуть додавати в себе інші компоненти.

Припустимо, що у нас є набір сторінок зі стандартним комплектом: банер зверху, нижче заголовок, ліворуч меню з кнопочками навігації, знизу службова інформація з датою останньої зміни сторінки. У вигляді об'єктів це можна представити так.

Рис.11

Як видно, у нас є один компонент (назвемо його контейнер), в якому по черзі зберігаються інші вкладені компоненти. Механізм роботи зображений на рис. 12.

Рис.12

Створюємо наш контейнер, потім поміщаємо туди потрібні елементи і змушуємо його намалювати себе, тобто сформувати HTML-код.

Отримуємо Content, трансформуючи XML

Іноді необхідно мати гнучкий механізм зміни способів подання інформації. Для цього необхідно розділити спосіб представлення інформації і саму інформацію. Для цього зручно використовувати XML. Давайте уявімо, що Ваші сервлети будуть формувати не HTML, а XML, який ви жорстко декларуєте. І цей XML будете оброблятися іншим скриптом, який містить в собі правила перетворення вашого XML в HTML-код. І якщо Вам захочеться поміняти зовнішній вигляд свого сайту, Вам буде достатньо змінити правила відображення XML в HTML. Ви також зможете написати свій аплет, який буде спілкуватися з сервером, отримувати від нього XML і відображати його іншим способом в браузері клієнта. Іншими словами, Ви формуєте той самий XML, а він може представлятися в HTML і у вигляді аплету. Позитивні додаткові ефекти, які приносить використання XML, не помешаютсістеме, яка має різнорідні клієнтські програми.

Висновок

Я постарався поділитися з Вами своїм досвідом і не претендую на те, що ідеї, викладені вище, є самими-самими, але думаю, що знання, яке Ви отримали при прочитанні моєї статті змусять Вас обміркувати свої погляди на процес розробки і проектування сценаріїв взаємодії з Web-компонентами.

Copyright (C) 2001 Eugene Igumnov. Всі права захищені.

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

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*