KOL – кодоекономічная об’єктна бібліотека для Delphi, Delphi, Програмування, статті

Мета даної статті – переконати читача (я сподіваюся, цей текст потрапить в руки програміста), який звик до великих розмірах сучасних програм (о, ні, додатків, програми-то якраз були ще не дуже великими) в тому, що його безсовісно надувають. Коли стверджують, що програма для середовища Windows, якщо вона щось корисне вміє робити, ніяк не може бути менше … ну, скажімо, триста кілобайт. А якщо це дуже “розумна” програма, яка містить дуже багато корисних можливостей, хороший інтерфейс, відмінно взаємодіє з користувачем, підтримує різні формати даних, сучасні клієнт-серверні технології, то без півсотні мегабайт ну ніяк не обійтися. Нісенітниця несусвітня. Нас обманюють!


Насправді, об’єктне програмування дозволяє створювати дуже економічний за розміром код. Причому, досить ефективний. Приклади? Пожалуйства. Ява – об’єктно-орієнтоване програмування. Ява-аплети дуже невеликі за своїми розмірами, а як багато корисного вони вміють робити! Втім, мова піде не про Яві. Предметом даного розмови буде середу Delphi.

Як не дивно, саме Delphi виявився тим інструментом, за допомогою якого виявилося можливим виготовити бібліотеку KOL – Key Objects Library (Ключову Об’єктну Бібліотеку). Дивно тому, може бути, що програми, виготовлені засобами Delphi, зазвичай маленькими не бувають. Мінімальний стартовий розмір програми, що представляє із себе одне пусте вікно, яке можна посувати по екрану і закрити, і яке, власне, нічого більше робити не вміє, становить близько трьохсот кілобайт. Причому, з випуском кожної чергової версії Delphi цей стартовий розмір виростає ще на кілька десятків ні в чому не винних кілобайт.

Бібліотека KOL дозволяє виготовляти не менш потужні програми, ніж стандартна бібліотека Delphi – VCL (Visual Component Library, Візуальна Бібліотека Компонентів). І при цьому домагатися зменшення розмірів програм в 5-15 разів! Наприклад, додаток DirComp, доступне для завантаження на сайті KOL, займає без стиснення пакувальних програмами близько 65 кілобайт. Аналогічне додаток, написаний за два роки до цього з використанням стандартної бібліотеки Delphi, займало 750 кілобайт. Різниця вражає, чи не так?

KOL – не тільки об’єктно-орієнтована, а й візуальна бібліотека. Програми та їх графічний інтерфейс можливо проектувати практично так само, як і у візуальному середовищі VCL. На додаток до KOL йде бібліотека MCK (Mirror Classes Kit, Бібліотека дзеркальних Класів), яка містить VCL-компоненти, що встановлюються на палітру звичайним чином. Єдина відмінність в тому, що дзеркальні компоненти бібліотеки MCK існують тільки на стадії розробки (design time), беручи участь в генерації “справжнього” коду, сумісного з вимогами бібліотеки KOL. Під час роботи (run time) виконується цей код, і той, який був доданий самим розробником. У коді, виконавчі немає посилань на компоненти VCL, є тільки об’єкти KOL, компактні й ефективні.

У чому ж полягає секрет компактності коду? Відповідь не один, але виділити головні складові все ж видається можливим. У першу чергу слід відзначити здатність компілятора Delphi не включати в код кінцевого програми незатребуваний код. Процедури і змінні, на які немає посилань з того коду, який вже внесений до списку ділянок коду, що підлягають включенню в кінцевий продукт, відкидаються і в подальшій збірці не учавствуют. На жаль, дана здатність компілятора Delphi, звана самими розробниками компілятора “smart linking” (розумне зв’язування), дещо обмежена. Зокрема, віртуальні методи використовуються класів і об’єктів не можуть бути вилучені з процесу компіляції і збірки додатку. Відповідно, і ті змінні і процедури (методи), на які є посилання з таких віртуальних методів, також не можуть бути відкинуті.

При розробці бібліотеки KOL ця обставина була врахована. Автору довелося відмовитися від жорсткого слідування канонам об’єктно-орієнтованого програмування. Зокрема, в KOL один і той же об’єктний тип може використовуватися для інкапсуляції декількох подібних один одному об’єктів. Наприклад, тип TControl не є базовим для опису візуальних об’єктів подібно тому, як це зроблено в VCL. Представники об’єктного типу TControl в бібліотеці KOL вже без будь-якого наслідування можуть виконувати роль різних візуальних об’єктів (кнопок, міток, панельок, і т.п.) – в залежності від того, яка глобальна функція використовувалася для конструювання кожного конкретного об’єкта (наприклад, NewPanel, NewButton і т.д.)

Таке суміщення декількох об’єктів в одному об’єктному типі, взагалі кажучи, може приводити до деякої плутанини, оскільки поряд з методами і властивостями, загальними для всіх об’єктів, інкапсульованих цим об’єктним типом, можуть матися методи і властивості суто індивідуальні, характерні тільки для певної конкретної різновиду об’єктів. Оскільки тип (клас) той же самий, існує ймовірність помилкового застосування методу, не властивого для даного різновиду об’єкта. Єдина причина, що змусила автора чинити так, це необхідність уникнути великої числи віртуальних методів.

