Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Свитки
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  06:06[Войти] | [Зарегистрироваться]

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

Аслан Корытов
дата публикации 10-09-2004 16:08

Как перестать беспокоиться и начать программировать. Часть I. Комплект инструментов. Цикл статей «Как перестать беспокоиться и начать программировать»
размышления старого программиста о жизни и о себе

Введение
Целевая аудитория:
молодёжь, которая хотела бы заниматься программированием; возможно, что-то полезное для себя найдут и более подкованные товарищи
Структура заметок:
рассуждения общего характера, плавно перетекающие в конкретные примеры с исходниками
Среда разработки:
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)


Смотрите также материалы по темам:
[Дополнительные средства и утилиты]

 Обсуждение материала [ 14-09-2004 15:14 ] 4 сообщения
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования