Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2005.02.13;
Скачать: [xml.tar.bz2];

Вниз

Какие правильнее писать программы - быстрые или устойчивые?   Найти похожие ветки 

 
lipskiy ©   (2005-01-25 11:53) [0]

Если производить все возможные проверки перед всеми операциями, которые потенциально могут быть источником исключения, то программа начинает работать медленнее, но не ошибается. Если не рассчитывать на нестандартные ситуации и оставить только проверки рабочих ситуаций, то программа работает быстрее, но если сильно продвинутый юзер начинает действовать "нестандартно" (то есть не так, как предполагает программист :), то возникают исключения.
И как правильнее?

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

Допустим, в моих библиотеках, которые используются для всех проектов, есть три универсальные функции:

Есть функция StrToInt, которая возвращает 0 если строка не цифровая:
function StrToInt(const s:string): integer;
begin
 if not DigitalString(s) then Result:= 0 else Result:= SysUtils.StrToInt(s);
end;


Есть также отдельно написанная функция DigitalString, которая проверяет все ли символы в строке цифровые.

И есть еще некая функция, примерно такая:
procedure SomeFunc(s:string):boolean;
 var x:integer;
begin
if not DigitalString(s) then
begin
 ...
 // например выдать сообщение и выйти
 ...
end
 else
begin
 ... // что-то вычислить
 x:= StrToInt(s);
 ... // еще что-то вычислить
end;
end;


Каждая из трех функций использутся в проектах самостоятельно.
Но SomeFunc использует StrToInt и получается, что внутри SomeFunc дважды вызывается проверка DigitalString, проверяя одно и то же. Причем использовать саму StrToInt для проверки цифровая ли строка нельзя, поскольку когда она возвращает ноль это может значить и то, что строка была не цифровая, и то, что строка была "0".
И как избегать таких бессмысленных повторных проверок в коде?
(пример условный, не из реальной ситуации, придумал для наглядности, но смысл такой).


 
Ega23 ©   (2005-01-25 11:56) [1]

Есть функция StrToInt, которая возвращает 0 если строка не цифровая:

Нафига? Есть же Val


 
}|{yk ©   (2005-01-25 11:58) [2]

Насколько я знаю, можно вообще отключить обработку приложением ошибок и по необходимости получать исключения с помощью GetLastOSError.


 
kirasukii   (2005-01-25 12:06) [3]

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

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/structured_exception_handling.asp


 
Игорь Шевченко ©   (2005-01-25 12:08) [4]


> Какие правильнее писать программы - быстрые или устойчивые?
>


Никаких. Программы надо скачивать с варезных сайтов, а не писать.


 
Думкин ©   (2005-01-25 12:10) [5]

Типа казнить чиста нельзя памиловать.


 
kirasukii   (2005-01-25 12:11) [6]

Игорь Шевченко
>Никаких. Программы надо скачивать с варезных сайтов, а не писать.
Чему молодежь учите???


 
lipskiy ©   (2005-01-25 12:13) [7]


> Нафига? Есть же Val

Блин, я же ясно написал - пример УСЛОВНЫЙ. Я про идеологию спрашиваю, а не про конкретику.


> Насколько я знаю, можно вообще отключить обработку приложением
> ошибок и по необходимости получать исключения с помощью
> GetLastOSError.

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


> Никаких. Программы надо скачивать с варезных сайтов, а не
> писать.

Так я так и делаю! :) Пишу только если такого еще нет :))


 
Jeer ©   (2005-01-25 12:14) [8]

Как правильнее ездить - по правилам или без ?

Оцените степень риска и принимайте правильное решение.


 
Johnmen ©   (2005-01-25 12:18) [9]

>Jeer ©   (25.01.05 12:14) [8]
>Как правильнее ездить - по правилам или без ?

Не, не так. Вот так
Как правильнее ездить - по правилам или по дорогам ?


 
kaif ©   (2005-01-25 12:18) [10]

Мое ИМХО:

 Во-первых, что касается конкретно StrToInt существует функция StrToIntDef, позволяющая в случае "ошибочной строки на входе" обойтись без генерации исключительной ситуации и подставить некое значение по умолчанию (пусть тот же 0).

 Во-вторых можно перехватывать и подавлять исключительные ситуации в конструкции
 try
 except
   //если здесь нет raise, то исключение "подавлено"
   //если здесь написано On E: <класс исключительных ситуаций>
   //можно вставить свои обработчики на каждый класс
 end;

 В-третьих можно перехватить все исключительные ситуации на уровне события Application.OnException (кажется так оно называется, не помню). Можно для этой цели использовать компонент TApplicationEvents.

 В-четвертых если "проверка" происходит при вводе пользователем строки, то "предварительную проверку" можно делать, и это не может привести ни к какому ощтимому "замедлению", если учесть, что современные процессоры способны делать сотни миллионов операций в секунду. Но делать массы "предварительных проверок" - плохой стиль программирования в Object Pascal, так как
 а) такой подход делает программу менее устойчивой "к развитию" (не всегда помнишь, какие проверки делаются, а какие - нет, если они не централизованы)
 б) кучи if-ов плохо обозримы и чреваты скрытыми логическими ошибками
 в) существует в Object Pasacl мощная система классов исключительных ситуаций, наследников класса Exception и EAbort, которые можно к тому же самому развивать и почему бы этим всем не воспользоваться?
 г) централизованная обработка исключительных ситуаций упрощает локализацию программ (перевод на другие языки), так как "сообщения об ошибках" не разбросаны по тексту, а помещены в какое-то предсказуемое место, например, в файлы ресурсов или файлы с директивой resourcestring.


 
Игорь Шевченко ©   (2005-01-25 12:18) [11]

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


 
Ega23 ©   (2005-01-25 12:22) [12]

Блин, я же ясно написал - пример УСЛОВНЫЙ. Я про идеологию спрашиваю, а не про конкретику.

Идеология такова:

type
type EGPException = Class(Exception);

try

except
on E:Exception do
 raise EGPException.Create(E.message+"; Исключение в классе таком-то, методе таком-то, месте таком-то");
end;

И отписывать в файл:

procedure TFMain.AppEvents1Exception(Sender: TObject; E: Exception);
var
fn:String;
begin
 fn:=ChangeFileExt(ExtractFileName(ParamStr(0)),".log");
 WriteLog(e.message,sessinfo,fn);
end;


 
kaif ©   (2005-01-25 12:23) [13]

Игорь Шевченко ©   (25.01.05 12:18) [11]
По сабжу: скорость и размер программы в общем случае являются последними критериями, которые следует стараться оптимизировать.


 Я не согласен. Конечная скорость работы программы для меня - главный приоритет. Но я работаю с базами данных, так что для меня скорость программы это в первую очередь правильное построение базы и  SQL-запросов. А скорость работы кода экзешника приложения в большинстве случаев действительно не является фактором, который бы влиял на "конечную скорость" при современных скоростях процессовор, возможно Вы это имеете в виду. Тогда - Вы правы.


 
lipskiy ©   (2005-01-25 12:24) [14]

так что, хороший тон - весь код обрамлять конструкцией try except?


 
Ega23 ©   (2005-01-25 12:27) [15]

Правда, когда этот эксепшн возник где-то в глубоких недрах программы, бывает, что пройдёт штук 10 raise, пока до Application.OnException доберётся. в этом случае стока сообщения может быть весьма больших размеров.
С другой стороны, ты всегда по логу сможешь историю ошибки проследить.


 
lipskiy ©   (2005-01-25 12:27) [16]

кстати, насчет скорости. Если в качестве такой проверки неправильно (нерационально) используется FileExists, то скорость работы замедляется сильно, даже на глаз, и это уже важно.


 
}|{yk ©   (2005-01-25 12:27) [17]

У меня есть такой вопрос - а есть ли инструменты, позволяющие при генерации ошибки показывать также строку в программе , которая вызваля ошибку - ну как в VC++? Не дебаггер, конечно.


 
Игорь Шевченко ©   (2005-01-25 12:28) [18]

kaif ©   (25.01.05 12:23) [13]

Да, Ашот, я имею в виду именно скорость современных процессоров и объемы современных дисков. Увеличение скорости работы за счет правильной организации базы данных или правильных запросов есть, на мой взгляд, не оптимизация, но смена алгоритма. Каковой алгоритм безусловно следует менять, если он дает прирост производительности. Я же возражал против "а этот кусок я напишу на асме - так быстрее будет" как подхода к оптимизации в целом.

С уважением,


 
Ega23 ©   (2005-01-25 12:31) [19]

2 lipskiy ©   (25.01.05 12:27) [16]
Если в качестве такой проверки неправильно (нерационально) используется FileExists, то скорость работы замедляется сильно, даже на глаз

Ну, если тебя это настолько сильно напрягает (хотя у меня большие сомнения, насчёт "на глаз"), то можешь свой FileExists написать, ничего сложного в этом нету:

function FileAge(const FileName: string): Integer;
var
 Handle: THandle;
 FindData: TWin32FindData;
 LocalFileTime: TFileTime;
begin
 Handle := FindFirstFile(PChar(FileName), FindData);
 if Handle <> INVALID_HANDLE_VALUE then
 begin
   Windows.FindClose(Handle);
   if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
   begin
     FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
     if FileTimeToDosDateTime(LocalFileTime, LongRec(Result).Hi,
       LongRec(Result).Lo) then Exit;
   end;
 end;
 Result := -1;
end;

function FileExists(const FileName: string): Boolean;
begin
 Result := FileAge(FileName) <> -1;
end;


 
Ega23 ©   (2005-01-25 12:34) [20]

2 }|{yk ©   (25.01.05 12:27) [17]
У меня есть такой вопрос - а есть ли инструменты, позволяющие при генерации ошибки показывать также строку в программе , которая вызваля ошибку - ну как в VC++? Не дебаггер, конечно.

Я уже как-то раз спрашивал - хотелось некую "автоматизацию" обработчика исключений сделать. Теоретически, можно через RTTI названия published-методов автоматом включать. А вобщем случае - увы.

Кстати, насколько мне известно, в с++ номера строк только для checked build будут выдаваться. При финальной линковке такие вещи не включаются...


 
TUser ©   (2005-01-25 12:44) [21]

Эту ветку обязательно надо сохранить, ради поста [4].

По сабжу. Описанное замедление скорости, ИМХО, не существенно. Если для программы критична скорость, - то надо думать в направлении принципиального переделывания алгоритма, а не улучшения подобных мелочей.
Например, однажды у меня в программе сортировалось довольно много строк. Конечно, тормозило это все дело немерено. Но для того чтобы все это дело существенно ускорить было, конечно, бесполезно написать где-нибудь with MyStringList do, и далее обращаться к строкам через Strings[]. Понятно, with даст некоторое ускорение, т.к. адрес объекта будет вычислен только один раз и запомнен, но такое ускорение будет незначительным, так что разгонять программы подобными вещами бессмысленно. Возможно, спасло бы ситуацию переписывание QuickSort"а без рекурсии (через собственный стек). Реально, я сделал немного по-другому - переделал алгоритм заполнения списка, так что он получался сразу отсортированным. Но в любом слечае, если скорость несущественна, но не надо огорчатся из-за мелких тормозов, а если скорость критична, - то убираение мелких тормозов - это не тот метод, которым разгоняют программы.


 
TUser ©   (2005-01-25 12:48) [22]


> Я уже как-то раз спрашивал - хотелось некую "автоматизацию"
> обработчика исключений сделать.

JclDebug.pas ?


 
kaif ©   (2005-01-25 13:09) [23]


TUser ©   (25.01.05 12:44) [21]
... Но в любом случае, если скорость несущественна, но не надо огорчатся из-за мелких тормозов, а если скорость критична, - то убираение мелких тормозов - это не тот метод, которым разгоняют программы.


Хорошо сказано.


 
KSergey ©   (2005-01-25 14:07) [24]

> [12] Ega23 ©   (25.01.05 12:22)

Да это же с тоски сдохнешь каждый метод каждого класса в try/exception оборачивать!
Может действительно проще решить проблему в одном месте, как уже упомянул [22] TUser ©   (25.01.05 12:48)?


 
Ega23 ©   (2005-01-25 14:29) [25]

2 KSergey ©   (25.01.05 14:07) [24]

Ну, на все методы я, конечно, такого не пишу... Но на какие-то критические - обязательно.


 
Prohodil Mimo ©   (2005-01-25 15:43) [26]

надо писать быстрые и в то же время устойчивые :о)


 
Rem ©   (2005-01-25 15:43) [27]

>>У меня есть такой вопрос - а есть ли инструменты, позволяющие при генерации ошибки показывать также строку в программе , которая вызваля ошибку - ну как в VC++? Не дебаггер, конечно.

ASSERT(<Condition>, {<Message>});

По теме:
procedure SomeFunc(s:string):boolean;
var x:integer;
begin
if not DigitalString(s) then
begin
...
// например выдать сообщение и выйти
...
end
else
begin
... // что-то вычислить
x:= SysUtils.StrToInt(s);
... // еще что-то вычислить
end;
end;


 
Rem ©   (2005-01-25 15:43) [28]

>>У меня есть такой вопрос - а есть ли инструменты, позволяющие при генерации ошибки показывать также строку в программе , которая вызваля ошибку - ну как в VC++? Не дебаггер, конечно.

ASSERT(<Condition>, {<Message>});

По теме:
procedure SomeFunc(s:string):boolean;
var x:integer;
begin
if not DigitalString(s) then
begin
...
// например выдать сообщение и выйти
...
end
else
begin
... // что-то вычислить
x:= SysUtils.StrToInt(s);
... // еще что-то вычислить
end;
end;



Страницы: 1 вся ветка

Форум: "Потрепаться";
Текущий архив: 2005.02.13;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.039 c
14-1106314154
Kerk
2005-01-21 16:29
2005.02.13
реальная история одной знакомой.


3-1105621655
SOS
2005-01-13 16:07
2005.02.13
работа в базе


14-1106591407
Гарри Поттер
2005-01-24 21:30
2005.02.13
вопрос по ХР


3-1106045419
Виктор Д.
2005-01-18 13:50
2005.02.13
Таблицы Paradox


1-1106918647
Drakosha
2005-01-28 16:24
2005.02.13
Помогите выявить повторения....





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский