Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

Надежные VPS и выделенные серверы в Нидерландах

Storage VPS, High CPU VPS

Профессиональная техническая поддержка

Домены, SSL сертификаты, VPN

Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

Спринтхост — хостинг от 129 ₽ в месяц

Бесподобная поддержка, тестовый период 30 дней и домены от 149 ₽

Промокод на 30% кешбэк — CITFORUM

2005 г.

Как перестать беспокоиться и начать программировать.

Андрей Кочетов, «Королевство Delphi»

Цикл статей "Как перестать беспокоиться и начать программировать" размышления старого программиста о жизни и о себе
Часть 1 Часть 2 Часть 3
Введение
Целевая аудитория:
молодёжь, которая хотела бы заниматься программированием; возможно, что-то полезное для себя найдут и более подкованные товарищи
Структура заметок:
рассуждения общего характера, плавно перетекающие в конкретные примеры с исходниками
Среда разработки:
Borland C++ Builder; большинство исходников с лёгкостью переносятся в Delphi; общие рассуждения вообще справедливы для любого средства разработки
Затронутые темы:
  • разработка собственных компонентов (интерфейсных, вспомогательных, системных, работающих с БД, и т.д.)
  • разработка архитектуры приложений
  • унификация процесса проектирования приложений

Хочу обратить внимание читателей, что никаких откровений или мыслей, блистающих особой глубиной/новизной, вы здесь не найдёте. Просто прикладной программист среднего (или чуть выше) уровня излагает свои соображения, рождённые опытом работы, и иллюстрирует их конкретными примерами работающего инструментария.

Ещё раз подчёркиваю, что по всем вопросам изложена моя личная точка зрения. Я открыт для конструктивной дискуссии и с радостью восприму все замечания, исправления и дополнения к исходным текстам.

Предполагается, что читатель знаком с основными принципами объектно-ориентированного программирования и разработки приложений.

Последовательность изложения: вначале будет описана совокупность инструментов. Это займёт несколько статей (глав) – вместе с исходными текстами и примерами использования.

Во второй половине будет описана моя стратегия разработки приложений с примерами реализации.

Итак,

часть I. Комплект инструментов.

Чем профессионал отличается от любителя? На мой взгляд, наличием собственных стратегии и "средств производства". Совокупность собственных инструментов, которыми пользуется профи, преодолев определённый объём и качество структуризации, становятся его собственной инструментальной средой. Её использование сокращает большинство этапов разработки, увеличивает надёжность продукта, упрощает сопровождение.

Должен без ложной скромности признаться, что некоторые идеи, реализованные мною в своей среде, которую я называю "ASK Tools", впоследствии обнаружил в .NET. Конечно же, совсем на другом качественном уровне.

Много лет я работаю в качестве прикладного программиста БД. Все последние проекты, как закрытые (корпоративные), так и общедоступные, используют "ASK Tools" и некоторые принципы разработки, которые я считаю весьма полезными.

"ASK Tools" содержит только те инструменты, которые нужны повседневно при разработке бизнес-приложений. Здесь вы не найдёте работы с мультимедиа и прочих буржуазных излишеств – спартанская простота, которая кому-то покажется скудостью. Возможно, не без основания.

Состав "ASK Tools":
  1. AskMsg.* - файлы текстовых ресурсов
  2. AskClasses.dll - библиотека классов низкого уровня, которая используется всеми прочими компонентами из состава "ASK Tools"
  3. AskImg.dll – графическая библиотека, содержащая набор общеупотребительных изображений
  4. AskFunc.dll – библиотека функций
  5. ASK.bpl – пакет компонентов BCB, Delphi
  6. AskForm.dll – библиотека форм

Средствами "ASK Tools" реализовано простое средство формирования текстовых отчётов; на звание "генератор отчётов" оно не претендует, однако ж довольно удобно в использовании.

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

Ничего нового в такой организации нет: это отвечает идее повторного использования ресурсов, доведённой до совершенства разработчиками из Microsoft. Я полностью разделяю и поддерживаю эту идею, и хотел бы немного её разъяснить. Повторное использование ресурсов (текстовых, графических, программного кода) выгодно как разработчику, так и исполняющей системе (компьютеру, на котором выполняется программа).

