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

Вниз

---|Ветка была без названия|---   Найти похожие ветки 

 
VEG   (2002-08-10 23:18) [0]

Безопасный код: Безопасность - прежде всего! Лучше заранее предохраниться от проблем!

Интересное название? То-то же! Оказывается, что есть и такой тип кода! Вы не представляете себе, до какой степени он может быть безопасным! Оказывается, чтобы от строки убрать три последних символа, нужно писать:
var
L:Integer;
S:String;
begin
L:=Length(S);
Inc(L,-3);
If L<0 then L:=0;
SetLength(S,L);
end;
Вместо более привычной строчки: If Length(S)>2 then Delete(S,Length(S)-2,3) else S:="";, т.к. первый вариант является безопасным, а второй нет! Почему? Я и сам не знаю! Вроде делают эти отрывки кода абсолютно одинаковую вещь! Единственное отличие этих отрывков кода, которое я нашел - это количество переменных и строчек кода! В безопасном варианте требуется лишняя переменная и 4 строчки программного кода, а в небезопасном ни одной лишней переменной и одна строчка программного кода!
Обо всем этом я узнал из разговора в чате с Anatoly Podgoretsky.
К чему это я все пишу? Ответ прост: Я хочу попросить объяснения, почему первый отрывок кода явяется безопасным, а второй - нет.
Собственно все!


 
VEG   (2002-08-10 23:59) [1]

Вот еще один безопасный код:
if Length(s)>2 then SetLength(s,Length(s)-3) else S:="";


 
TTCustomDelphiMaster   (2002-08-11 08:57) [2]

VEG © (10.08.02 23:18)
По моему все три кода являются безопасными, вот только код Anatoly Podgoretsky быстрее, меньше памяти занимает и менее понятный.

PS: Оптимизация if Length(s)>3 then SetLength(s,Length(s)-3) else S:="";


 
Anatoly Podgoretsky   (2002-08-11 10:02) [3]

VEG © (10.08.02 23:18)
Оба варианта безопасны, так как проводится проверка на допустимость, но ты передернул карты во втором случае. Ведь речь шла о коде Delete(S,Length(S)-2,3) без проверки If Length(S)>2
Вот такоей код не является безопасным.

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

В разговоре в чате, кроме того стояла речь об L:=Length(S)-3; вместо двух строк, как у тебя.

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


 
Anatoly Podgoretsky   (2002-08-11 10:26) [4]

TTCustomDelphiMaster © (11.08.02 08:57)
Это не мой код!
И с Delete не мой код!
Да и не в строчках я обычно считаю, а в операциях
Два присваивание, одно сравнение и один вызов процедуры.
Речь в чате зашла не об этом коде, а конкретно о коде VEG по работе с реестром, где на весь код ни одной проверки на допустимость, данный код был только демонстрацией принципа написания безопасных программ, так к слову, при том со ссылкой на ветку откуда это взято и на указание кто обратил внимание на потенциальную ошибку в Delete, это Дигитман, если делать это без проверок на допустимость значений.

Суть теории такова, зачем писать код с ошибками, что бы потом тратить время на отладку, лучше сразу писать код без ошибки.
Если есть параметры их надо проверять, если используются ресурсы, то их надо защищать с помощью try finally/try except блоков. Программа проверять не только на ограниченном наборе данных, но и на границных условия, на недопустимых данных.
В теории написания безопасного кода есть много различных приемов, даже следование части из них резко повышает надежность программ, меньше возможность, что в процессе эксплуатации, откуда то вылезет подлянка.


 
Юрий Зотов   (2002-08-11 10:32) [5]

> Оказывается, что есть и такой тип кода!

Совершенно верно, такой тип кода есть. Точнее, не тип кода, а стиль программирования. Вот простой, но наглядный пример:

Вариант 1:
with TMyObject.Create do
begin
...
Free
end;

Вариант 2:
with TMyObject.Create do
try
...
finally
Free
end;

Комментарии, думаю, не требуются. То же самое относится и к другим "парным" операциям (GetMem-FreeMem, BeginUpdate-EndUpdate, GetDC-ReleaseDC, SelectObject, OnChange:=nil - OnChange:=OnChangeHandler и т.д.).

Еще пример.

Вариант 1:
if CreateProcess(..., PI) then
begin
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, ...);
... // что-то делаем
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;

Вариант 2:
if CreateProcess(..., PI) then
begin
CloseHandle(PI.hThread);
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, ...);
CloseHandle(PI.hProcess);
... // что-то делаем
end;

В первом варианте системные ресурсы остаются захваченными даже когда они реально не нужны, а во втором освобождаются сразу же, как только становятся ненужными. Казалось бы - подумаешь, каких-то пара хэндлов, мелочь. Действительно, мелочь. Но только до тех пор, пока нам не придет в голову что-то вроде использования небезопасного кода (не этого, но подобного ему) внутри цикла. И тогда появляется реальный шанс нарваться на нехватку ресурсов, а потом писать в форумах, какая же все-таки масдай эта Win9x.

Еще пример, уже на другую тему (увы, из собственной практики).

Вариант 1:
N := 0;
for i := 1 to Length(StringList.Text) do
if StringList.Text[i] = "A" then N := N + 1;

Вариант 2:
S := StringList.Text;
N := 0;
for i := 1 to Length(S) do
if S[i] = "A" then Inc(N);

Второй вариант кэширует свойство Text и использует Inc, а потому выполняется во много раз быстрее первого (в основном, за счет кэширования, конечно). Кстати, аналогичный прием в модуле VBA (кэширование свойств объектов - Workbook и пр.) как-то позволил ускорить работу макросов этого модуля в несколько десятков (!!!) раз (тоже реальный случай из практики).

Еще пример, с виду совершенно невинный.

procedure TMyCollection.Update(Item: TCollectionItem);
begin
... // что-то делаем
end;

Здесь нет вызова inherited. Вроде бы, он и не нужен - в классе-предке метод Update пустой, там только begin-end. Однако представьте, что в какой-то версии Delphi появились изменения и этот метод стал непустым. Все, большой привет - начиная с этого момента наш тщательно отлаженный и безукоризненно работавший код может начать глючить. И мы будем очень долго ломать голову над причиной такого странного явления. А если бы сразу написали inherited - не имели бы никаких проблем.

Еще пример - гашение потенциально возможной ошибки (с помошью try-except, или if или еще как-то - неважно). В итоге программа, вроде бы, работает, но работает неверно (кстати, это еще надо заметить, и чем скорее - тем лучше, потому что последствия могут быть катастрофическими). А все потому, что программист поленился обработать ошибку как следует и просто замаскировал ее. А она, конечно, никуда не исчезла, ее просто не видно.

===== см. продолжение =====


 
Юрий Зотов   (2002-08-11 10:46) [6]

===== продолжение =====

Еще примерчик, в Вашего разрешения.

Вариант 1:
if <условие1> and <условие2> then...

Вариант 2:
if <условие1> then
if <условие2> then...

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

И подобных примеров "узких мест" можно привести очень много. Это практически все операции, явно или неявно связанные с выделением памяти и других ресурсов. Это скорость выполнения операций. Это оптимизация циклов (вынесение инвариантов и пр.), да и не только циклов (даже порядок следования ветвей в операторе case тоже имеет значение - желательно упорядочивать их по возрастанию параметра, так быстрее). Это пренебрежение особенностями машинной арифметики (особенно, с плавающей точкой). Это отключение проверок выхода за диапазон (хотя бы на этапе отладки программы). Это использование недокументированных возможностей или деталей внутренней реализации. Это закладка на умалчиваемые опции компилятора. Это и закладка на порядок следования модулей в uses (редкий, но очень тяжело локализуемый вид ошибок). Это пренебрежение хинтами и предупреждениями компилятора (лично сам видел, как человек забыл написать override в объявлении деструктора, а на сообщение компилятора наплевал - утечка памяти почти гарантирована).

Это... ну, в общем, это практически вся наша программа.

Конечно, абсолютно безопасного кода не существует в принципе, но в нашей власти сделать его более безопасным. Причем НАМНОГО более. Другое дело, что не следует становиться параноиком и втыкать проверки где надо и не надо.

Поэтому совет всем начинающим программистам - с самого начала старайтесь вырабатывать у себя именно грамотный, безопасный стиль. Он должен войти в привычку, стать просто стереотипом. И тогда Вы никогда не напишете begin вместо try (см. первый пример) - автопилот не позволит.

А как его вырабатывать? Очень просто - внимательность и аккуратность. Безопасный стиль, как это ни странно, начинается с самых простых вещей - форматирование текста, смысловые имена, соблюдение регистров и т.д. Ну и, само собой, надо думать буквально над каждой скобкой.

В общем, надо просто приучить себя к аккуратности. Без этого точно ничего не получится, а остальное придет с опытом.

Sorry за длинный постинг. Единственным его оправданием может служить то, что он, возможно, окажется кому-то полезным. :o)


 
Anatoly Podgoretsky   (2002-08-11 11:15) [7]

Спасибо Юрий Зотов, как всегда развернуто.
В чате речь зашла про конкретный код, строк 10 работы с реесром, аргумент был такой да все работает!
А к примеру с inherited он связан с тем недавним обсуждением, про удаление (усечение строки) на три символа с конца, там был аргумент про различные версии компилятора, что нельзя привязываться к внутренней реализации той или другой версии компилятра, проблемы неизбежны. Идя на встречу недобросовестным программистам Борланд изменил реализацию функции Delete теперь она работает следующим образом

If index is larger than the length of the S or less than 1, no characters are deleted.

В версиях 5 и ниже

If Index is larger than the length of S, no characters are deleted.

Большая разница, но к тому по словам Дигитман и это не работает как нужно, не происходит удаления символов если длина строки меньше Index, а удалить все равно требовалось, здесь они внесли только зашиту от выхода индекса за пределы. Вариант с SetLength или такой же, для Delete, с проверкой и корректировкой индекса работает нормально и хорошо лемонстрирует принципы написания безопасного кода.


 
VEG   (2002-08-11 12:52) [8]

Все! Я разобрался!
Все дело в скорости!!!
Для проверки я использовал следующие отрывки кода:
Для первого безопасного:
var
L:Integer;
S:String;
Time:Integer;
FTD:Integer;
begin
Time:=GetTickCount;
For FTD:=1 to 1000000 do
begin
S:="ABC";
L:=Length(S);
Inc(L,-3);
If L<0 then L:=0;
SetLength(S,L);
end;
Time:=GetTickCount-Time;
Label1.Caption:=IntToStr(Time);


Для второго безопасного:
var
S:String;
Time:Integer;
FTD:Integer;
begin
Time:=GetTickCount;
For FTD:=1 to 1000000 do
begin
S:="ABC";
If Length(S)>2 then SetLength(S,Length(S)-3) else S:="";
end;
Time:=GetTickCount-Time;
Label1.Caption:=IntToStr(Time);


Для небезопасного:
var
S:String;
Time:Integer;
FTD:Integer;
begin
Time:=GetTickCount;
For FTD:=1 to 1000000 do
begin
S:="ABC";
If Length(S)>2 then Delete(S,Length(S)-2,3) else S:="";
end;
Time:=GetTickCount-Time;
Label1.Caption:=IntToStr(Time);

Оба безопасных варианта показали отличный результат! Первый безопасный справлялся в среднем за 110 мс., а второй - 124 мс.!!! Небезопасный вариант ОЧЕНЬ отстал от своих конкурентов. Его средний результат 890!!!
Для справок: Все тесты проводились на процессоре Pentium III - 550Mhz.
PS: Щас буду читать, что вы написали:-)


 
VEG   (2002-08-11 13:08) [9]