Зрозуміло, якби віртуальні методи благополучно пропускалися компілятором в тих випадках, коли вони не потрібні (а потенційно така можливість існує), структуру об’єктів можна було б зробити більш ясною. Тим не менш, навіть і в цьому випадку VCL не дозволив би програмами стати набагато компактніше. І проблема тут вже в тому, що розробники VCL спроектували свою бібліотеку так, що багато об’єктів створюються і багато дії проводяться ще до того, як буде відомо, чи знадобляться вони взагалі, чи так і залишаться лежати в коді програми мертвим вантажем. Наприклад, якщо створюється візуальний об’єкт, то для нього ініціалізується шрифт, полотно для малювання, менеджери перетягування, безліч інших об’єктів – на всякий випадок: а раптом знадобляться! Звичайно, програму може знадобитися щось намалювати, або змінити небудь шрифт. Програма може бути спроектована для використання популярного інтерфейсу розташування плаваючих панелей drag-and-dock. Може, але ж не зобов’язана, так?

На противагу VCL, бібліотека KOL надходить з необов’язковими діями і об’єктами значно більш акуратно. Вони (дії) виконуються і (об’єкти) ініціалізувалися тільки тоді, коли вони вперше будуть потрібні. Очищення ресурсів і пам’яті по завершенні використання при цьому проблем як раз не представляє. Один і той же (віртуальний) метод Free прекрасно справляється зі звільненням відпрацьованих підлеглих об’єктів, незалежно від їх типу. Власне, це і є головна причина того, чому програми, виготовлені з використанням бібліотеки KOL, настільки кодоекономічни.

У описуваної бібліотеці використовується кілька різних способів реалізації такого відкладеного прийняття рішення, в залежності від природи необов’язкового до включення в програму коду. Важливіше не стільки перерахувати ці способи, які, взагалі кажучи, є просто вдалим застосуванням загальноприйнятих програмістських прийомів, скільки пояснити і зрозуміти суть їхньої дії.

Як відомо, вихідний текст програми перетворюється в виконуваний машинний код в результаті роботи іноді декількох програм: прекомпілятора, компілятора, збирача. Зазначимо, що коли мова йде про середовище Delphi, розділяти ці кроки особливого сенсу не має, тому що всі вони виконуються однією і тією ж програмою. Тому, кажучи “компілятор”, будемо мати на увазі всі ці етапи разом. Оскільки саме компілятор Delphi приймає рішення, підключати або не підключати код тієї чи іншої процедури до програми, відкладання рішення про необхідність її використання шляхом першого звернення до неї в коді тільки тоді, коли її функціональність виявилася затребуваною розробником проекту, вимагає пояснення.

Насправді, все дуже просто пояснюється слеующім невеликим прикладом. Нехай наш візуальний об’єкт (кнопка, наприклад) містить властивість Font (шрифт). На відміну від VCL, не будемо створювати підлеглий об’єкт, що відповідає цій властивості, в конструкторі нашого об’єкта (кнопки, господаря шрифту). Створимо його в тому методі, який виконує читання властивості Font (в методі GetFont), у разі якщо він ще не створено. В результаті, якщо в додатку до властивості Font ніде немає звернень (тобто розробнику не було потреби змінювати шрифт своїх візуальних об’єктів, і його влаштовують стандартні шрифти, налаштовані користувачем), компілятор не виявить і жодного виклику методу GetFont, і відповідно, не включить в програму код цього методу. Отже, жодного посилання не буде виявлено ні на конструктор об’єкта шрифту, ні на інші процедури, які інакше б опинилися задіяні і потрапили б в здійснимий модуль.

Зрозуміло, що наведений приклад пояснює тільки один з багатьох використаних прийомів. Але принцип всіх таких прийомів один і той же, а саме, як вже сказано вище: відкласти прийняття рішення про підключення додаткового коду до тих пір, поки він не буде потрібно розробнику программногопродукта. На думку автора, даний принцип в корені розходиться зі сформованою практикою програмування. Мабуть, на прикладі KOL, зокрема доведена безглуздість загальноприйнятого підходу, який призводить до того, що 90% коду в сучасних додатках – це шлак, сміття, який якщо і працює, то вхолосту, і лише даремно витрачає ресурси процесора, оперативної пам’яті, займає місце на жорсткому диску, забирає час при передачі зайвих сотень кілобайт по мережі і через інтернет, і залазить при цьому у вашу кишеню. І недарма у відповідь на питання, як зменшити розмір програми, іноді можна отримати таку відповідь, що, мовляв, навіщо зменшувати? – Чим більший об’єм, тим більше заплатять. (Варіанти: “солідніший”, замовник більше поважає). Чи не нісенітниця чи що?

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


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

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

Ваш отзыв

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

*

*