Программист, однажды разработав и отладив ресурс (в том числе и программный код), в дальнейшем использует его многократно, что ускоряет процесс разработки, упрощает отладку за счёт локализации кода в одном лишь известном месте, и повышает надёжность софта.

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

Следствием моей приверженности этой идее является тот факт, что я никогда не собираю BCB и Delphi-приложения без использования runtime компонент. Более того, все ресурсы, необходимые для работы моих приложений, я отдаю заказчикам в виде отдельных дистрибутивов. За счёт этого дистрибутивы собственно прикладных программ получаются довольно компактными, что упрощает обновление версий через Интернет.

Текстовые ресурсы

Как уже было сказано, они используются всеми остальными компонентами инструментального пакета. Уточнение: когда упоминаются "компоненты пакета инструментов "ASK Tools", имеются в виду не Delphi-компоненты, а составляющие пакета.

Выделение текста в отдельный ресурс позволяет упростить интернационализацию приложений: файл легко перевести на любой язык. Файлы ресурсов имеют структуру INI-файлов и расширение, соответствующее трёхбуквенному обозначению языка локализации: ENU, RUS, и т.д. Любой компонент пакета, обращающийся к текстовым ресурсам, предварительно определяет язык локализации Windows, и затем использует нужный файл.

Пример содержимого файла текстовых ресурсов:

[TypeOfDisk]
Unknown=Не определён
REMOVABLE=Сменный
FIXED=Локальный
REMOTE=Сетевой
CDROM=CD-ROM
RAMDISK=Виртуальный (RAM)
[Printer]
ErrOpen=Ошибка открытия принтера
ErrStartDoc=Ошибка начала печати
ErrWrite=Ошибка печати
[ErrNo]
1=Неверный № функции
2=Файл не найден
3=Путь не найден
7=Блок памяти уничтожен
9=Неверный адрес блока памяти
.
.
.

Библиотека классов низкого уровня

Здесь "низкий уровень" - условное название, отражающее тот факт, что эти классы используются всеми остальными компонентами "ASK Tools".

Класс TAskCursor

TAskCursor.*. В период выполнения программы для обозначения длительных операций часто требуется изменить форму курсора, а по завершении операции – вернуть курсор в нормальный вид. Писать каждый раз что-то типа "Screen->Cursor = crHourGlass", а затем не забыть "Screen->Cursor = crDefault" - это слищком тяжко. Как известно, лень – двигатель прогресса, поэтому гораздо приятнее изобрести простенький классик, при создании экземпляра которого курсор будет менять форму, а при прекращении сусуществования объекта – возвращать свою форму. Согласитесь, приятно написать такое:

void Func(void)
{
TAskCursor Cursor;
  // …тело "притормаживающей" функции…
}

Класс AskMoney

AskMoney.*. Класс "денежная сумма", предназначенный для финансовых расчётов. Имеет public-методы:

AnsiString __fastcall InWords(int CurrencyCode=810); // Сумма прописью
char *         __fastcall c_str(bool isSpaces=true); // Сумма прописью

Пояснение: if(isSpaces == true и сумма нулевая) then будет сформирована пустая строка, а не "0-00"

Классы AskDate, BCDate, AskTime

AskDate.*, BCDate.*, AskTime - классы моей разработки, унаследованные из DOS. Иногда их использовать (лично мне) немножко удобнее, чем TDateTime

Класс TFile

TFile.* - базовый класс для классов "ToFile" и "IniFile". Здесь уместно следующее пояснение. В языке "С++" есть средства, унаследованные из языка "С". Например, многие системные функции, функции работы с файлами, и т.д. К их числу относится подавляющее большинство функций Windows API.

Работа с ними кардинально отличается от работы со средствами С++, и не в лучшую сторону. В С++ (а также средах Delphi, BCB, и т.д.) принято обрабатывать ошибки времени исполнения с помощью исключений (exceptions). То есть если программист не обработал возникшую ошибку на прикладном уровне, она будет обработана системой исполнения, и ничего страшного не произойдёт.