>Anatoly Podgoretsky
>Оба варианта безопасны, так как проводится проверка на допустимость, но ты передернул карты во втором случае. Ведь речь шла о коде Delete(S,Length(S)-2,3) без проверки If Length(S)>2
Вот такоей код не является безопасным.
А ты помнишь, как я тебе говорил, что к этому коду приплюсовать проверку нехватки количества символов? Это я и имел ввиду!
>Второе на что надо обратить внимания, хоть оба варианта и сделают желаемое, но Delete в первую предназначен для удаления символов изнутри строки, в то время как SetLength именно для изменения ее длины в большую и меньшую стороны.
Согласен!
>В разговоре в чате, кроме того стояла речь об L:=Length(S)-3; вместо двух строк, как у тебя.
Извини. В чате мы разговаривали утром, а текст я писал ночью. Копии разговора я не сохранил. Ошибся!
>Речь в чате зашла не об этом коде, а конкретно о коде VEG по работе с реестром, где на весь код ни одной проверки на допустимость, данный код был только демонстрацией принципа написания безопасных программ, так к слову, при том со ссылкой на ветку откуда это взято и на указание кто обратил внимание на потенциальную ошибку в Delete, это Дигитман, если делать это без проверок на допустимость значений.
Да. Было дело! Но! Во-первых - это не весь код, и этот код не демонстрирует мой стиль программирования. Ты говорил, что в том коде ошибок больше, чем строчек! Это НЕ так! Единственное, что там нужно сделать - это весь код поместить в try ... except!!! Но там ошибка может случиться 1/1000000 вариантов. Вот оригинал вопроса: http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1025549197&n=2
>Суть теории такова, зачем писать код с ошибками, что бы потом тратить время на отладку, лучше сразу писать код без ошибки.
Я высказал эту мысль чуток в другой форме: "Лучше заранее предохраниться от проблем!":-)

PS: Сейчас прочту текст "Юрия Зотова"


 
VEG   (2002-08-11 13:43) [10]

>Юрий Зотов
Спасибо за такое подробноя разъяснение! Что-то подобное не мешало бы опубликовать в разделе статьи.
>Другое дело, что не следует становиться параноиком и втыкать проверки где надо и не надо.
И это главное!

>Anatoly Podgoretsky
В игре у меня используется куча обработок ошибок. Реально произойти могут только 4 ошибки:
1. Видеокарта не поддерживает требуемый видеорежим.
2. Поврежденный вопросник.
3. Отсутствие всех файлов игры (кроме EXE-шника, естественною).
4. Отсутствие звуковой карты, или MPEG-3 Decoder-а.
В первом случае появится сообщение об несоответствии, потом ВСТРОЕННОЕ УСТРАНЕНИЕ НЕПОЛАДОК.
Во втором и третьем случаях программа ЗАПУСТИТСЯ безо всяких проблем и ошибок! Ведущий аккуратно объяснит проблему пользователю, и расскажет, как ее устранить!
В четвертом случае программа заблокирует звук. Если есть звуковая карта, то отправит на мой сайт за декодером.
Я люблю писать код аккуратно. То, что ты видишь в форумах - это те обрывки, которые еще малоисследованы мной. Они не иллюстрируют тот код, который написан в игре.
Я не знаю, что у тебя с IE, о только у тебя такие шрифты. Мой сайт не такой страшный. Другое дело - программа. Кроме Windows ей ничего не надо.Там все будет отображаться, как положено! А игра очень красивая! Она безопасна, и риск, об котором ты мне говорил, сводится к нулю!
Вообще, если честно, большинство программ в интернете написаны небезопасным кодом.


 
VEG   (2002-08-11 17:06) [11]

Интересно, а предложенный здесь ( http://delphi.mastak.com/cgi-bin/forum.pl?look=1&id=1027684797&n=7) мой код является безопасным?


 
Anatoly Podgoretsky   (2002-08-11 17:10) [12]

VEG © (11.08.02 17:06)
Нет, читай выше про парные команды, try/finally


 
Юрий Зотов   (2002-08-11 18:40) [13]

> VEG © (11.08.02 17:06)

Что ж, попробуем прокомментировать. Естественно, лишь с той точки зрения, как я сам это понимаю, не более того. И, чур, не обижаться, ОК? Расценивайте это, как дружескую критику - каковой она и является.

1. Оформление текста все же оставляет желать лучшего (регистр, отступы, пробелы). А безопасный стиль с него и начинается.

2. TBitmap.Create - а где try-finally? Представьте себе, что в момент вызова этой процедуры Panel1 или Image1 уже уничтожены (например, из-за ошибки в совсем другом месте) - и здравствуй, утечка памяти.

3. GetDC(0) - а где try-finally? Согласен, что на этом участке кода появление ошибки слишком маловероятно. Но если уж строго следовать канонам безопасности, то try-finally не помешает.

4. GetDC(0) - надежнее GetDC(GetDesktopWindow). Где гарантия, что в версии Win2005 нулевой хэндл по-прежнему будет означать десктоп, а не какой-то очередной наворот от дяди Билли?

5. PanelPoint:=ClientToScreen(Point(panel1.BoundsRect.Left,panel1.BoundsRect.Top));

Завтра Ваш коллега по проекту переложит Panel1 с формы на любой другой Parent (другую панель, TabSheet и т.д.) - и код заглючит. Надо привязываться к самой панели, а не к форме - например, можно использовать MapWindowPoints и точку (0,0).

6. ReleaseDC(0, ScreenDC) - см. п. 4.

7. Последнее - код далеко не оптимальный (лишние операции, лишние переменные, лишняя память).

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


procedure TForm1.Button1Click(Sender: TObject);
var
PanelRect: TRect;
ScreenWnd: HWND;
ScreenDC: HDC;
begin
if GetWindowRect(Panel1.Handle, PanelRect) then // Неявная проверка Panel1
with Image1.Picture.Bitmap do // Неявная проверка Image1
begin
Width := Panel1.Width;
Height := Panel1.Height;
ScreenWnd := GetDesktopWindow; // Чтобы не вызывать дважды
ScreenDC := GetDC(ScreenWnd);
// Вот здесь try-finally уже лишнее - если ошибка есть,
// то она всплывет раньше.
BitBlt(Canvas.Handle, 0, 0, Width, Height, ScreenDC, PanelRect.Left, PanelRect.Top, SRCCOPY)
ReleaseDC(ScreenWnd, ScreenDC)
end
end;



 
VEG   (2002-08-11 20:36) [14]

>Anatoly Podgoretsky
>Юрий Зотов
Этот код я писал уже давновато. Можете сами ппроверить, поглядев на дату. Догда я еще ниразу не слышал понятия "Безопасный код"

>Юрий Зотов
За время программирования я приобрел СОБСТЕННЫЙ стиль программирования. Вот пример:
(******************************Название болка кода******************************)
Function Name(S:String):String;//То, что делает эта процедура; Описание переменных и т.д.
var
//Name :Type; //Comment
FTD :Integer; //Пример
STR :String; //Еще пример
const
XXX=0; //И еще пример:-)
begin
(*Название подблока*)
STR:="abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"
+"abcabcabcabcabc";
If ... then
begin
For FTD:=1 to 100 do
begin
...
...
end;
end else ...;
If ... then ... else
begin
...
...
end;
If ... then
try
...
...
except
...
...
end
else
try
...
...
finally
...
...
end;
With ... do
begin
...
...
end;
For ... to ... do ...;
end;//Авторские права на процедуру, дата, время
Вас всех не должно волновать, что этот пример нерабочий! Это демонстрация моего стиля. Поймите! Мне так НАМНОГО удобнее! Код выглядит, как картинка!

Вот, например, так выглядит фрагмент с переменными у меня в игре:

(************************Параметры вопросных баз (Tags)************************)
BasePass :String; //Пароль доступа к вопроснику
BaseName :String; //Название вопросника
BaseNumAllQA :Integer; //Всего вопросов в вопроснике
BaseAutor :String; //Автор вопросника
BaseTopic :String; //Общая тема вопросника
BaseLoads :Integer; //Всего запусков базы

(**************************Работа с вопросными базами**************************)
BaseFName :String; //Имя файла вопросника
BaseFile :TextFile; //Файл вопросной базы
QA :array[1..15]of Integer; //Количетво вопросов
QABaseAll :array[1..15]of QABaseNum;//Все вопросы

(************************************Опции*************************************)
OnMusic :Boolean=True; //Музыка
OnTimer :Boolean=True; //Таймер
OnAnime :Boolean=False; //Анимация
MenuTimerSpeed :Integer=20; //Скорость таймера
для меню
Не код, а картинка!
Вот одна из процедур:
(******************************Системные поцедуры******************************)
procedure Delay(msecs : Longint);//Ждет msecs секунд, не зависая программу
var
FirstTick :longint; //TEMP для проверки времени
begin FirstTick:=GetTickCount;
repeat Application.ProcessMessages; {для того чтобы не "завесить" Windows}
until (GetTickCount-FirstTick >= msecs)or(GetKeyState(VK_SPACE) < 0);
end;


>Anatoly Podgoretsky


 
Oleg_Gashev   (2002-08-11 20:39) [15]

procedure Delay(msecs : Longint);//Ждет msecs секунд, не зависая программу
var
FirstTick :longint; //TEMP для проверки времени
begin FirstTick:=GetTickCount;
repeat Application.ProcessMessages; {для того чтобы не "завесить" Windows}
until (GetTickCount-FirstTick >= msecs)or(GetKeyState(VK_SPACE) < 0);
end;

А это зачем?


 
Oleg_Gashev   (2002-08-11 20:42) [16]

>Это демонстрация моего стиля.
> QA :array[1..15]of Integer; //Количетво вопросов
> QABaseAll :array[1..15]of QABaseNum;//Все вопросы

Плохой стиль. Будут проблеммы, если придется кол-во вопросов увеличить.


 
Oleg_Gashev   (2002-08-11 20:51) [17]

>BaseFName :String; //Имя файла вопросника
А если в имени файла больше 255 символов?


 
app   (2002-08-11 20:52) [18]

Не говоря о том, что она просто ошибочна, работает только при определенных условиях.
1. возврщаемое значение беззнаковое! DWord, а не знаковоый LongInt
2. в итоге даст ошибку при значении GetTickCount+msecs ~= 2^31, произойдет зацикливание или задержка в 24 дня, это относится к ранее упоминаемой проверки на работоспособность при предельных значениях.


Если хочешь иметь процедуру разогревающую процессор, то посмотри как это сделано в RxLib


 
VEG   (2002-08-11 22:21) [19]

>Oleg_Gashev
Количество вопросов по КАКТЕГОРИЯМ. Ты что, правил игры не знаешь??? В игре присутствует 15 вопросов. Правила игры менять не собираюсь! А в QABaseAll хранится динамический массив, который устанавливается автоватом по количеству вопросов. Количество вопросов ограничено типом Integer*15!!!
>А если в имени файла больше 255 символов?
Файл хранится в папочке QA вместе с игрой. В этой переменной хранится просто имя файла, без расширения и путя доступа!!! А имя файла, как известно, ограничено! Ошибка исключена!
>app
Во-первых максимально используемое в моей игре значение - это 10000!
Во-вторых здесь встроена возможность отмены всего процесса: GetKeyState(VK_SPACE) < 0!!!
В-третьих ЗАЧЕМ МНЕ ТРАТИТЬ ЛИШНЕЕ ВРЕМЯ НА ПРОВЕРКУ, И ЛИШНИЕ БАЙТЫ МОЕЙ ПРОГРАММЫ, если я точно знаю, какие значения я использую? Ведь пользователь не имеет право менять значения этих переменных!

ЗЫ Чтобы увидеть всю прелесть моего стиля написания кода, впишите его в редактор кода Delphi!!!
Примерный вид:
(******************************Название болка кода******************************)
Function Name(S:String):String;//То, что делает эта процедура; Описание переменных и т.д.
var
//Name :Type; //Comment
FTD :Integer; //Пример
STR :String; //Еще пример
const
XXX=0; //И еще пример:-)
begin
(*Название подблока*)
STR:="abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"
+"abcabcabcabcabc";
If ... then
begin
For FTD:=1 to 100 do
begin
...
...
end;
end else ...;
If ... then ... else
begin
...
...
end;
If ... then
try
...
...
except
...
...
end
else
try
...
...
finally
...
...
end;
With ... do
begin
...
...
end;
For ... to ... do ...;
end;//Авторские права на процедуру, дата, время


 
Anatoly Podgoretsky   (2002-08-11 22:48) [20]

VEG © (11.08.02 22:21)
Слушай если хочешь говорить о своей игре это одно, а о стиле это другое, Олег справедливо заметил что это стиль плохой.
В таких случаях или объявляют или граничные константы или что еще лучше поддипазон, например:

type
QuestionsRange = 1..15; //Количество вопросов


QA : array[QuestionsRange]of Integer; //Количетво вопросов
QABaseAll: array[QuestionsRange]of QABaseNum;//Все вопросы

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


 
Юрий Зотов   (2002-08-11 22:52) [21]

> VEG © (11.08.02 20:36)

Выглядит красиво и читается очень хорошо, спора нет. Но ведь стиль только начинается с красоты, а вовсе не заканчивается на ней. Не буду повторяться насчет array[1..15] и беззнакового MSecs, а вот по поводу "разогревания процессора" добавлю к уже сказанному - подобные циклы задержки гораздо лучше делать на основе MsgWaitForMultipleObjects. Вот это действительно будет грамотный стиль - при минимальной загрузке процессора делается все, что нужно. Очень советую такую процедурку написать, она не раз пригодится.

Хотя и то что есть - уже неплохо. Некоторые профессиональные программисты пишут хуже. Увы...

P.S. Информация к размышлению.
Выражение msecs + FirstTick в Вашем цикле repeat является инвариантом. Никаких мыслей по этому поводу не возникает? Это ведь тоже стиль...


 
Anatoly Podgoretsky   (2002-08-11 23:03) [22]

Ну не знаю насчет красоты, но меня коробит код, в котором begin и предложение в одной строке, то же repeat


 
Юрий Зотов   (2002-08-11 23:11) [23]

> Anatoly Podgoretsky © (11.08.02 23:03)

Дело привычки, не более. Не стоит забывать, что парню всего 15 лет. Стиль оформления он еще не раз сменит и в конце концов все равно придет к стилю Borland, не он первый и не он последний. Не это главное - гораздо важнее стиль ПРОГРАММИРОВАНИЯ.


 
Oleg_Gashev   (2002-08-11 23:39) [24]

>Не это главное - гораздо важнее стиль ПРОГРАММИРОВАНИЯ.

Я извиняюсь. Это не более важно мышления программиста, его отношения к самому программированию. Я несколько раз затрагивал эту тему на форуме и в который раз все сводится к тому же. Нас учат программировать, но не учат мыслить. Мы пишем
QA :array[1..15]of Integer;
и не понимаем, к чему это может привести. Поэтому могу посоветовать VEGу изменить в первую очередь мышление, а стиль программирования уже выработается сам.


 
Юрий Зотов   (2002-08-11 23:59) [25]

> Oleg_Gashev © (11.08.02 23:39)

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

Стиль программирования - "визуальное" отражение мышления программиста, его знаний и опыта. Эти вещи неразрывны, развиваются они всегда вместе. По сути, это одно и то же.


 
Torry   (2002-08-12 00:08) [26]

Юрию и Анатолию, в первую очередь:

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

Давайте поговорим на эту тему в привате?


 
VEG   (2002-08-12 00:32) [27]

>Anatoly Podgoretsky
>Слушай если хочешь говорить о своей игре это одно, а о стиле это другое, Олег справедливо заметил что это стиль плохой.
Я привел свой стиль НАПИСАНИЯ кода! Ошибка сдесь исключена, т.к. в конкретном случае новый тип создавать лучше не надо!
>У меня за эти месяцы создалось впечатление, что тебе плевать на все советы.
Хе-хе... Какие месяцы? Об написании кода мы заговорили только вчера!
>Ну не знаю насчет красоты, но меня коробит код, в котором begin и предложение в одной строке, то же repeat
Сперва я изучал Delphi без книг и интернета, т.к. ни того, ни другого не было! Придумал свой стиль, и мне он очень нравится!
>Юрий Зотов
Эта процедура была создана еще в прошлом году! И я не знаю, что за MsgWaitForMultipleObjects ты имел ввиду.
>...что парню всего 15 лет.
Когда же вы все НАУЧИТЕСЬ считать! Мне 14!!!
>Oleg_Gashev
>и не понимаем, к чему это может привести.
А к чему это может привести?


 
Anatoly Podgoretsky   (2002-08-12 00:32) [28]

Трудно это делать на постоянной основе, для любых кодов, задача более подходящая для форумов, на примере привеленного кода или как серия статей, помню у Борланда тольли в Д2 толи в Д3 в документации с Дельфи было несколько глав Robust Application.

Дело тут не в коде, а в психологии человека, либо он готов писать код без ошибок либо нет, непосредственное общение весь благоприятствует этому.

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

Совсем другое дело Юрий - это в его натуре и он это делает профессионально.


 
Anatoly Podgoretsky   (2002-08-12 00:35) [29]

Конкретно для Д5
Developer’s Guide
Chapter 3
Common programming tasks


 
MrBeer   (2002-08-12 01:49) [30]

Юрий Зотов © (11.08.02 22:52)
Некоторые профессиональные программисты пишут хуже. Увы...


Profesional oznachaet tolko chto chelovek etim zarabativet sebe na hleb, t.e. eto neochem ne govorit...


 
FLIZ   (2002-08-12 01:55) [31]

я даже в 2 ночи ВСЕ прочитал что вы написали.
как хорошо что вы так прекрасно учите!
спасибо вам!


 
Юрий Зотов   (2002-08-12 01:56) [32]

> MrBeer © (12.08.02 01:49)

Это и имелось в виду. К большому сожалению.


 
VEG   (2002-08-12 02:05) [33]

Спасибо Юрию Зотову за все!
Всем пока! Ветка закрыта!
VEG умер. За это отдельное спасибо в первую очередь Anatoly Podgoretsky, а потом уже MrBeer и Oleg_Gashev!

>Anatoly Podgoretsky, MrBeer, Oleg_Gashev
И все-таки печально, господа, печально...


 
Юрий Зотов   (2002-08-12 02:19) [34]

> VEG © (12.08.02 02:05)

Зря. Зачем так болезненно реагировать? Подумай спокойно. Только не сейчас, завтра. Спокойно перечитай и спокойно подумай, ОК?


 
Anatoly Podgoretsky   (2002-08-12 09:24) [35]

VEG © (12.08.02 02:05)
Что бы так болезнено не реагировать, могу посоветовать, кроме совета Юрия об отдыхе, приводить для анализа не свой код, с явным указанием этого, проще тогда будет оценивать.


 
VEG   (2002-08-12 12:14) [36]

И что? Все уже повторяется уже несколько раз... Разве последние три дня предел? Нет конечно же! Будут еще и другие...


 
FLIZ_   (2002-08-12 12:18) [37]

2 VEG © (12.08.02 02:05)

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

"VEG умер"

с таким пафосом о себе говорят пожалуй тока индейцы
(типа "дохлый енот уходит от вас" :-) )
и ....женщины! :)

