Логин:     Забыли пароль?
 
Пароль:   Регистрация

Форум / Программирование - В помощь новичкам и любителям.  

В помощь новичкам и любителям.


Страницы: «1» «2» «3» «4» «5» «6» «7» «8» «9» «10»
bugmenot
bugmenot
3-ий класс
Сообщения: 88
[Сообщение #11] 14 июня 2011, 19:26
Форматирование оказалось упущено из виду, хотя, видимо, применялось к приведенным примерам "плохого" говнокода. см. http://jedicodeformat.sourceforge.net/

Цитата (Ерёмин А.А.):

Дай бог, чтобы как можно большее число людей это прочитало!
На бога надейся, а сам не плошай. Серьезно, когда уже почините http://expert.delphi.int.ru/question/5408/#msg_26813

виконання програми розпочинається з того самого мiсця, де призупинилося.

bugmenot
bugmenot
3-ий класс
Сообщения: 88
[Сообщение #12] 14 июня 2011, 19:31

Цитата (Gooddy):

NormalModeScreenPercent = 0.70;

Это должно быть равно 7 промилле? Или 70%?

виконання програми розпочинається з того самого мiсця, де призупинилося.

Gooddy
Gooddy
3-ий класс
Сообщения: 84
[Сообщение #13] 14 июня 2011, 19:37
Отступы, выравнивание.

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

Вступление.

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

I. Неверные переносы строки

  for ... 
  to ... do if ... then begin
 
  ...
 
  if ...  then ... end;

Понять что куда вложено совершенно непонятно.
Давайте добавим переносы строк куда нужно и уберём ненужные.


  for ... to ... do
  if ... then 
  begin
  ...
  if ...  then 
  ...
  end;

Выводы:
1. begin и end должны быть на отдельных строках. Не экономьте строчку и не ставьте begin на один уровень с оператором if, while или др.
2. Каждый оператор должен быть на отдельной строке. Не поддавайтесь искушению и не пишите так: x:=0; y:=0; z:=0; в одну строчку.
3. Пустые строки позволяют отделить логически части программы. Если такое действительно требуется - создайте процедуры.
4. Не пишите действие оператора if на одной строчке с then, или на одной строке с else. Тем более не надо запихивать if-then-else в одну строку: if x>y then x:=y else y:=x;

II. Горизонтальные отступы

Давайте дальше разбираться с нашим примером.

  for ... to ... do
  if ... then 
  begin
  ...
  if ...  then 
  ...
  end;

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


  for ... to ... do
    if ... then 
    begin
      ...
      if ...  then 
        ...
    end;

Выводы:
1. Когда вы пишите действие для оператора - ставьте эти действия на 2 пробела правее, чем сам оператор.
2. begin и end остаются на уровне оператора.

В итоге привожу код без замен на ...

  ResultMemo.Clear;
  for t := 1 to 100 do if frac( 4.5 * t - 400 ) / 5 = 0 then begin
  b := ( 4 * t + t div 2 - 400 ) div 5; k := 100 - b - t;
  if ( k > 0 ) and ( b > 0  then ResultMemo.Lines.Add( ... ); end;

Как видите ничего не понятно. А теперь с предложенными отступами:

  ResultMemo.Clear;
  for t := 1 to 100 do
    if frac( 4.5 * t - 400 ) / 5 = 0 then
    begin
      b := ( 4 * t + t div 2 - 400 ) div 5;
      k := 100 - b - t;
      if ( k > 0 ) and ( b > 0 ) then
        ResultMemo.Lines.Add( '' );
    end;

III. Выравнивание переменных

var
  x, y: Integer;
  h, w, i: Integer;
  Text: String;

В этом коде есть ещё ряд проблем, о которых была рассказано ранее, я их устраню но не буду объяснять.

var
  x, y:          Integer;
  Height, Width: Integer;
  Index:         Integer;
  Text:          String;

Выводы:
1. Разделять разные по предназначению переменные и объединять схожие - хорошая идея. Когда у вас в ряд написаны переменные x, y, h, w, i, j, txtCnt, tag, врядли кто-нибуть разберёт их предназначение.
2. Выравнивание по горизонтали улучшает читаемость кода. Когда тип переменной расположен сразу после её имени - неплохо. Но когда все данные предоставлены в виде таблицы, когда мы можем раздельно работать с разными колонками - отлично!

IV. Выравнивание присваиваний

Я уже выкладывал код с небольшим выравниванием присваиваний, но сейчас напишу более запущеный.

if LastResult > X then
begin
  Result := X;
  LastResult := X;
  NowX := X / 2;
end
else
begin
  Result := LastResult ;
  X := LastResult ;
  LastResult := LastResult / 2;
end;

А теперь сделаем выравнивание по присваиванию:

if LastResult > X then
begin
  Result     := X;
  LastResult := X;
  X          := X / 2;
end
else
begin
  Result     := LastResult;
  X          := LastResult;
  LastResult := LastResult / 2;
end;

Вывод:
1. Выравнивание даже для присваиваний позволит лучше визуально оценивать код.
2. Выравнивание эффективно для переменных с большой разницей в длине идентификаторов. Сделать выравнивание для переменных x, y, x2, y2 - небольшое улучшение, тогда как в примере длина переменных очень разная и в разы улучшает читаемость кода.

Чисти код! Чисти код! Чисти код!
min@y™
min@y™
Доктор наук
Сообщения: 400
[Сообщение #14] 14 июня 2011, 21:33
Молодец, правильное дело пишешь. Я пишу совсем немного по-другому, но в основном именно так.
Добавлю от себя: при вызове функции/процедуры/метода без параметров, ставьте скобки (в С/С++ это обязательно), в delphi такая возможность появилась, ЕМНИП, с 4-й версии.
ResultMemo.Clear(); // <--- пример не очень, конечно, но таки да...

Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
min@y™
min@y™
Доктор наук
Сообщения: 400
[Сообщение #15] 14 июня 2011, 21:41
Ещё добавлю, пожалуй.
Многие товарищи пытаются (бывает, что, успешно) писать программы на основе TTreeView, TListView, TPageControl и т.п. Причём, стараются прикручивать сложные динамические структуры к свойству Data. Это, конечно, возможно и работает, если всё сделать правильно, однако есть способ лучше, ИМХО, нашкрябать класс-потомок от TListItem, TTreeNode, TTabSheet... Лично я считаю, что так делать правильно, и везде, где возможно, пишу потомков. Даже от TStringList, TObjectList и т.д. Если кому интересно - могу научить.

Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
bugmenot
bugmenot
3-ий класс
Сообщения: 88
[Сообщение #16] 14 июня 2011, 21:44
Ну про отступы тут много личного получилось. Знаете ли вы, что те, кто ставит "операторные* скобки" по Кернигану ненавидят тех, кто их ставит по Оллмену даже больше, чем пользователи vi ненавидят пользователей emacs?
if X > 0 then Y := X*X + 2*X;
 
if X > 0 then 
begin 
  Y := X*X + 2*X;
end;
 
{ здесь и далее выражение приведено к трехпозиционному коду исключительно в иллюстративных целях }
if X > 0 then begin
  Y := X/2;
  Y := Y + 2*X;
end;
 
if X > 0 then
begin
  Y := X/2;
  Y := Y + 2*X;
end;

В частности, не очевиден конец предлагаемого в примере составного условного "оператора"*, вложенного в цикл.

*оператор здесь подразумевает statement.

виконання програми розпочинається з того самого мiсця, де призупинилося.

Gooddy
Gooddy
3-ий класс
Сообщения: 84
[Сообщение #17] 15 июня 2011, 00:50
Ключевое слово begin, как мне кажется совершенно не важно где расположено. Главное - чтобы человек ставил всегда одинаково, а исправить под себя если чего это будет легко.

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

Чисти код! Чисти код! Чисти код!
IlluminatI
IlluminatI
2-ой класс
Сообщения: 38
[Сообщение #18] 15 июня 2011, 14:48
min@y™: Научи :)

Gooddy
Gooddy
3-ий класс
Сообщения: 84
[Сообщение #19] 15 июня 2011, 15:10
min@y™: Насчёт скобок у функций/процедур.
Один человек, которого я очень уважаю сказал: "Когда процедура вызывается в отдельном утверждении, то итак ясно, что это вызов процедуры/функции. Когда же функция вызывается в выражении, она должна иметь пустые скобки, потому что необходимо помнить о накладных расходах которые возникнут при вызове этой процедуры"
С тех пор я пишу круглые скобки у каждой функции. Пытаюсь у каждой процедуры, но иногда забываюсь.

Чисти код! Чисти код! Чисти код!
bugmenot
bugmenot
3-ий класс
Сообщения: 88
[Сообщение #20] 15 июня 2011, 23:18
Gooddy: я вот о чём:
while True do
  if not False < (True and False) then
    if 2 * 2 = 4 then
    begin
      Large;
      Compound;
      Statement;
    end;
Another;
с отступами в 2 пробела даже в таком коротком блоке сложно увидеть где какая управляющая конструкция кончается.

Цитата (min@y™):

при вызове функции/процедуры/метода без параметров, ставьте скобки (в С/С++ это обязательно)

Ненене, у Паскаля совершенно другая идеология чем в крестах, и попытки писания C++ на паскале кончатся как всегда. Тут как бы понятна идея обозначить скобками символ с побочными эффектами, но это не будет работать в 100% случаев, ибо геттеры свойств как раз и призваны прятать вызов за простым символом (отдаю себе отчет, что геттер в принципе не должен иметь сайдэффектов)

Цитата (Gooddy):

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

Конечно, годный компромисс, но полностью описанную выше задачу не решает.

виконання програми розпочинається з того самого мiсця, де призупинилося.


Страницы: «1» «2» «3» «4» «5» «6» «7» «8» «9» «10» (всего страниц: 10, текущая: 2)
Всего сообщений: 96 (сейчас показаны: с 11 по 20)

Перейти в раздел:


 © 2004 - 2024, Delphi.int.ru
Версия форума: 1.10 (19.01.2010)
RSS Delphi.int.ru Expert Код
Выполнено за 0.04 сек.
Обратная связь