Docu/ru/Tut-1.odc

Часть первая: подходы к проектированию
ENGLISH

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

Вторая часть руководства по BlackBox демонстрирует, как использовать самые важные библиотечные компоненты: формы, элементы управления и текстовые компоненты.

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

1 Взаимодействие с пользователем 

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

1.1 Дружелюбность к пользователю

Сегодня в мире используется не менее 100 миллионов персональных компьютеров. При таком большом числе пользователей, которые не являются специалистами по компьютерам, важна легкость использования компьютеров. Это подразумевает, что операционная система и приложения должны быть дружелюбными к пользователю. Что это значит? Здесь есть несколько аспектов.
Во-первых, различные приложения должны быть согласованы друг с другом: функция, которая доступна в различных программах должна иметь сходный пользовательский интерфейс во всех этих программах, так, чтобы пользователю не нужно было учиться делать различными способами одно и то же. Первый способ   опубликовать правила построения пользовательского интерфейса, которых должны придерживаться все разработчики ПО. Такой подход был впервые применен компанией Apple в системе Macintosh. Второй подход  реализовать функцию только один раз, чтобы ее можно многократно использовать в различных приложениях. Это идея компонентного ПО. Разработчики Apple так далеко не пошли, но они по крайнем мере дали много стандартных процедур в довольно богатой инструментальной библиотеке Toolbox, встроенной в Mac OS.

Во-вторых, метафора рабочего стола, где значки графически представляют файлы, каталоги, программы и другие сущности, позволила заменить труднозапоминаемые команды, которые нужно набирать с клавиатуры, более интуитивными прямыми действиями: например, значок с помощью мыши может быть брошен в мусорную корзину вместо набора с клавиатуры команды вроде "erase myfile". Подобный богатый пользовательский интерфейс требует обширной функциональности. Не удивительно, что инструментальная библиотека Toolbox Mac OS включает процедуры поддержки для работы с окнами, меню, мышью, диалоговыми окнами, графикой и др. Toolbox делает возможным построение приложений, которые действительно придерживаются обнародованных правил построения пользовательского интерфейса. К сожалению, программирование в такой среде означает огромный скачок в сложности. В результате Macintosh оказался гораздо проще в использовании, но и гораздо труднее для программирования.
Сегодня метафора проводника  все более популярное добавление к традиционным графическим пользовательским интерфейсам. Вместе с доступом к Интернету она открывает пользователю компьютера целую вселенную документов  и еще больше усложняет работу разработчика.

Наконец, один из наиболее общих и важных аспектов дружелюбности к пользователю - это исключение модальных диалогов [modes]. Модальный пользовательский интерфейс разделяет взаимодействие с пользователем на различные классы и дает свой контекст для каждого класса. Переключение между контекстами громоздко. Например, в программе для работы с базой данных пользователь может открыть окно для ввода данных. В этом окне нельзя удалить записи, осуществить поиск записей, сделать примечания, прочитать электронную почту и т.д. Для каждой из этих задач следует вначале покинуть окружение ввода данных. Это громоздко и напоминает  способ вычислений, ориентированный более на приложение, чем на документ. При работе со сложными программами часто трудно уследить, в каком контексте вы сейчас находитесь, какие команды здесь доступны и куда вы можете пойти далее. 
Рисунок 1-1 иллюстрирует пример состояний и возможные переходы состояний гипотетического модального приложения.



Рисунок 1-1. Возможности навигаации в модальном пользовательском интерфейсе.

Немодальные пользовательские интерфейсы не имеют раздельных рабочих контекстов [working environment] или, по крайней мере, позволяют вам переключаться между контекстами без потери состояний других. Например, если по ходу ввода данных вы захотите взглянуть на что-то с помощью браузера библиотек или утилиты текстового поиска, вы не потеряете часть данных, которую уже ввели. Если нет раздельных рабочих контекстов, то навигация становится простой и очевидной, если система дает информацию пользователю о текущем состоянии контекста и его возможностях. 
Современный графический пользовательский интерфейс  основной пример преимущественно немодального пользовательского интерфейса. Здесь одновременно могут быть открыты несколько окон (контекстов), но хорошо видно, с каким окном вы сейчас взаимодействуете (это обычно "верхнее" окно). Вы можете, работая в одном окне, временно поработать в другом (тем самым сделав его "верхним"), и затем переключится обратно, чтобы продолжить работу в первом окне.

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

BlackBox Component Builder более радикален, чем остальные инструменты, в том, что он просто не поддерживает модальные окна. Все диалоговые окна немодальные, за исключением очень малого числа встроенных в операционную систему, таких как стандартное окно открытия файлов. В общем случае, вы можете всегда оставить диалоговое окно и вернуться к нему позже.

1.2 Циклы обработки событий

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



Рисунок 1-2. Цикл обработки событий для немодальной программы

Цикл опроса событий типичной программы, управляемой событиями, выглядит подобно следующему программному фрагменту:

	PROCEDURE Main;
		VAR event: OS.Event;
	BEGIN
		LOOP
			event := OS.NextEvent();	(* запросить у ОС информацию о следующем событии *)
			IF event IS KeyDownEvent THEN
				HandleKeyDown(event)
			ELSIF event IS MouseDownEvent THEN
				IF MouseInMenu(event) THEN
					HandleMenuEvent(event)
				ELSIF MouseInWindowTitle(event) THEN
					HandleTitleEvent(event)
				ELSIF MouseInWindowBorder(event) THEN
					HandleBorderEvent(event)
				ELSIF MouseInWindowContents(event) THEN
					HandleContentsEvent(event)
				ELSIF...
					...
				END
			ELSIF ...
				...
			END
		END Main;
Листинг 1-3. Цикл обработки событий с каскадным выбором обработчиков событий.

В реальной программе такие каскады условных операторов могут запросто занимать несколько страниц листинга, и они всегда похожи. Таким образом, напрашивается мысль заложить этот код в библиотеку (или, еще лучше, в операционную систему). В такой библиотеке можно было бы реализовывать стандартные правила построения пользовательского интерфейса. Например, процедура HandleTitleEvent различала бы, в каком именно месте заголовка окна произошел щелчок мышкой. В зависимости от точного положения окно будет перемещено на другое место, увеличено, закрыто и т.п. Это  универсальное поведение, которое может и для единообразия должно быть реализовано единожды. Однако процедуры типа HandleContentsEvent имеют иной характер: стандартная библиотека не может знать, что должно произойти, когда пользователь щелкнул внутри окна.
Если мы требуем, чтобы сама библиотека никогда не нуждалась в адаптации к конкретному приложению, то получается система со специфической структурой, в которой библиотека иногда вызывает процедуры приложения. Такой вызов называется обратным [call-back]. Если мы изобразим приложение находящимся над библиотекой, то станет очевидным, почему такие вызовы также называются отложенными вызовами  [up-call], а полученный стиль программирования  "перевернутым" программированием [inverted programming].



Рисунок 1-4. Образец проектирования "перевернутого" программирования.

Библиотека, которая систематически основана на "перевернутом" программировании, называется каркасом [framework]. Это полузаконченный продукт, который должен достраиваться с помощью динамического подключения процедур. Для некоторых процедур это может быть необязательным: процедура HandleTitleEvent может иметь реализацию по умолчанию, в которой реализованы стандартные правила построения пользовательского интерфейса. Такие процедуры могут быть заменены, только если возникнет нужда в нестандартном поведении.

Опыт показывает, что процедура, подключенная к каркасу, многократно обращается к одим и тем же данным. Например, процедура HandleTitleEvent будет часто обращаться к окну, в котором пользователь щелкнул мышкой. Поэтому удобно "упаковать" процедуру и соответствующие данные (ее состояние) в капсулу. Такая капсула называется объектом, и тем самым "перевернутое" программирование развивается до объектно-ориентированного программирования.

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

BlackBox Component Builder скрывает цикл обработки событий от программистов прикладных программ. Он даже идет дальше каркасов-предшественников в том, что скрывает и платформо-зависимые черты, такие как окна и меню. Этого удалось добиться, сосредоточившись на абстракциях, которые представляют содержимое окна: так называемый тип View. Мы расскажем об этом более подробно в Главе 2.

1.3 Многопользовательский доступ

Благодаря персональным компьютерам пользователи стали независимы от централизованных отделов ИТ (информационных технологий), их бюрократизма и перегруженных серверов, работающих в режиме разделения времени. Эта независимость  хорошая вещь, если она может быть соединена с интеграцией там, где это полезно и выгодно. Локальные сети, глобальные сети и затем Интернет сделали интеграцию возможной. Когда два компьютера взаимодействует через сеть, один из них запрашивает другой о предоставлении некоего сервиса, например, о передаче файла через сеть. Компьютер, который выдает запросы, называют клиентом, другой  сервером. Одна и та же машина может функционировать и как клиент, и как сервер, но эти роли часто фиксированы: клерк в филиале банка всегда использует компьютер-клиент, а большая стойка в кондиционируемом хранилище штаб-квартиры банка всегда функционирует как сервер. Внутренняя сеть банка может соединять тысячи клиентов и дюжины серверов. Но даже самая маленькая сеть, очевидно, требует разделения приложений на две части: клиентскую и серверную. Поэтому такой тип архитектуры называют клиент/серверными вычислениями. Он позволяет распределить разные задачи между наиболее подходящими машинами. На уровне предприятия наиболее популярное разпределение ролей  возложить обязанности обслуживания централизованной базы данных на сервер базы данных, а оставшуюся функциональность  на машины-клиенты. Это называется двухуровневой архитектурой. Она требует толстых клиентов, т.е. машины-клиенты должны выполнять все, кроме собственно доступа к базе данных. Чтобы уменьшить эту нагрузку, наиболее развитые системы управления базами данных позволяют выполнять некоторый код на самом сервере как интерпретируемые хранимые процедуры. Это может существенно увеличить производительность за счет уменьшения объема данных, пересылаемых по сети в обоих направлениях. 
Если количество клиентов большое, то становится трудно вовремя обновлять и поддерживать согласованность программного обеспечения на всех машинах-клиентах. Данная проблема может быть уменьшена с помощью трехуровневой архитектуры, где между клиентами и серверами находятся специальные серверы приложений. Функции "тонких" клиентов сокращены до реализации пользовательских интерфейсов, серверы баз данных управляют базами данных, а серверы приложений реализуют все знание о конкретных приложениях ("бизнес-логика").