2 олл
а я вот почитал что умные люди пишут и у себя
в стиле огрехи нашел, и еще раз говорю этим людям -
спасибо что учите! информация - самая ценная вещь...


 
DenKop   (2002-08-12 15:52) [38]

IMHO:
Думаю к таким вещам как типы данных придираться не стиоит, если эти значения не доступны юзеру. Если программист знает, что его программа ни при каких условиях не сможет обратиться к элементу массива индекс которого >15, то он имеет полное право объявить свой массив как [1..15]. Но если всё же остаются вопросы, тогда нужно использовать только типы Extended или Cardinal, наверняка не промажешь. В таком случае возникает вопрос об экономии памяти, а это тоже будет критиковаться. Так что же получается, какой код ни предоставь, всё равно он будет не правильный, ведь так же: либо не экономный, либо вообще не правильный (т.к. вопросов может быть более 15-ти, хотя для разработчика - это одна из основных идей, что вопросов может быть не более 15).
В таком случае и для нужно предусмотреть случай, что вопрос может быть вообще отрицательный (например -12). ПАРАДОКС господа! И зря вы напали с такими грубыми критиками на праня. Ведь это стиль программирования, а не обязательное правило, например типа такого, как точка с запятой после каждой строчки.


 
VEG   (2002-08-12 15:59) [39]

>FLIZ_
Речь идет не об стиле. Об разговорах в чате последних трех дней.


 
Anatoly Podgoretsky   (2002-08-12 16:02) [40]

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



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

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

Наверх





Память: 0.62 MB
Время: 0.009 c
1-35705
DN
2002-09-02 17:37
2002.09.12
Удаление файла


3-35609
ShuraGrp
2002-08-22 16:28
2002.09.12
TDataSet.Open приводит к тому, что все поля Visible = false


6-35844
Дельфятник
2002-07-04 11:37
2002.09.12
Как сканировать трафик?


14-35863
BAY
2002-08-15 23:24
2002.09.12
Модемное соединение


1-35689
Sergey-ZZZ
2002-08-30 12:12
2002.09.12
Компоненты





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский