Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Универсализация кода, Подходы, удобные утилитарные функции 
:(
    Опции темы
vstepanov78
Дата 30.8.2010, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 10.1.2006
Где: Москва

Репутация: нет
Всего: нет



В теме предполагаю писать и предлагаю обмениваться различными красивыми решениями по универсализации кода, подходов к простым типичным, часто возникающим в процессе программирования задачам (баланс - если сделать слишком универсально, то выйдет слишком сложно, а весь функционал и не потребуется, а если неуниверсально, то вскоре придется переделывать или доделывать). Также идеи раличных удобных функций и объектов. Примерные темы: работа с различными типами (различные утилитарные функции по каждому типу, которых не хватает в стандартных библиотеках Delphi), парсинг строк, память, списки (включая таблицы, иерархия), файлы (включая работу с именами файлов, логи, параметры командной строки), потоки, ini и реестр, многопоточность, исключительные ситуации, языки, а также окна и диалоги, базы данных, интернет, процессы, финансовые функции, криптография, VCL и др.

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

Код

{Классика жанра - при IfCase равном True вернуть ValueIfTrue,
иначе ValueIfFalse; пригождаются и вариации этой функции для Integer
и др. типов}
function IIf(IfCase: Boolean; const ValueIfTrue, ValueIfFalse: string): string;
{Добавить к строке S префикс PrefixStr, постфикс PostfixStr, если она непустая,
иначе вернуть пустую строку}
function AddPrefix(const PrefixStr, S: string): string;
function AddPostfix(const S, PostfixStr: string): string;
{Соединить строки S1 и S2, при этом между ними вставляется DivStr только если
они обе непустые}
function JoinStr(const S1, DivStr, S2: string): string;
{Возвращает строку S, если она непустая или DefValue в противном случае}
function IfEmpty(const S, DefValue: string): string;
{Возвращает строку DefValue, если значение S равно Value, иначе возвращает S,
пригождаются вариации и для Integer, др. типов}
function IfEqual(const S, Value, DefValue: string): string;

{Пример}
ShowMessage(JoinStr('Ошибка - нет прав подписи для документа, валюта: ' +
  IfEmpty(вызов_считывающий_значение_кода_валюты, 'РУБ'), ', ',
  JoinStr(AddPrefix('БИК: ', вызов_считывающий_значение_поля_БИК), ', ',
  AddPrefix('корсчет: ', вызов_считывающий_значение_поля_корсчета))));


Еще примеры удобных утилитарных функций: GetMin, GetMax, MinMax; AddPathSlash, DelPathSlash; BufToStr, StrToBuf; FileToStr, StrToFile; StreamToStr, StrToStream...

Или, скажем, вначале думал о более-менее универсальном объекте логирования, которым бы везде пользовался, объект сделал (с кэшированием дескриптора файла), но для отладочного логирования, интегрированного во многих местах кода (да и почти везде) пользуюсь простой функцией W с вариантным открытым массивом аргументов (ностальгия по WriteLn), которая в зависимости от глобальной настройки пишет в файл и/или на консоль и/или выводит сообщения на экран (с выбором - продолжить, продолжить, отключив вывод сообщений на экран насовсем/на 25 сообщений, выйти из программы) и/или может взаимодействовать с другим приложением с более сложной логикой фильтрации/отображения логируемой инфы.
В файловые логи пишем дату и время, миллисекунды с прошлого вызова W, а далее через Tab параметры W, кодируя их как строки С++ для однозначного обратного разбора (при других глоб.настройках можно не кодируя и слитно), имя файлового лога - по умолчанию во временном каталоге имя библиотеки, год и месяц точка log, можно настроить и по дням или по годам, по классам, см далее. Первый параметр открытого массива функции W определяет класс записи, например, 'WAPI' - вызовы Windows API, 'SQL' - SQL-запрос, 'ERR' - генерация исключения и т.п. Для исключений, правда, приходится описывать функции их генерации, например, общая:

Код

function ExceptionCreate(const Msg: string;
ExceptionClass: EExceptionClass): Exception;
begin
  Result := ExceptionClass.Create(Msg);
  {$IFNDEF NODEBUG} {$IFNDEF NODEBUG_ERR}
  if IsDebug('ERR') then W(['ERR', 'ExceptionCreate', Result.ClassName,
    Result.Message]);
  {$ENDIF} {$ENDIF}
end;


(здесь функция IsDebug('ERR') возвращает True, если включен режим записи в лог класс записи 'ERR'; может быть задано писать в лог несколько классов записи, перечисляются через пробелы, или задан режим '*' - писать всё; директивы компилятора позволяют исключить из кода программы отладочное логирование все целиком или данного класса ERR; при первом обращении к IsDebug функция читает типы записи в лог из специального параметра командной строки; вот в целом такой подход к логированию, которого хватает более-менее везде, получился; возможно, еще нужно будет добавить в глобальные настройки количество последних файлов лога, которые хранить, удаляя более старые)
PM MAIL WWW   Вверх
vstepanov78
Дата 18.11.2010, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 10.1.2006
Где: Москва

Репутация: нет
Всего: нет



Пример еще универсализации.

Вот, допустим, нужно работать с версиями. Разбирать, собирать, сравнивать. Получаются примерно такие функции:

Код

// строку – в версию
function StrToVer(const S: string): TProductVer;

// сравнение версий, Ver1 > Ver2 – результат > 0, Ver1 < Ver2 – результат < 0, Ver1 = Ver2 – результат = 0
function CompareVer(const Ver1, Ver2: TProductVer): Integer;

// версию - в строку, при CommaDiv использовать разделитель - запятую, как в inf-файлах, MinNumCount задает минимальное количество выводимых чисел, например, можно задать 2
function VerToStr(const Ver: TProductVer; CommaDiv: Boolean; MinNumCount: Integer): string;

// формирование структуры о версии
function ProductVer(const Prefix: string; MajorVersion, MinorVersion, Release, Build: Integer; const Postfix, Text: string): TProductVer;

// Пример:
If CompareVer(  StrToVer(строка_с_версией), ProductVer('', 3, 6, 0, 0, '', '')  ) >= 0 then
  {Версия в "строка_с_версией" больше или равна 3.6};
  
// Структура с информацией о версии
type
  TProductVer = record
    Prefix: string;        {текстовый префикс}
    MajorVersion: Integer; {основная версия}
    MinorVersion: Integer; {подверсия}
    Release: Integer;      {выпуск}
    Build: Integer;        {сборка}
    Postfix: string;       {постфикс}
    Text: string;          {версия в виде текста при особенном написании}
  end;


Т.е. идея и в организации некой совместной работы над подобными функциями - достаточно простыми (нетяжеловесными), но и более-менее универсальными - применимыми почти во всех случаях, когда "рядовому программисту") нужно работать с подобной темой. Что-то вроде wiki-исходников.

Список тем нужно будет расписать...
утилитарные функции по работе: с различными базовыми типами, потоками, файлами, ini, реестром, многопоточнотью, исключенями, языками, диалогами, БД, интернетом, скриптами, процессами, сжатием, оборудованием, графикой, финансовые, криптографические.
PM MAIL WWW   Вверх
cat512
Дата 19.11.2010, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 438
Регистрация: 20.3.2007

Репутация: 7
Всего: 15



Большинство вещей уже реализованно в VCL. Надо просто разбираться с исходным кодом, тогда отпадёт необходимость написания типа 
Цитата

{Классика жанра - при IfCase равном True вернуть ValueIfTrue,
иначе ValueIfFalse; пригождаются и вариации этой функции для Integer
и др. типов}

Например аналог вышеописанной функции уже сидит в модуле Math (емнип), помойму наз. IfThen
По поводу, логов, не надо выдумывать ВЕЛОСИПЕД, потому как на практике, получится не лучше существующих. Например есть готовый лог, портированный Keith Wood из Джавки. Очень мощный, потокобезопасный лог! Надо с ним только разобраться и будет вам счастье smile

Это сообщение отредактировал(а) cat512 - 19.11.2010, 18:38
PM MAIL   Вверх
imageman
Дата 29.11.2010, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 30.9.2004

Репутация: 1
Всего: 1



 тогда давайте писать какие функции из каких библиотек используете почти во всех программах

к примеру есть стандартная отладочная функция  assert( f(x)=1,'Ой, f(x)<>1'); 
удобна тем, что можно быстро отключить проверки в релизе и тем, что выдает номер строки 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1135 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.