Этюды в тональности C#. TV паттерн программирования 1

Этюды в тональности C#. TV паттерн программирования

MVC паттерн программирования
В последнее время в технических публикациях "Майкрософт" замелькала аббревиатура MVC (MODEL-VIEW-CONTROLLER) паттерна программирования. Нынче эта программная идеология считается самой модной при создании дектопных, да и, пожалуй, веб-приложений. Исходно данный подход к программированию появился еще в языке SMALLTALK и позже прижился в JAVA. Похоже, он оказался довольно удачным и сейчас постепенно завоевывает все больше сторонников.
Насколько я понял англоязычную документацию, суть идеи сводится к тому, что в вашей программе должно быть три слабо связанных между собой функциональных блока.
Первый блок, называющийся MODEL, отвечает за поведение приложения (его бизнес-логику). Он содержит в себе сам алгоритм задачи, которую вам необходимо решить, сам основной поток вычислений программы. Так, если в качестве задачи ставится описать функциональность обычного дорожного светофора, в этом блоке будут находиться процедуры, задающие последовательность переключения его цветов.

Кроме того, не стоит забывать и о том факте, что одна большая задача чаще всего подразделяется на несколько других отдельных подзадач. В частности, чтобы включить на светофоре нужный свет, необходимо для начала убедиться в наличии электричества, а затем подать его на конкретную лампочку, не забыв погасить при этом другие, возможно, горящие, лампы. Вся эта функциональность также входит в модель светофора и помещается в этот блок приложения.
Второй блок, называющийся VIEW, отвечает за отображение информации пользователю. Сюда сносятся все функции, ответственные за визуальные формы отображения информации. В нашем примере тут расположены не только сами лампочки светофора, но и даже столб, на котором он висит.
Третий блок называется CONTROLLER и служит для сбора пользовательского ввода, а также информирования блока MODEL о том, что требуется решить ту или иную задачу, а блока VIEW — о том, что некую информацию необходимо отобразить. В нашем примере со светофором в понятие контроллера входят такие вещи, как таймер, задающий период, во время которого горит тот или иной цвет. Помимо автоматического таймера, в систему может входить и ручной блок управления светофором, прикрепленный к отдельному столбу.

Достоинства паттерна MVC
К главным достоинствам этого паттерна относят то, что MODEL (то есть само приложение как таковое) очень слабо связан с блоком VIEW и CONTROLLER. При такой системе ему безразлично, откуда именно получать команды или каким образом их выводить. Вы вольны как угодно крутить интерфейсом или механизмом пользовательского ввода своей программы — ее общее функционирование от этого никак не пострадает. Более того: в больших проектах можно даже поручить разработку кода MODEL, VIEW и CONTROLLER разным группам разработчиков. Им не потребуется вникать в задачи друг друга, для того чтобы решать сообща общую задачу.

Недостатки паттерна MVC
Значительно хуже в MVC-паттерне обстоит дело с парочкой блоков VIEW и CONTROLLER. В силу своей жесткой привязки к блоку MODEL они значительно хуже поддаются абстрагированию. Действительно, пульт от дорожного светофора бессмысленен как без самого светофора, так и без логики его переключения. Равно и сама коробка светофора при отсутствии логики ее переключения пользы не приносит. Разве что сплавить ее с пультом управления в единое целое и поставить рядом гаишника. Пусть сам вручную на кнопки жмет.
Что забавно, при использовании этого паттерна чаще всего так и происходит. Реализация блока MODEL делается отдельно, по всем правилам, а вот блоки CONTROLLER и VIEW программист соединяет вместе. Я это неоднократно наблюдал в чужом коде — как в обычных дектопных приложениях, так и в ASP-, ASP.NET-приложениях, ориентированных на WEB.

Последний вид приложений так прямо напрашивается на подобное объединение самой своей идеологией. По всей видимости, именно поэтому "Майкрософт" и заинтересовалась этим паттерном программирования. Использование кода на стороне сервера (ASP- или ASPX-страницы) и пользовательского интерфейса на стороне клиента (веб-браузер) идеально подходит для ситуации, когда имеется отдельная MODEL и объединенный блок VIEW-CONTROLLER.
Впрочем, и в обычных деcктопных приложениях дело обстоит примерно таким же образом. У вас имеется форма приложения, которая, во-первых, отображает на себе визуальный интерфейс (VIEW), а во вторых, содержит управляющие элементы — скажем, кнопки, которые играют роль блока CONTROLLER. Таким образом, те, кто так использует паттерн MVC в своих приложениях, на самом деле лукавят. Тот паттерн, которым они пользуются, правильнее назвать M(VC)-паттерном, так как фактически в их программах не три независимых блока, как положено, а всего два.

Библиотека BORLAND TURBO VISION как идеальный MVC-паттерн
Чем больше я читал документации по этому вопросу, тем больше прочитанное напоминало мне старую добрую библиотеку TURBO VISION от BORLAND PASCAL 7.0. Ее разработчики, правда, пошли дальше по пути еще большей абстракции и создали среду, в которой любой функциональный блок кода, а не только три предопределенных, понятия не имеет о существовании остальных частей приложения. Весь обмен данными между функциональными блоками осуществлялся с помощью так называемых сообщений. При такой системе вы легко можете полностью отделить MODEL, VIEW и CONTROLLER друг от друга — собственно говоря, они в этой библиотеке и так изначально отделены друг от друга и полностью равноправны.

С полгода назад в онлайн-мастер-классе сайта GOTDOTNET.RU мне дали контрольную работу по C# с требованием выполнить ее в стиле MVC. Ехидно усмехнувшись, я оформил алгоритм на общих принципах механизма сообщений TURBO VISION. Работа была принята и успешно зачтена.
Складывается ощущение, что поговорка про давно забытое старое действительно права. При таких условиях этот мой небольшой практикум может оказаться вам полезным для практического "обкатывания" данной "новой" и набирающей популярность идеологии создания приложений. Также его, вероятно, будет любопытно пройти студентам, жалующимся в форумах на то, что их заставляют изучать морально устаревший TURBO-PASCAL. Они смогут убедиться, что при наличии у человека в голове хороших идей он их легко сможет выразить и на этом "учебном" языке, а общие приемы программирования не меняются уже очень много лет.

Немного истории
Во времена программирования под MSDOS, в далеком 1990 году, фирма BORLAND выпустила довольно любопытный программный продукт, называвшийся TURBO VISION. Мне он впервые попался в руки вместе с дистрибутивом среды разработки TURBO PASCAL 6.0. В те годы наиболее трудоемкой задачей для программиста являлось, как ни странно, создание удобного пользовательского интерфейса. Операционной системы WINDOWS на компьютерах пользователей тогда не было, а вместе с ней отсутствовала и общепринятая концепция того, как именно должны выглядеть элементы управления в компьютерной программе.

Все программы, как правило, писались по следующему алгоритму. Программист разрисовывал на экране пользовательский интерфейс просто как картинку, а затем его программа впадала в бесконечный цикл. В этом цикле она непрерывно опрашивала клавиатуру или мышку. Как только пользователь нажимал кнопку или щелкал мышкой по экрану, программа выясняла, по какому месту экрана он щелкнул или какую клавишу нажал. Затем рассчитывала по известным координатам экрана или коду символа нужный элемент интерфейса. Следующим шагом на экране разрисовывался процесс изменения в этом элементе (например, изображалось нажатие кнопки) и выполнялись действия в основном потоке вычислений, связанные с этим интерфейсным элементом. Реализация подобного алгоритма требовала поистине титанической работы. Крупные софтверные фирмы не могли пустить этот процесс на самотек, и многие из них выпустили свои собственные программные пакеты, призванные оснастить программиста набором кнопочек, выпадающих списков и тому подобных мелочей, легко узнаваемых современным пользователем компьютера.
Пакет интерфейсных примитивов от BORLAND разительно отличался от продукции ее конкурентов тем, что принес с собой не только сами "кнопочки и рюшечки", но и целую концепцию того, как вообще должен выглядеть обмен информацией между пользователем и программой. По версии BORLAND вся обработка событий от пользователя, ну, типа пользователь нажал кнопку на форме или там пользователь выбрал что-то из списка, должна была не немедленно обрабатываться функцией в бесконечном цикле, а по цепочке обходить всю форму приложения, заходя в каждый его интерфейсный элемент. При этом каждый из этих элементов должен был самостоятельно отреагировать на это событие, если таковая обработка в нем предусмотрена, или же игнорировать событие, если его обработка была ему не нужна. В некоторых ситуациях любой управляющий элемент мог "сбросить" при необходимости полученную команду, таким образом прекратив ее ход по приложению. Он также, напротив, в ответ на входной "раздражитель" мог разразиться целой пачкой своих собственных команд. Эти вновь созданные команды попадали в общий канал и заставляли уже другие управляющие элементы как-то реагировать на их появление.

В качестве примера: если пользователь проводил мышкой над кнопкой на форме, информация об этом событии доносилась не только до самой кнопки, которая могла, скажем, изменить свой цвет, но и до всех остальных элементов на форме. Причем, если, скажем, соседней кнопке эта информация была совершенно не нужна, то строка статуса могла отреагировать на нее, выведя подсказку о назначении кнопки. А могла и не отреагировать, если таковая функциональность не была в нее заложена. Не правда ли, очень знакомая по операционной системе WINDOWS программная концепция?
Несмотря на понятные нам сейчас преимущества, библиотека TURBO VISION была довольно прохладно встречена программистами. Создавая ее, фирма BORLAND допустила одну неочевидную ошибку. Она сделала пакет слишком уж всеобъемлющим, мощным, передовым... и поэтому крайне сложным для изучения, да и вообще выглядящим довольно дико и непривычно. Программисты просто не могли понять, зачем им устраивать всю чехарду с событиями, объектами (да-да, я совсем забыл сказать, это был ООП-пакет!), когда им всего-навсего надо нарисовать две кнопки на форме и написать две функции по их обработке. Используя старые методы линейного программирования, они добивались тех же результатов намного проще. Их программный код занимал меньше места и быстрее работал. Поэтому единственное, что оценили программисты тех лет в TURBO VISION, так это единство используемого интерфейса. Через некоторое время внешний вид управляющих элементов "а-ля TURBO VISION" стал стандартом де-факто для приложений, написанных под MSDOS. А вот идеология обработки событий внутри программы так и не прижилась.
Вскоре появилось несколько пакетов от сторонних производителей, имитирующих внешний вид и поведение интерфейса TURBO VISION, но построенных без применения объектно-ориентированного программирования, а также не имеющих вышеописанного механизма взаимодействия с пользователем. Напомню хотя бы TURBO PROFESSIONAL или монстроподобный пакет OBJECT PROFESSIONAL. Последний хоть и использовал ООП, но идеологически был написан в "старом" стиле.

Вышел и быстро набрал популярность WINDOWS 3.1. Злые языки немало ехидничали по поводу того, что "Майкрософт" взяла из TURBO VISION множество идей для своей новой операционной системы. Правда, развили они их несколько по-своему, еще больше запутав исходную идеологию. К следующей версии своего знаменитого компилятора BORLAND PASCAL 7.0 фирма BORLAND приложила и новую версию TURBO VISION, лишь в мелочах отличающуюся от предыдущей, и акцентировала внимание на библиотеке OBJECT VISION, предназначенной для взаимодействия с Windows. Несмотря на то, что ноги у OBJECT VISION росли из той же пресловутой TURBO VISION, механизм взаимодействия с пользователем по большей части отдавался ею на откуп самой среде WINDOWS с ее сообщениями. В дальнейшем BORLAND "завязала" с компиляторами под MSDOS, и началось победное шествие DELPHI с ее событиями ONCLICK и перехватываемыми в коде ваших объектов его обработчиками. Впоследствии этот механизм стал стандартным и перекочевал и в языки VISUAL STUDIO NET. И тут мы, также как в DELPHI, бросаем кнопки на форму и пишем им обработчики.
Сам механизм обмена сообщениями никуда не девался, но он был запрятан вглубь реализации кода библиотек и практически не используется современными программистами. За время своего последующего развития он еще более усложнился и стал еще менее понятен человеку, чем был раньше. Программисты обращаются к нему лишь для реализации всяких нестандартных задач типа создания пресловутой иконки в трее "рядом с часами".

Базовый TV-паттерн
В этой своей статье я предлагаю вам попробовать возродить в своем коде старый добрый TURBO VISION и посмотреть, насколько хорошо эта технология с высоты возможностей, предоставляемых современными языками программирования, ляжет на ваши повседневные задачи. Я лично нашел ее очень удобной и широко использую в своих программных проектах. Причем не только в проектах, написанных на C# или DELPHI, но и в проектах на JAVASCRIPT и VBSCRIPT при создании веб-приложений.
Пусть WINDOWS вместе с C# сами маршрутизируют сообщения, связанные с оконными событиями. Мы с вами реализуем свой собственный параллельный канал, по которому будут "гулять" только те сообщения, которые запрограммировали мы сами. Так как мы сами этот канал придумали и запрограммировали, то и работать нам с ним будет легко, так как никакой дополнительной литературы по его изучению нам не потребуется.
Возможности предлагаемого мной паттерна программирования далеко превосходят функциональность, заложенную в паттерн MVC. Я предлагаю назвать этот паттерн как-нибудь по-другому. В честь первооткрывателей этой модели давайте назовем его TV-паттерн, то есть паттерн TURBO VISION.
Мне бы очень хотелось не попасться в ту же самую ловушку, что и BORLAND в свое время. Будет очень плохо, если вы запутаетесь и откажетесь от использования предлагаемой технологии создания программ. Поэтому я вполне сознательно начну рассказ с более простой модели приложения. Она не в полной степени реализует модель, предложенную в свое время BORLAND, зато значительно более проста в реализации. Освоив ее, вы без труда сможете самостоятельно развить ее под свои потребности. Сам я когда-нибудь поделюсь своими наработками в этой области. Назовем такой паттерн базовым TV-паттерном.

Базовый TV-паттерн. Постановка задачи
Итак, мы с вами собрались создать такую структуру приложения, при которой "левая его нога не знает, что делает правая". Говоря серьезно, все приложение поделено на независимые функциональные блоки. Обмен информацией между этими блоками осуществляется с помощью системы команд, которые передаются по общему для всех блоков каналу сообщений.
На отдельные блоки мы поделим и визуальный интерфейс. То есть единого блока VIEW у нас не будет. Обычное WINDOWS-приложение имеет в своем активе меню, строку статуса, тулбар и рабочее окно формы. Я собираюсь оформить эти элементы в отдельные модули. При этом каждый из них не будет ничего знать о существовании кого-либо еще, кроме себя самого. Тем не менее, меню и тулбар будут выдавать команды, которые будет исполнять рабочее окно формы. Строка статуса станет отображать состояние рабочей области формы и при этом не будет иметь о ней совершенно никакой информации.
Более того: если мы вытащим из нашего приложения какой-либо из этих кирпичиков, работа всего приложения не будет нарушена. Так как остальные функциональные блоки кода понятия не имеют о существовании своих соседей, им совершенно безразлично, есть они вообще в природе или нет. В свою очередь, любой из этих блоков, будучи помещен в другое приложение, будет работать в нем ничуть не хуже, чем в своем родном.
Роль блока MODEL в нашем паттерне будет исполнять главная форма приложения. Только она одна будет знать о существовании остальных функциональных блоков. Этого избежать, увы, никак нельзя, так как именно MODEL задает поведение всей программы, делает ее единым целым, предназначенным для решения некоей поставленной нами задачи. Поэтому волей-неволей она должна быть осведомлена о существовании всех остальных блоков программы.

Продолжение следует


Компьютерная газета. Статья была опубликована в номере 01 за 2004 год в рубрике программирование :: разное

©1997-2024 Компьютерная газета