Совсем иное дело – работа унаследованных функций. Здесь ошибки требуется обрабатывать с помощью анализа кода возврата каждой такой функции. Если прикладной программист не забудет это сделать, ему придётся отлить прижизненный памятник, так как такая работа крайне трудоёмка и не отвечает современным методам разработки ПО.

Если же программист будет забывать или пренебрегать обработкой ошибок, получится некачественный код, ненадёжное ПО, которое будет "глючить" в самых неожиданных местах. Это, в свою очередь, может привести к самым плачевным результатам: потере данных, краху системы, и т.д.

Можно возразить: "не используйте устаревшие средства". Ну, во-первых, это возможно далеко не всегда: API-функции из песни не выкинешь; во-вторых, лично мне работа с потоками ввода вывода С++ (stream) кажется излишне громоздкой, во многих случаях гораздо приятнее обходиться старыми добрыми средствами.

Выход один: для каждого случая использования устаревших средств языка необходимо писать класс-обёртку, который будет обрабатывать все возможные коды возврата всех унаследованных функций и преобразовывать их в исключения (exception). Проблема кардинально решена в .NET – и именно описанным способом.

Так вот, классы, производные от TFile, являются оболочками для файловых функций. Их основной задачей является обработка кодов возврата файловых функций языка "С" и преобразование их в исключения. Дополнительным, но не менее приятным бонусом, является более удобная функциональность классов по сравнению с использованием простых функций. Это ведёт к написанию более лаконичного кода.

Итак, "завернув" все унаследованные функции в "оболочки" классов, мы делаем шажок к написанию безопасного кода.

Класс IniFile (производный от TFile)

IniFile.* - класс-оболочка для функций работы с .INI-файлами. Удобен как способом формирования имени файла, так и методами "get" и "put". Пример использования:

void Func(int Count)
{
IniFile ini(“C:\\TEMP\\Sets%02d.ini”, Count);
// Последний параметр - умолчание
AnsiString Str = ini.get(“Section”, “StrParam”, “”);
 // Последний параметр – умолчание
long Lng = ini.get(“Section”, “LongParam”, 0L);
  ini.put(“Section”, “LongParam”, Lng + 3);
}

Класс ToFile (производный от TFile)

ToFile.* ("открываемый файл") – класс-оболочка для работы с файлами, текстовыми и двоичными. Удобен как способом формирования имени файла, так и методами. Файл необязательно закрывать вручную, он будет закрыт автоматически перед прекращением существования экземпляра класса. В случае возникновения ошибки при работе с файлом будет возбуждено исключение, содержащее (в дополнительных числовых и строковых полях errNo, dosErrNo) всю информацию о файловой ошибке.

Пример использования:

void Func(int Count)
{
ToFile r(“r”, “C:\\TEMP\\read%02d.txt”, Count);
ToFile w(“w”, “C:\\TEMP\\write%02d.txt”, Count);
AnsiString Str;
  r.GetStr(Str);
  w.fprintf(“Прочитанная строка: %s\n”, Str.c_str());
}

Класс TAskRecycleBin

Стоит несколько особняком, так как используется напрямую только в тех приложениях, которые должны поддерживать работу с "Корзиной". Думаю, декларация свойств и методов класса не нуждается в дополнительных комментариях:

#ifndef AskRecycleBin_H
#define AskRecycleBin_H
#include <vcl.h>
#include "shellapi.h"
#ifdef DLL_EXP
# define CLASS_MODE __export
#else
# ifdef DLL_IMP
# define CLASS_MODE __import
# else
# define CLASS_MODE
# endif
#endif
const DWORD SHERB_SILENT = SHERB_NOCONFIRMATION | SHERB_NOPROGRESSUI
  | SHERB_NOSOUND;
class CLASS_MODE TAskRecycleBin {
private:
        bool __fastcall GetCanErase();
        bool __fastcall GetCanUse  ();
protected:
        DWORD GetDLLVersion(String dllName);
        inline DWORD PackDLLVersion(DWORD major, DWORD minor)
		   { return((major << 16) + minor); }
public:
        bool DeleteFiles(String filespec, bool allowUndo=true);
        bool Erase();
        __property bool CanErase  = { read=GetCanErase };
        __property bool CanUse    = { read=GetCanUse   };
};
#endif

Библиотека функций общего назначения

Достойна упоминания лишь одна функция: разбиение строки текста на строки меньшей и ограниченной длины с пословным переносом. Практически все остальные случаи жизни можно инкапсулировать в классы :-) Спецификация: void StringWordSplit(AnsiString Str, TStringList *StringList, const unsigned short LengthOfOneLine)

Пример использования:

void Func(void)
{
std::auto_ptr<TStringList> StrLst(new TStringList());
ToFile w(“w”, “C:\\TEMP\\ StringWordSplit.txt”); // Открыть файл
  // Разбить фразу на строки длиной не более 20 знаков
  StringWordSplit(“Четыре чёрненьких чумазеньких чертёнка
  чертили чёрными чернилами чертёж”,
                  StrLst.get(), 20);
  // Вывести все строки в файл
  for(int i=0; i<StrLst.Count; ++i) {
    w.fprintf(“%d: %s\n”, i+1, StrLst->Strings[i].c_str());
  }
}

Результат:

1: Четыре чёрненьких
2: чумазеньких
3: чертёнка чертили
4: чёрными чернилами
5: чертёж

Графическая библиотека

AskImg.dll содержит графические образы общего назначения - такие, как картинки 16Х16 для кнопок TBitBtn и 32Х32 для кнопок в инструментальной панели. Зачем это нужно? Графика, как и любой другой повторяющийся ресурс, увеличивает объём результирующего .EXE-файла. Возьмите размер ресурса, умножьте его на количество копий – и получите объём балласта в программе. Неверящие могут провести простой эксперимент: создать форму в Delphi, бросить на неё несколько экземпляров кнопок TBitBtn с непустым свойством "Glyph", а затем посмотреть на содержимое файла ресурсов этой формы (.DFM) в текстовом виде.

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

Пакет компонентов ASK.BPL

Ну, вот мы и добрались до ядра "ASK Tools". Пакет состоит из компонентов разного назначения, сгруппированных на нескольких закладках (после установки в среде BCB или Delphi). Пойдём от простого к сложному.

Закладка "ASK Controls"

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

Компонент TAskButton унаследован от "TButton" и обладает дополнительными свойствами:

  • PtrSecondBtn – указатель на соседнюю кнопку (чаще всего на кнопку "Cancel" - для кнопки "OK")
  • AskSetMouse – если "true", то при показе формы курсор мышки будет сфокусирован на этой кнопке
  • AskEnabledOff - если "true", то при нажатии на кнопку свойство "Enabled" примет значение "false"
  • AskKind – облегчает жизнь во время проектирования (design time). Значение по умолчанию – "akCustom".
    • Если в инспекторе объектов ему присвоить значение "akOK", следующим свойствам будут присвоены значения:
      • ModalResult - mrOk
      • Caption - читается из файла текстовых ресурсов, соответствующего языку локализации Windows: "Выполнить", "OK", и т.д.
      • Cancel – false
      • Default – true
      • AskSetMouse – true
      • AskEnabledOff – true
    • Если в инспекторе объектов ему присвоить значение "akCancel", следующим свойствам будут присвоены значения:
      • ModalResult - mrCancel
      • Caption - читается из файла текстовых ресурсов, соответствующего языку локализации Windows: "Выход", "Cancel", и т.д.
      • Cancel – true
      • Default – false
      • AskSetMouse – false
      • AskEnabledOff – false

Компонент TAskBitBtn унаследован от TBitBtn, аналогичен TAskButton, но дополнительно имеет ещё 2 свойства:

  • AskNameDll – имя DLL, содержащей графические ресурсы. По умолчанию – "AskImg.dll"
  • AskNamePic – имя графического ресурса (картинки 16Х16) из указанной DLL

Как видно из названия свойств, эта кнопка загружает картинку из DLL во время выполнения; в "design time" кнопка не содержит изображения, что способствует уменьшению размера исполняемого модуля.

Уф, кажется, для первого раза хватит. Исходные тексты всех упомянутых элементов представлены в архиве.
До встречи, дорогие читатели!

Скачать архив: AskTools.rar (18 K)

Часть 2 Часть 3

VPS в России, Европе и США

Бесплатная поддержка и администрирование

Оплата российскими и международными картами

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...