True Unix GUI
В последнее время много шума раздается вокруг идеи о вступлении
Linux (и вообще Unix-подобных систем) в войну за место на рынке
настольных систем. В качестве разведки боем в этой войне возникли и
развиваются такие системы, как KDE и GNOME. Но, по моему мнению, эти
системы обречены на провал. Я не считаю, что Linux не место на десктопе
пользователя. Просто атаковать позиции Windows надо с другого фланга.
Что такое KDE и GNOME - это всего лишь попытка построить над ядром
Unix и X-Window систему, основанную на тех же принципах, что и Windows -
документ-ориентированная модель, взаимодействие между приложениями на
базе drag'n'drop и Object Request Broker, куча бесполезного
украшательства. Фактически для такой системы все преимущества
нижележащей многозадачной, многопользовательской, прозрачно
интегрированной в сеть системы становятся недостатками, приводящими
только к ненужному расходу ресурсов. Ресурсов сейчас, как правило
избыток, но это же не повод транжирить их без пользы.
В результате, мы получаем монстра, в котором работа с удаленными
ресурсами ограничена лазаньем по Web, возможностей расширения - не
больше чем в Windows. Хорошо хоть компилятор бесплатный, но ведь и в
Windows его уже портанули, а так для написания минимальной примочки к
нужно писать на C, или в случае KDE на C++.
Пользователь этой системы опять отдается на милость программистам - он
может пользоваться только тем что для него написали, поскольку изучать C
и, тем более писать на нем, у него нет времени. У него свои,
пользовательские, задачи - отчетик красивый сваять, посчитать
что-нибудь.
Заметим, что и программисты в наше время, во всяком случае то
подавляющее большинство их, которое обслуживает задачи
бизнес-пользователей, пользуется для разработки всяческими системами
Rapid Application Development, то есть по отношению к самому Desktop
Environment выступают скорее как пользователи, чем как программисты.
В то же время ни KDE ни GNOME не начинались с идеи - давайте напишем
RAD-среду, в которой можно сделать все. Что, кстати, сильно ограничивает
и количество их разработчиков, и продуктивность каждого из них.
Разработчики NextStep лучше продумали свою политику в этом отношении, но
и они потерпели неудачу в войне как за десктопы пользователей, так и за
умы программистов.
Сравним это с ситуацией в начале 70-х годов - эпохи победного шествия
Unix по университетам США. Почему эта система смогла тогда вытеснить
гораздо более "дружественные к пользователю" LISP-машины?
На мой взгляд потому, что она последовательно проводила одну
незамысловатую идею - "не хочешь общаться с программой сам - заставь это
делать другую программу". Я уверен, что на этом месте каждый из
читателей вспомнил что-то типа ls -l|grep root или
find . -name "*.bak"|xargs rm. Да, речь именно об этих конструкциях.
Основное их достоинство заключается в том что они, во-первых, вполне
доступны пользователю, умеющему работать в командной строке, а во-вторых
являются полноценными программами на языке shell. Их можно записать в
файл, объявить этот файл исполняемым и пользоваться наряду с прочими
командами системы.
Если вспомнить, что отчеты в те времена писали на troff, который весьма
подходит для обработки sed-ом и awk, то окажется что
пользователи вполне могли легко адаптировать систему к своим нуждам.
Причем этот процесс скорее напоминал обучение - сделал что-то один раз,
дал этой операции имя, и дальше требуешь сделать операцию с таким-то
названием.
Результатом этого явилось практически полное отсутствие барьера между
использованием системы и программированием в ней. И дальнейшее развитие
в общем-то не привело к его увеличению. В ответ на X-Window появился Tk,
в ответ на интерактивные программы типа ftp - expect.
Другое дело что практически неизменным остался барьер между человеком,
видящим компьютер в первый раз и квалифицированным пользователем, в
снятии которого преуспели другие системы, в особенности MacOS.
Памятником тому славному времени служит O'Reilly-вкая книжка "sed &
awk", которая фактически является летописью верстки серии про X window.
Каковы же составляющие интерфейса командной строки Unix, которые
оказались в свое время настолько удачные, что живут уже 30 лет, и до сих
пор находится немало людей, предпочитающих их разнообразным GUI?
На мой взгляд их четыре:
1. Универсальная форма представления информации - текстовый файл,
понимаемый как последовательность символов, некоторые из которых имеют
специальный смысл - разделяют строки(записи), поля и слова.
Его командно-строчные программы выдают на экран человеку (stdout),
его же ожидают в качестве ввода (stdin). Не будь этого стандарта
бесполезен был бы следующий пункт
2. Переназначение ввода-вывода. Этот инструмент в Unix знают по-моему
все.
3. Toolbox Phylosophy. Это свойство тоже широко известно. Во-всяком
случае именно на нем заостряет внимание Ричард Столлман в
info-документации на textutuls. Идея состоит в наличии многих маленьких
утилит, которые хорошо интегрируются, вместо огромного монстра, который
умеет все. Это единственный урок Unix, который усвоили разработчики
GNOME и KDE.
4. Регулярные выражения. Это тоже пункт, о котором многие забывают,
но без них идея "заставить одну программу читать вывод другой" была бы
бессмысленной. Это формальный, достаточно гибкий и более-менее
интуитивный способ указать программе, что следует искать в потоке
данных. И стандартные средства текстовой обработки, и такие
инструменты как expect, появившиеся в ответ на появление программ,
отказывавшихся честно взаимодействовать со стандартными фильтрами,
опираются именно на этот механизм.
Очевидно, что модель обработки данных, основанная на этих четырех китах,
не покрывает потребностей современного пользователя.
Наиболее слабым местом оказывается текстовый файл как универсальный
способ представления информации в сочетании с регулярными выражениями
для его обработки. Во-первых, кроме текста есть картинки и звук.
Во-вторых,
оперировать с текстом на уровне символов не всегда удобно - хочется
опереировать на уровне предложений, абзацев, а то и глав. В-третьих,
существуют табличные данные, которые не всегда удобно обрабатывать в awk
- иногда нужен sql. В четвертых, есть элементы оформления - шрифты,
начертания и пр., которые иногда несут существенную тематическую
нагрузку. (Здесь мы вступаем на театр военных действий между
сторонниками логической и физической разметки, к борьбе между которыми
мы еще вернемся).
Другим слабым местом являются регулярные выражения, как встроенный в
систему способ распознавания образов. Они во-первых, сложны для
пользователя - недаром AltaVista ими не пользуется, во-вторых очень
ограничены по своим возможнотсям - переставьте местами два слова и все.
Есть ограничения и у концепции переназначения ввода-вывода. Она
принципиально линейна, хотя пространство на экране принципиально
двумерно. Мне очень часто хочется написать что-то вроде
gzcat /var/log/httpd/access.log.gz | tee v | grep одно
|
+-> grep другое
В командной строке так нельзя. Хотя со стороны ядра Unix принципиальных
возражений нет. Другое дело что пытаясь записать это с каким угодно
синтаксисом на втором-третьем уровне вложенности обязательно
запутаешься. А если не писать, а рисовать на экране мышкой стрелочки?
Тогда можно охватить взглядом довольно сложную схему потоков данных. С
ветвелениями, слияниями и много чем еще.
Отвлекаясь немного от темы: А не кажется ли вам, что время
графических интерфейсов как таковых заканчивается? Грядет время
интерфейсов голосовых, которые, как ни странно куда ближе к командной
строке Unix, чем к графическому интерфейсу Windows. Ведь речь линейна, и
буде надлежащим образом распознана, превращается в тот самый поток
текстовой информации, который так любят традиционные утилиты Unix.
Что же касается синтеза речи, то эта задача просто уже решена - берете
festival и переназначаете вывод на него. Потребуется, правда немного
изменить синтаксис shell'а и, особенно, регулярных выражений, чтобы
команды было удобно произносить, а выдачу - воспринимать на слух.
Но голосовой ввод - пока еще туманное будущее. Ближайшие года два-три
нам предстоит жить с мышкой, окошками и иконками, которым кстати,
примерно столько же лет, что и Unix.
Итак, каким же должен быть истинно юниксячий графический интерфейс?
1. Должен существовать единый способ представления информации.
Это позволит направлять выдачу любой программы на вход другой.
2. Должно существовать средство поиска шаблонов в этом потоке
информации, причем такое, чтобы видя нечто на экране, пользователь легко
мог сформулировать задачу "найди мне все, похожее на это"
3. Не должно существовать монстров типа Microsoft Word или Netscape
Communicator.
Должна быть маленькая утилитка для показа форматированного текста,
другая маленькая утилитка для показа таблиц (которой будет заодно
пользоваться и средство доступа к sql-базе), отдельная утилитка для
доступа к удаленным ресурсам, больше похожая на wget,
4. Должен существовать нелинейный способ интегрирования этих утилит,
такой, что с одной стороны, пользователь способен с ним справиться
сам, с другой - он позволяет сцепить wget
с показывалкой текста и получить эквивалент Netscape. Этот способ
должен иметь интуитивно яслное интерфейсное выражение.
Естественно, что реальная среда, построенная на этих принципах, не будет
состоять из одних голых кирпичиков. В дистрибутив должно входить
несколько сотен скриптов, которые будут создавать у пользователя
впечатление, что у него есть и Netscape и Word и Excel. Но если ему
вдруг захочется оторвать считалку формул от электронной таблицы и
воткнуть ее (вместе с sql-интерфейсом) внутрь текстового документа, это
должно делаться даже не написанием пяти строк, а несколькими движениями
мыши. Интересная метафора на эту тему была реализована в свое время во
FrameWork - у каждого окна была лицевая сторона (примерно то, что
окажется на принтере) и изнанка (макрос который это генерирует).
Интересно, что последовательная реализация этой концепции может привести
к существенному уменьшению размеров дистрибутива. Вы никогда не
задумывались сколько разных http-клиентов входит в типичный дистрибутив
Linux? Сходу: Netscape, Lynx, wget, http-пакет для Tcl, libwww-perl.
А ведь хватило бы одного, но хорошего. И так для всего остального.
Предвижу возражения, что описанная система - рай для программиста, но не
для пользователя. Пользователю не нужны reusable components - ему
подавай готовые приложения. Да, но... Если система представляет собой
одно большое средство для быстрой разработки приложений, то за
последними дело не станет - найдется немало (гораздо больше чем
участников "базара" сейчас) людей которые за деньги, для удовлетворения
собственных потребностей, и просто ради самовыражения будут эти самые
приложения клепать. Правда, это должна быть среда разработки приложений,
которая соотносится с существующими Delphi и C Builder-ами, примерно как
"Среда программирования Unix" времен Кернигана и Пайка
(shell+awk+yacc+C) соотносилась с распространенными в те времена языками
типа Fortran и Basic.
Посмотрим, какими же средствами мы располагаем сейчас, для того, чтобы
попытаться реализовать подобную идею. Начнем с универсального способа
представления информации. В NextStep попытались с этой целью
использовать Display Postscript. К сожалению, крупным недостатком
Postscript является то, что это полноценный процедурный язык, и
представить себе как выглядит постскриптовский файл, не
проинтерпретировав его полностью, принципиально нельзя. Поэтому
Postscript совершенно не подходит для программной обработки.
Кроме того, Postscript совершенно не заботится о сохранении
высокоуровневой содержательной информации - деления на какие-либо
логические части, например.
Во всех
остальных смыслах он совершенно замечателен - широко распространен, есть
свободно распространяемый код для интерпретации (Ghostscript), картинки
передаются в том же потоке, что и текст.
Display PDF уже гораздо лучше, чем Display Postscript, поскольку PDF -
язык преимущественно декларативный, а программы на декларативных языках
гораздо лучше поддаются автоматизированному анализу, чем программы на
процедурных. Есть в PDF и минимальные средства структурирования,
например гиперссылки. Но тут гораздо хуже как со средствами рендеринга, хотя
Alladin (а теперь уже и GNU) Ghostscript с этим справляется, и особенно
со средствами генерации. Кроме pdftex и того же Ghostscript ничего и
нет.
Попробуем зайти с другой стороны - со стороны языков логической
разметки. Сразу же в голову приходит SGML с его наиболее
распространенным вариантом HTML и наследником XML. Похоже, что это
именно то, что нам надо. Правза, в HTML картинки хранятся отдельно от
текста, но кто мешает придумать другую DTD. Зато есть средства сколь
угодно высокоуровневого логического структурирования, существенно
упрощающие объяснение программе того, что нам от нее нужно.
Еще одним, неожиданным, кандидатом на роль универсального способа
представления является X-протокол. С очевидностью, все что можно
показать на экране, можно представить в виде последовательности команд
этого языка. Более того, с появлением Xprt он теперь годится и как язык
описания страниц. Любая существующая программа под Unix умеет его
генерировать. Единственный недостаток - никто не пытался написать
программу обработки, которая не была бы X-сервером. К тому же, в
X-протоколе поток событий от пользователя к программе очень не похож
на поток событий от программы к пользователю (Х-серверу).
И еще один нетривиальный кандидат:
.c create rectangle 107.0 81.0 203.0 172.0 -disabledwidth 0 -tags {Rectangle obj utag1}
.c create line 108.0 81.0 158.0 18.0 202.0 82.0 -joinstyle miter -tags {Line obj utag2}
.c create rectangle 121.0 102.0 144.0 172.0 -disabledwidth 0 -tags {Rectangle obj utag3}
.c create rectangle 164.0 109.0 191.0 143.0 -disabledwidth 0 -fill #bfbfbf -tags {Rectangle obj utag4}
.c create text 155.0 207.0 -font {Helvetica 10 {}} -text {House, which Jack build
} -tags {text obj utag5}
Что это такое по-вашему? Векторный графический формат? Программа?
И то и другое - это рисунок, сделанный в графической программе tkpaint,
который на самом деле является программой на языке Tcl (на котором
написан сам Tkpaint).
Теперь о том, что не является документом - меню, диалоговое окно.
Заметим, что на программирование подобных вещей уходит львиная доля
труда пользователей RAD-систем, хотя казалось бы вот что RAD-инструменты
делают хорошо, так это диалоговые окна.
На самом деле это не так.
Порочен сам подход к интерфейсу как к картинке. Пользователь типичного
Delphi рассуждает так "разместим здесь вот этот интерфейсный элемент. Он
будет делать то-то и то-то". При этом минимальные изменения, такие как
переход к другому шрифту при создании национальной версии программы, или
увеличение размера поля БД приводят к полному развалу тщательно
продуманного внешнего вида окна.
Несколько более разумным подходом
представляется использование geometry manager, как в Tk или Xview, когда
расположение видимых элементов определяется в терминах их относительного
положения "вот эта кнопка под этой строкой ввода, выравненая по ее
правой границе". Очевидно, что такой способ более устойчив к изменениям
размеров шрифта или полей базы данных.
К сожалению, мошные geometry manager'ы имеют один существенный
недостаток - они отучают пользователя пользоваться графическими
application-designer'ами. Зачем, спрашивается рисовать на экране десять
полей ввода, когда трехстрочный скрипт с циклом foreach сам их
замечательно нарисует. Хотя, на самом деле разумной была бы гибкая
комбинация обоих подходов. Проблема в том, что для этого нужно то, что
не обеспечивается на данный момент ни одним средсвом RAD - возможность
переключаться между графическим дизайном и писанием кода в любой момент.
Но это только одна сторона вопроса. Вторая заключается в том, что мы,
имея готовую программу с диалоговыми окнами и прочим графическим
интерфейсом, хотим управлять ей из другой программы. На данный момент
существует только один способ решения этой проблемы - встраивание в
программу макроязыка, т.е. набора комманд, которые можно тем или иным
способом вызывать, будь то встроенный язык типа WordBasic, или методы
объекта OLE или CORBA, когда сам по себе язык реализован где-то
отдельно, а программа предоставляет только набор функций.
И в том и в другом случае, набор функций как правило сильно отличается
от набора позиций меню, а набор их параметров от набора полей ввода в
соответствующих диалоговых окнах. Да, конечно, есть операции, которые
могут быть интересны разработчикам приложений, но совершенно не нужны
пользователям, например "открыть файл и получить его дескриптор".
Но, принцип первый: все что может сделать пользователь, должна иметь
возможность сделать программа. Без реализации этого принципа реализовать
базовую идею разработки приложения как интеграции существующих
инструментов, не удастся.
Принцип второй: Если существуют операции, доступные только из языка
программирования, но не через GUI, то должна быть консоль, с которой
команды этого языка можно ввести. Без реализации этого принципа будет
неудобно отлаживаться и изучать поведение существующих приложений.
Известно, что первым пунктом в разделе BUGS любого man должно идти
"User never reads documentation". Поэтому надо дать пользователю
возможность изучать систему экспериментальным путем.
Обратите внимание, что в DOS существовал командный язык, слабенький, но
язык. В Windows 3.1 был Macro Recorder - попытка реализовать идею записи
сценариев работы. В Windows 95 его уже нет. Попытка реализовать писание
скриптов путем протоколирования действий пользователя в GUI-среде
блистательно провалилась. Почему? Потому что фиксировались слишком
низкоуровневые события - нажатия кнопок мыши в таких-то координатах. Это
существенно отличается от тех понятий, которыми оперирует пользователь
"Вытащим наверх окно Word и выберем позицию Open в меню File". Если бы
макрос записанный макро-рекордером выглядел бы как
MaximizeOrStart "winword.exe"
Menu.File.Open invoke
Filedialog.Filename insert "myfile.doc"
FileDialog.OpenButton invoke
может быть этим и можно было бы пользоваться. Особенно если при
последующем редактировании макроса можно было бы предоставить
пользователю свободу действий на каких-то этапах, например
Menu.File.Open invoke
Wait window.close "Filedialog"
if Filedialog.Exitcode=Ok then
...
endif
или наоборот, поместить эти действия внутрь цикла, скажем по всем файлам
в текущей директории.
Здесь мы сталкиваемся с той же проблемой, что и при проектировании
диалоговых окон - пользователь никогда не мыслит в терминах координат
экрана, даже когда он рисует мышкой линию в графическом редакторе.
Таким образом, складывается концепция принципиально нового подхода
к устройству десктопной OS, которая состоит в следующем:
Имеется базовый скриптовый язык, имеющий графический интерфейс.
Все необходимые компоненты реализуются как расширения для этого языка.
Они могут быть как объектно-ориентированными, так и нет. Я считаю, что
ООП это не панацея, тем более в ситуации когда работать с этим языком
зачастую будет конечный пользователь, которому легче в качестве
собеседника воспринимать компьютер в целом и формулировать свою мысль
как "Сделай то-то вот с этим объектом", а не "Эй, объект, сделай вот
это", особенно в ситуациях когда задействовано несколько объектов.
Например, неочевидно, чьим методом должно являться копирование из
объекта в объект - источника или назначения.
Уровень абстракции, на котором пользователь работает с этим языком
должен быть несколько выше, чем тот, который предоставляют Tcl/Tk или
Python.
Для часто выполняемых операций, таких как создание диалогового окна,
связывание формы с базой данных, должны существовать графические интерфейсы.
В идеале у каждого приложения данной системы должна быть кнопочка в
заголовке окна "Показать внутреннее устройство", которая превращает
окно приложение в окно RAD-системы. Последнее, видимо представляет собой
диалог с закладками, где можно посмотреть иерархию видгетов внутри окна,
связи с другими объектами в системе, текст который в результате
получился.
Для всех объектов в системе, которые по смыслу являются документами (а
таких будет не так много, как в MacOS или Windows) должен существовать
способ получить их стандартное представление, видимо на чем-то типа XML,
и должны существовать средства обработки этого XML, по простоте и
эффективности подобные grep, awk и sed, но учитывающие в удобных для
пользователя терминах структуру этого XML.
Мне кажется, что идеальным языком для реализации такой системы является
Tcl. Его преимущества:
1. Гибкий синтаксис, вполть до возможности реализации собственных
управляющих структур, что облегчает создание языка верхнего уровня.
2. Простота разбора скриптов на Tcl средствами самого Tcl, что облегчает
создание RAD-компонент, способных прочитать и графически представить
произвольный код.
3. Наличие мощных интроспективных функций, которые делают ненужным
разбор кода, например для показа иерархии виджетов - проще спросить у
самих виджетов.
4. Наличие системы соподчиненных интерпретаторов, что позволяет не
засорять пространство имен приложения функциями и объектами RAD-системы
5. Наличие большого количества готовых компонент, хотя Python и Perl в
этом отношении несколько превосходят Tcl.
Все вышеперечисленное не означает, что на Tcl должны быть написаны все
компоненты системы. Скорее наоборот, большая часть вещей, для которых
критична производительность, должны быть написаны на C или C++, но в
виде расширений Tcl.
Виктор Вагнер