вторник, 25 декабря 2007 г.

Форма и содержание

Наверное, сейчас уже никто толком не скажет, кто и когда придумал метафору формы – как прототипа экранного окна. Возможно, эта идея неотделима от идеи самого окна, а она, как известно, в научном и техническом мире витала и обретала различные представления не один десяток лет. Так или иначе, попытки визуально проектировать интерфейс с помощью форм я увидел впервые году так в 1990, когда приходил к отцу на работу посмотреть на персональные компьютеры IBM PC/AT 286 «Компан». Это был Clarion версии 2.0. Он был оснащен так называемым скриндизайнером, который позволял с помощью мышки, достаточно быстро и споро создать под ДОС псевдографический пользовательский интерфейс для разрабатываемой базы данных. Как сейчас помню - сижу, расставляю мышкой ключики у полей, не очень понимая, для чего все это нужно, перемещаю окошки, как вдруг слышу сзади голос начальника отдела автоматизации: «Ну что, сидишь, ерундой маешься? Займись-ка лучше делом!» И достает из конвертика пятидюймовую дискету с надписью «Будокан». Конечно, обучение Clarion на этом закончилось, но всё равно, те деньки я вспоминаю с воодушевлением. Потому что были ещё Арканойд, Метал Мутантс и многое другое. =)
Что касательно Clarion-а, то он до сих пор весел, здоров и замечательно себя чувствует. Возможно, появление Foxpro, Delphi и других подобных систем и подпортило ему жизнь, но уже тогда в нем был заложен очень большой потенциал, который помог Clarion дожить до .Net 2.0. Удивительное дело, но, похоже, сама судьба помогла Брюсу Берингтону, основателю компании HBO и разработчику Clarion в его начинаниях. Ища наиболее перспективные пути развития своего продукта он наткнулся на компилятор от небольшой и почти неизвестной компании JPI, которую создал Нильс Йенсен – один из основоположников Borland. Компилятор этот был непростой. Основанный на Борландовских разработках, он был переработан командой Йенсена так, что для всех поддерживаемых языков (а их было немало – Модула, Паскаль, Си и Си++) компилятор генерировал совместимый двоичный код. Поэтому, в рамках одного приложения можно было использовать любой из этих языков без особых проблем. Так что пятнадцать лет спустя переход на .Net, заключаю я с некоторой долей иронии, является скорее способом остаться в рамках мейнстрима, нежели технологическим шагом вперед. =)
Но оставим Clarion в покое, в конце концов, речь сейчас идет не о нем, а о формах. Именно о них, родимых, я и хотел поговорить. Несомненно, сама парадигма форм в Delphi была сильнейшим стимулом к переходу на это средство разработки. Достаточно просто просуммировать время, потраченное на невизуальное создание окон в Windows, что хочется забыть эти пустые хлопоты, как страшный сон. Но технологии не стоят на месте, достоинства стерлись бытом, а недостатки стали все четче проявляться и мозолить глаз. Прежде всего, это раздельное хранение класса формы и её инициализации в двух разных файлах Pas и Dfm. Почему был выбран путь отделения формы и модуля? Наверное, в 1994 году не хватало технологий, производительности, ещё чего-то? Может быть, тогда существовала какая-то очередная иррациональная мода, которая может заставить разумных людей делать безумные вещи – например, покупать ужасные по реализации, но раскрученные пиаром технологии или затыкать XML-ем любую дыру. К сожалению, достоверные причины мне неизвестны (к тому же, вряд ли можно создать архитектуру, прожившую в IT сфере более десяти лет и удовлетворяющих всех и вся). Но все-таки хранить настройки формы в отдельном файле от класса – это очень неудобно. При этом происходит неоправданное размазывание логики приложения. Часть кода в модуле, часть в форме. Хотим мы что-то изменить, поиском прошли, да и не нашли часть инициализации. Где-то поменяли, где-то забыли. В таких условиях я часто склоняюсь к тому, что некоторые настройки формы и компонентов на ней вообще лучше писать в коде, чтобы получить гибкость в управлении изменениями (согласитесь, что не всегда удобно открывать монстрообразную среду, чтобы внести пару простейших изменений в код). Ну и сравнивать две версии проекта приходится тоже дважды – в модуле и в форме. Еще одной шероховатостью, связанной с разделением данных, является необходимость инициализации компонентов из потока в методе Loaded (и установка соответствующего состояния), которая, конечно, досконально описана, разжевана и не вызывает проблем у опытных разработчиков, но рождает некоторое недоумение в глазах новичков. А что ж делать? Система-то уже построена, надо как-то с ней жить. И для нивелирования недостатков её архитектуры появляются семиногие подпорки: в новых версиях Delphi встроенный рефакторинг, который учитывает особенности такого разделения кода и проводит изменения не только в тексте модуля, но и в дизайнере. А для старых версий – есть различные эксперты, реализующие отсутствующую функциональность. Да и если проследить историю развития Delphi, то от версии к версии можно заметить, что механизм обслуживания такой дуалистической архитектуры совершенствовался, развивался и улучшался, давая больше сервисных функций (читай – подпорок).
Другая засада – это невизуальные компоненты на форме. Порой проект разрастается до таких размеров, что под невизуальными компонентами уже не видно визуальных. И первые приходится постоянно перекладывать с места на место, чтобы добраться до вторых. Правильное решение этой проблемы – создание Datamodule, если быть до конца честными, тоже подпорка из разряда: «О как удачно все получается!».
Конечно, если опытный разработчик начинает новый проект, он знает обо всех этих заковыках, и его код будет максимально приспособлен под такие особенности среды. Как говорится: «все правильно сделал!», т.е. с оглядкой на такой вот небольшой бардачок в сердце технологии.
«Что делать» давно знают и разработчики Delphi, и её пользователи. Готовые решения есть прямо тут, в Delphi для Net. Загляните в Winforms и увидите простую и элегантную реализацию хранения и инициализации формы в коде класса. Ненужные постоянно методы скрыты фолдом, страшный LiveSource для надежности можно вообще выкинуть и заменить простым Include с автогенерацией. Что касается невизуальных компонентов, то в Winforms для этого есть специальный отсек. Компоненты форму не засоряют, расположены упорядочено, есть скроллер, можно ещё контекстный поиск добавить. Красота. И сделать такой отсек для VCL ветки продукта на вскиду не составит проблем, так как это просто интерфейсное решение.
В заключение хочу сказать, что на мой скромный взгляд эти изменения нужны. Может быть, они не такие необходимые, как поддержка Unicode и 64 разрядной архитектуры, но они помогут сделать Delphi лучше. Да, возможно, не все старые проекты будут работать как надо, но это все решается. Скорее всего, конечному пользователю даже думать над совместимостью не доведется – старые формы смогут работать параллельно с новыми. Компоненты, если они написаны правильно, тоже не придется переписывать. Кое-что надо будет почитать, появятся дополнительные настройки, но это не такая уж большая проблема. В конце концов, мы уже десять лет живем с OldCreateOrder под боком, и по моим сведениям, никто от этого ещё не умер…

4 комментария:

Анонимный комментирует...

Здравствуйте! Спасибо вам за ваш блог. Очень нужный!

cobo комментирует...

> увидите простую и элегантную
> реализацию хранения и
> инициализации формы в коде класса

и забудьте про наследование форм и фреймов, да?

Mikhail Mokhov комментирует...

Почему, как и любой другой класс мы можем наследовать формы. Принципиальных ограничений ведь в этом вопросе нет. Просто раньше борландовской реализации C# и Delphi.Net как-то это дело глючило. =) Сейчас не знаю.

Анонимный комментирует...

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