Последнее время я не программирую, а рaзгpебаю зaвалы которые оставили до меня покoления программистов. Чтобы внести минимальное декоративное изменение требуется исправить несколько модулей и потратить несопоставимую по сложности работу по выискиванию всех мест, в которые надо внести изменения.
Дело в том, что тем методы, которые допустимы в примерах, олимпиадах и лабах по программированию, совершенно неприемлемы при создании крупных и долгоживущих прикладных программ.
Предлагаю в этой теме публиковать примеры, как не надо программировать на Delphi, что бы потом не было мучительно больно от встречи с теми, кто исправлял твой код.
Всего в теме 421 сообщение
Добавить свое сообщение
Отслеживать это обсуждение 
№ 231 21-05-2008 01:31 |  |
Ответ на »сообщение 230« (Mirage)
___________________________
Поэтому, честно говоря, вообще не вижу смысла использовать какие-либо другие схемы обработки ошибок. Они заведомо хуже. Почему-то мне это не очевидно, но спорить не буду, что бы не разводить флейм.
P.S. Может напишите статью на эту тему с примером реализации? Было бы интересно.
№ 230 20-05-2008 23:47 |  |
Ответ на »сообщение 227« (Cepгей Poщин)
___________________________
Похоже слишком частные случаи начали рассматривать, в каких-то случаях одно лучше, в каких-то другое. В то время как философия направлена на постановку и рациональное, или иррациональное разрешение наиболее общих вопросов.
Сама возможность решать на месте как именно обрабатывать ошибку - весьма общий вопрос. Я бы даже сказал ответ.:)
Конкретное решение при конкретной ошибке - частный.
Причем понятно, что в более-менее сложной программе эти решения будут разными - от игнорирования до исключения.
Поэтому, честно говоря, вообще не вижу смысла использовать какие-либо другие схемы обработки ошибок. Они заведомо хуже.
№ 229 20-05-2008 13:13 |  |
Ответ на »сообщение 218« (Ins)
___________________________
Забыл дописать.
Если кто сильно хочет Exception в обработчике AppLog можно и Exception возбудить.
Если Exception не всегда нужен можно проверить число ошибок в AppLog до и после вызова некоего метода и тогда их все кучей показать вместе с Exception.
Можно и наоборот, отключить временно AppLog вызвать метод и включить его снова. Тогда можно ошибки тихо пропустить.
За одним и журнал ошибок в программе появляется.
№ 228 20-05-2008 12:56 |  |
Ответ на »сообщение 218« (Ins)
___________________________
Что лучше, уведомлять о том, что что-то пошло не так, в виде возвращаемого значения или в виде исключения?
Десять лет думал что делать :) Какое из зол выбирать?
Для своего проекта сделал следующее:
Создал глобальный объект (назвал его AppLog) в нем сделал несколько методов - AddError(const Msg: string); AddWarning ...
Объект AppLog имеет события.
Если при загрузке проекта программа не находит файл, таблицу, поле ... продолжает грузить то, что может, а внизу, в окошке, напоминающем Message View в Delphi отображается список ошибок, предупреждений и т. п. Он также автоматически выскакивает, когда появляются новые сообщения, которых пользователь еще не видел.
Если программа может работать дальше пусть работает.
Иначе пользователь может застрелиться, когда программа будет вылетать с ошибкой из-за каждого отсутствующего файла. И если будет молчать тоже плохо. А если будет спрашивать, да переспрашивать пользователя каждый раз, что ей делать когда файл не нашелся - пользователь программиста застрелит.
№ 227 20-05-2008 05:36 |  |
Ответ на »сообщение 226« (Mirage)
___________________________
Кстати, философский вопрос...
Лучше иметь возможность решать это в процессе Похоже слишком частные случаи начали рассматривать, в каких-то случаях одно лучше, в каких-то другое. В то время как философия направлена на постановку и рациональное, или иррациональное разрешение наиболее общих вопросов.
№ 226 20-05-2008 05:02 |  |
Ответ на »сообщение 218« (Ins)
___________________________
Кстати, философский вопрос :) Что лучше, уведомлять о том, что что-то пошло не так, в виде возвращаемого значения или в виде исключения?
Лучше иметь возможность решать это в процессе.
Я использую функцию-делегат. Что-то подобное предложил DRON.
TErrorHandler = function(const Error: TError): Boolean of object;
TError - класс, описывающий ошибку, хотя можно и номер ошибки передавать.
Если функция вернет True, то подпрограмма, где возникла ошибка, попытается повторить операцию.
По умолчанию она просто выводит ошибку в лог, но если установить свой обработчик, то он может выкинуть исключение, или попросить пользователя освободить немного места на диске.;)
№ 225 20-05-2008 03:25 |  |
Ответ на »сообщение 224« (Cepгей Poщин)
___________________________
Использование параметрических (или все же параметризованных?) запросов имеет и еще одни плюс. Нет, даже два.
Во-первых, на подготовку запроса тратится некоторое время. Параметрический же запрос готовится один раз. Так что при частой смене тех же условий отбора 9параметрический запрос дает существуенный выигрыш).
Второй плюс является идеологическим. Если каждый раз составлять текст запроса с нуля, то это способстует (или, по крайней мере, не препятствует расхлябанности. Шаман чукотский: о чем вижу, о том пою. Если же используются параметрические запросы, то возникает невольное желание минимизировать их количество. В идеале -- создание всех запросов в design-time. А это приводит к проработке структуры БД и логики реализации запросов, что положительно сказывается на результате.
№ 224 20-05-2008 02:32 |  |
По поводу не использования bind-переменных (параметров запроса).
Странно, что еще ни кто не писал здесь (или я ошибаюсь) о порочной практике использования таких конструкций: SQL.Text := 'SELECT * FROM Table WHERE FieldDate > ' + StrToDateTime(Now) + ' and ' + 'Id = ' + inttostr(Id);
Для формирования строк лучше, конечно, воспользоваться функцией Format, но не об этом сейчас речь.
1. Задайте себе вопрос, на всех ли серверах формат даты будет одинаков. Если формат даты сервера не соответствует формату даты клиентского приложения, то в лучшем случае оно не будет работать, а в худшем — добавит записи в которых месяц перепутан с днем безо всяких ошибок, т.е. испортит БД.
Потом появляются вопросы типа. Как определить формат даты на сервере? Почему кода ввожу в поле Фамилия, "Д'Артаньян", появляется ошибка?
2. Не знаю точно как в других серверах, но в Oracle неиспользование bind-переменных радикально замедляет работу.
Вот, примерно, как надо изменить запрос:
SQL.Text := 'SELECT * FROM Table WHERE FieldDate > :DateNow and Id = :Id';
№ 223 19-05-2008 09:44 |  |
Ответ на »сообщение 222« (Денис Зайцев)
___________________________
>>> Ну, кстати, я бы тут встал на защиту такой практики, как принудительная инициализация Result и var-переменных в начале функции.
В принципе, идея нормальная, но не абсолютная. Примеры, когда инициализация переменных не обязательна.
function CalcSubs(const SubStr,Str : String) : Integer;
var
P : Integer;
begin
Result:=0;
P:=Pos(SubStr,Str);
if P = 0 then Exit;
repeat
Inc(Result);
P:=PosEx(SubStr,Str,P+Length(SubStr));
until P = 0;
end;
Еще вариант обсуждался здесь »сообщение 366 в теме №356 на БП«
Я для себя взял за правило сначала все инициализировать, а потом смотреть на логику программы и избыточную инициализацию выбрасывать. Осмысленно выбрасывать, а не наугад. То есть если есть сомнения, то инициализация остается. Это дает опредеелнные гарантии, что все нужное будет инициализировано, но не будет загромождения лишних операторов присваивания.
№ 222 19-05-2008 09:27 |  |
Ответ на »сообщение 219« (Geo)
___________________________
Впрочем, это пока только первое приближение. Возможно, еще все несколько раз поменяется.
Ну, кстати, я бы тут встал на защиту такой практики, как принудительная инициализация Result и var-переменных в начале функции. Именно потому, что "еще все несколько раз поменяется". Например, было:
Result:=false;
List:=TStringList.Create;
try
List.LoadFromFile(FileName);
Result:=true;
finally
List.Free;
end;
А стало:
Result:=false;
if not FileExists(FileName)
then Exit;
List:=TStringList.Create;
Во втором случае присвоение Result пригодилось. И хотя в первом случае нет, но такой стиль программирования, когда Result всегда вначале принудительно инициализируется, я приветствую.
Конечно, если это входит в противоречие с требованием отсутствия Warning'ов, можно задуматься...
Добавить свое сообщение
Отслеживать это обсуждение 
Дополнительная навигация: |
|