Рисунок 1-5. Проектная схема трехуровневой клиент/серверной архитектуры.

Трехуровневая архитектура неплохо управляема и масштабируема по размеру. Заметим, что программная система, разделенная таким путем, может быть в крайнем случае "ужата" за счет размещения клиента, сервера приложений и сервера баз данных на одной машине. Обратное неверно: монолитную программу нелегко разделить в соответствии с архитектурой клиент/сервер.
Клиенты и серверы соединены через сеть. Связь осуществляется либо на низком уровне абстракции нетипизированных потоков байтов (например, используя интерфейс сокетов для TCP/IP коммуникации), либо на высоком уровне абстракции типизированных данных. В последнем случае используются либо распределенные объекты (для непосредственной коммуникации точка-точка), либо объекты сообщений (для групповой или отложенной коммуникации).

Подсистема Comm компонентного каркаса BlackBox предоставляет простую абстракцию коммуникации через поток байтов, на основе которой могут быть построены службы сообщений. Между прочим, это может быть использовано для реализации удаленных элементов управления, т.е. таких, которые отображают и манипулируют данными на удаленной машине. Например, таким способом можно проверять внутреннее состояние встроенной системы.
Подсистема Sql BlackBox Component Framework обеспечивает простой интерфейс распределенных объектов, специализированный для доступа к реляционным базам данных (SQL-серверам). Более общие распределенные объекты, основанные на технологии DCOM [COM], могут быть доступны и реализованы при помощи компилятора Direct-To-COM для языка Компонентный Паскаль.


1.4 Настройки на разные языки пользователей

Глобальная природа современного бизнеса програмного обеспечения часто требует выпуска "локализованных" версий программного пакета. Это требует, как минимум, перевода в программе всех строковых констант, которые может увидеть пользователь. Например, в такой стране как Швейцария с ее четырьмя официальными языками,часто требуется, чтобы у одного и того же программного продукта были версии на немецком, французском и итальянском языках. Может даже потребоваться адаптировать к разным языкам формат диалоговых окон, т.к. заголовки и ярлыки элементов управления имеют разную длину в различных языках.
Если такие зависимые от языка аспекты жестко закодированы в исходном тексте программы, то локализация версии требуют редактирования и компиляции исходного кода. Это всегда деликатный вопрос, т.к. легко могут быть внесены ошибки и несогласованности. Кроме того, это очень неудобно:    из-за отсутствия наглядности трудно менять неинтуитивно "впаянный" непосредственно в исходный текст программы формат диалоговых окон, и слишком громоздко выполнять полный цикл редактирования, компиляции и запуска, если нужно всего лишь изменить расположение или размер элемента управления. Разработано много утилит, которые предлагают более удобные специализированные редакторы, в частности, редакторы диалоговых окон. Например, такая утилита может генерировать программный код из интерактивно построенного диалогового окна, и этот код затем компилируется. Так как программист должен редактировать сгенерированный исходный код, легко внести рассогласованность между расположением элементов управления и программным текстом.
К счастью, существует намного лучший способ решить эту проблему, избежав промежуточного генератора исходного кода и использования выдачи редактора непосредственно в программе. Редактор сохраняет информацию о формате диалогового окна в так называемом файле ресурсов. Программа затем считывает такие ресурсы в нужный момент, например, при открытии диалогового окна. Такие ресурсы могут рассматриваться как сохраняемые объекты, которые достаточно модифицировать только при изменении конфигурации программной системы.

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

Black Box Component Framework использует свой стандартный формат документов для хранения ресурсов. Например, диалоговое окно и его элементы управления  просто части некоего составного документа, хранимого в файле. То же визуальное представление используется для проектирования диалогового окна и при его фактическом использовании  при этом нет необходимости в отдельном редакторе. Ресурсы могут быть доступны в версиях для нескольких языков одновременно, и языки могут даже переключаться во время исполнения. Это полезно для специализированных программных приложений, используемых в регионах, где разговаривают на нескольких языках.