Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Общие вопросы по программированию, компьютерный форум
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.01.2012, 22:50   #81
Вадим Мошев

Старожил
 
Аватар для Вадим Мошев
 
Регистрация: 12.11.2010
Сообщений: 8,568
По умолчанию

Разумеется, комментарии могут быть где угодно, и какими угодно, я здесь описал то, чем пользуюсь я. Не комментирую очевидное, например:
X:=1; // Присвоить переменной X значение 1
Я не описываю алгоритм работы программы или её части, но, как сказал выше, описываю в общих чертах то, что делает комментируемый кусок кода:

Код:
 // Циклически переставляем "элементы-матрицы" трёхмерного массива
	for i:=1 to N do {...}
Отступы и переносы.
Разумеется, отступы и переносы можно не делать вообще (в тех местах, где это не приведёт к ошибке), но программа пишется не только для компьютера, программный код читается и анализируется ещё и человеком. Лично мне удобно, когда элементы кода отделяются друг от друга не только синтаксически, но и визуально.

При записи арифметического (или иного) выражения отделять друг от друга операторы и операнды:
Код:
x:=1.356 + (k - (b mod T)) * (ln(1 - (1/(A + B)))
При вызове подпрограмм, параметры записываются не только через запятую, но и через пробел:
Код:
T:=SomeFunction(a, nil, 'tra-tata', 44, W_Command);
Теперь, что касается применения отступов к служебным словам и операторам. Про вертикальные отступы я уже говорил, они нужны для того, чтобы логически и в то же время визуально отделить друг от друга куски кода.
Горизонтальные отступы нужны же для выделения иерархии к коде, то есть чтобы было видно, какой оператор в какой вкладывается. Это, прежде всего, относится к составному оператору Begin-end. Слова Begin и End должны начинаться с новой строки, должны быть правее всех операторов, которые они в себе содержат, например:

Код:
 if SomeCondition 
	then
	    begin
	     a:=b;
	     t:=u;
	     
	     if a < t+1
	     		then
	     		   begin
	     		   	inc(k);
	     		   	for i:=t to S do
	     		   			st:=D[i] + 0.25;
	     		   			
	     		   end;
	     		      
	    
	    end; // if SomeCondition
В некоторых случаях (при довольно большом числе внутренних операторов) после слова End я пишу поясняющий комментарий, в который помещаю часть оператора, который этим словом end завершается, например, так, как это сделано в выше рассмотренном случае.
Переносы целесообразно использовать в тех местах, где без них записанная строка смотрится наименее читабельной.
Например:
Объявление подпрограмм:
Код:
procedure MakeArrayThreeDemention(A: ArrayType; x, y, z, i, j, k: byte; IsArraySquare: boolean;
				  var FirstArray, SecondArray, FinishArray: Array3D);
Запись выражений
Код:
SomeGroup.SomeSubGroup.Student[i].Fined:= AllExamsPassed AND (MissedLectures < 30) OR
					StudentHasMuchMoney;
Запись строковых выражений:
Код:
SomeString:='Вот эта вот строчка настолько блин длинная, что её целесообразно и удобно '+
		'записать в несколько строк при помощи операции конкатенации, а не лепить в '+
		'одну!';
Вадим Мошев вне форума Ответить с цитированием
Старый 05.01.2012, 22:51   #82
Вадим Мошев

Старожил
 
Аватар для Вадим Мошев
 
Регистрация: 12.11.2010
Сообщений: 8,568
По умолчанию

Замечу, что в первом случае продолжение объявления подпрограммы надо записывать не вровень с началом заголовка, а чуть правее, тем самым, «поясняя», что это продолжение заголовка, а не что-то новое.
То же самое можно сказать и про второй и третий случай, но, на мой взгляд, здесь предпочтительнее присваиваемую часть записывать таким образом, чтобы ни один из её символов не был левее «столбца», на котором записан оператор присваивания «:=».
Также сквозь призму такого переноса можно посмотреть и на запись длинного логического выражения в условном операторе.
Код:
// мы не будем лепить логические операнды в одну строку, а просто перенесём
	if (cond1) AND (cond2) AND
	   (cond4) XOR (cond4) OR
	   (SomeCondition5)
				then
Если хочется избежать таких конструкций, можно присвоить это логическое выражение логической переменной, и в условие поставить её:
Код:
a:=(cond1) AND (cond2) AND (cond4) XOR (cond4) OR (SomeCondition5)

if a then...
Наконец, я могу посоветовать НЕ писать слова Do, then и else вместе с тем, частью чего они являются (лучше всего писать так, чтобы эти слова были ЕДИНСТВЕННЫМИ в строке). На мой взгляд, это очень хорошо оправдывает себя при пошаговой трассировке программы.
Вадим Мошев вне форума Ответить с цитированием
Старый 05.01.2012, 22:53   #83
Вадим Мошев

Старожил
 
Аватар для Вадим Мошев
 
Регистрация: 12.11.2010
Сообщений: 8,568
По умолчанию

Имена идентификаторов.
Говорят, что имена идентификаторов не должны быть слишком длинными. В данный момент я пока НЕ готов выдвигать аргументы за или против. Но с тем, что имена должны отражать их назначение, я согласен полностью.
Если имя идентификатора получается длинным, то слова следует визуально разделять. Лично я для этих целей использую заглавные буквы в начале слов, записывая при этом название идентификатора слитно. То есть:
GetSystemTime
GetArrayZerosAmount
ClearStack
IsMatrixSignular
На мой взгляд, отпадает необходимость использования комментариев при работе с такими идентификаторами, в этом случае можно говорить о самодокументированности в некоторой степени.
Вадим Мошев вне форума Ответить с цитированием
Старый 05.01.2012, 22:53   #84
Вадим Мошев

Старожил
 
Аватар для Вадим Мошев
 
Регистрация: 12.11.2010
Сообщений: 8,568
По умолчанию

Вот, навскидку вспомнил. Напоследок, код, в котором соблюдены все (практически) изложенные мной правила:
Код:
procedure TForm5.ButtonNextToTypeNameClick(Sender: TObject);
// С редактора сценариев тестирования переходим на ввод имени тестируемого

var
   emb, WrongSequence, AreThereZeros: boolean; // emd = EditMarks are Blank
   sc: byte;


Const
    EditMarksAreBlank = 'Ни одно из полей для ввода порога получения балла/зачёта не должно быть пустым.'+#13+
                        'Заполните ВСЕ поля.';

    MarksArentCorrect = 'Последовательность порогов оценок должна быть СТРОГО возрастающей, начиная '+#13+
                        'с самой низкой и заканчивая самой высокой оценкой.';

    ZeroMark = 'Ни одно из значений порогов получения оценок не должно иметь нулевое значение.';

    MarkHighGreatherThenAmount = 'Порог оценки на 5 баллов (или на зачёт) не может превышать '+#13+
                              'количества вопросов в тесте.';

    TimeFieldIsBlank = 'Ни одно из полей ввода значений времени не должно быть пустым.';

    TimeEqualToZero = 'Если вы установите нулевое значение времени, то таймер будет выключен '+
                      'и время, выделенное на тестирование, будет неограниченным.'+#13+
                      'Продолжить?';


    CantToBack = 'ВНИМАНИЕ! Сейчас будет осуществлён переход к вводу имени тестируемого.'+#13+
                 'Следует иметь в виду, что обратный переход из режима ввода имени будет невозможен. '+
                 'Продолжить?';


begin

  // Сначала считаем, что ошибок нет
      emb:=false;
      WrongSequence:=false;
      AreThereZeros:=false;

  // Обработка возможных ошибок

    sc:=RadioGroupScale.ItemIndex;

                if sc < 2
                      then // Пятибалльная или четырёхбалльная шкала
                        begin
                          if EditMark5.Text = '' then emb:=true;
                          if EditMark4.Text = '' then emb:=true;
                          if EditMark3.Text = '' then emb:=true;
                           If SC = 0 then
                                   if EditMark2.Text = '' then emb:=true;

                             if emb
                                  then // хотя бы одно поле порога пустое
                                    begin
                                      MessageDlg(EditMarksAreBlank, mtError, [mbOK],0);
                                      exit;
                                    end;

                        // Получаем числовые значения порогов оценок
                          Mark5:=StrToInt(EditMark5.Text);
                          Mark4:=StrToInt(EditMark4.Text);
                          Mark3:=StrToInt(EditMark3.Text);
                            if sc = 0 then
                                       Mark2:=StrToInt(EditMark2.Text);

                          // Не превышает ли порог оценки 5 кол-ва вопросов
                              if mark5 > SpinEdit1.Value
                                                    then
                                                      begin
                                                        MessageDlg(MarkHighGreatherThenAmount, mtError, [mbOK],0);
                                                        exit;
                                                      end;
Вадим Мошев вне форума Ответить с цитированием
Старый 05.01.2012, 22:55   #85
Вадим Мошев

Старожил
 
Аватар для Вадим Мошев
 
Регистрация: 12.11.2010
Сообщений: 8,568
По умолчанию

Код:
// Проверяем пороги на нулевые значения
                           if mark5 = 0 then AreThereZeros:=true;
                           if mark4 = 0 then AreThereZeros:=true;
                           if mark3 = 0 then AreThereZeros:=true;
                             if sc = 0 then
                                          if mark2 = 0 then AreThereZeros:=true;

                           If AreThereZeros
                                        then
                                          begin
                                            MessageDlg(ZeroMark, mtError, [mbOK],0);
                                            exit;
                                          end;


                        // проверяем корректность последовательности
                          if mark5 <= mark4 then WrongSequence:=true;
                          if mark4 <= mark3 then WrongSequence:=true;
                            if sc = 0 then
                                    if mark3 <= mark2 then WrongSequence:=true;

                          If WrongSequence
                                        then // Погоре установлены неверно
                                          begin
                                           MessageDlg(MarksArentCorrect, mtError, [mbOK],0);
                                           exit
                                          end;

                        end;


                if sc = 2
                        then // двухбалльная шкала
                          begin
                            if EditPassed.Text = ''
                                           then // поле порога получения зачёта пустое
                                            begin
                                              MessageDlg(EditMarksAreBlank, mtError, [mbOK],0);
                                              exit;
                                            end;


                            MarkPassed:=StrToInt(editPassed.Text);

                            if markPassed = 0
                                          then
                                            begin
                                              MessageDlg(ZeroMark, mtError, [mbOK],0);
                                              exit;
                                            end;


                            if markPassed > SpinEdit1.Value
                                              then // порог получения зач. превышает кол-во
                                                   // вопросов в тесте (не в списке)
                                                 begin
                                                   MessageDlg(MarkHighGreatherThenAmount, mtError, [mbOK],0);
                                                   exit;
                                                 end;


                          end;

                // Надо проверить значение времени и записать его
                  if NOT checkBoxDeactivateTimer.Checked then
                                                           begin
                                                              if (EditHours.Text = '')
                                                                 OR (EditMinutes.Text = '')
                                                                       then
                                                                         begin
                                                                           MessageDlg(TimeFieldIsBlank, mtError, [mbOK],0);
                                                                           exit;
                                                                         end;



                                                              if (EditHours.Text = '0') AND
                                                                 (EditMinutes.Text = '0')
                                                                                         then
                                                                                            begin
                                                                                             If MessageDlg(TimeEqualToZero, mtWarning,[mbYes, mbNo],0) = mrNo
                                                                                                     then exit
Вадим Мошев вне форума Ответить с цитированием
Старый 05.01.2012, 22:55   #86
Вадим Мошев

Старожил
 
Аватар для Вадим Мошев
 
Регистрация: 12.11.2010
Сообщений: 8,568
По умолчанию

Код:

else // принимаем значения времени нулевым
                                                                                                       begin
                                                                                                         CheckBoxDeactivateTimer.Checked:=true;
                                                                                                         hours:=0;
                                                                                                         Minutes:=0;
                                                                                                       end;


                                                                                            end

                                                                                         else // Если хотя бы одно из полей времени не нулевое
                                                                                             begin
                                                                                              Hours:=StrToInt(EditHours.Text);
                                                                                              Minutes:=StrToInt(EditMinutes.Text);
                                                                                             end;

                                                           end


                                                         else // если флаг деактивации стоит

                                                          begin
                                                            Hours:=0;
                                                            Minutes:=0
                                                          end;

     // Заполняем оставшиеся переменные
      AmountToTest:=SpinEdit1.Value;
      Scale:=sc;


      // Прежде, чем перейти дальше, сделать предупреждение, что назад вернуться
      // будет невозможно
        if MessageDlg(CantToBack, mtWarning, [mbYes, mbNo],0) = mrNo
                                                then exit;



        // Переходим
            ICanCloseIt:=false; // Это значит что тестируемый не может закрыть программу сам!
            ICanSeeMainForm:=false; // Тестируемый не сможет увидеть главную форму программы

           GroupBoxScriptsEditor.Hide;

           GroupBoxTypeUserName.Left:=152;
           GroupBoxTypeUserName.Top:=248;
           GroupBoxTypeUserName.Show;

           Form5.WindowState:=wsMaximized; // Разворачиваем окно
           Form5.FormStyle:=fsStayOnTop;   // Поверх всех окон
           Form5.BorderStyle:=bsNone;      // Убираем границу окна
end;

//======================================================
Вадим Мошев вне форума Ответить с цитированием
Старый 05.01.2012, 23:03   #87
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Вадим Мошев, много хорошего по теме, отступы - вариации на тему отступы в стиле Олмана. Касательно комментариев - я тоже не комментирую Х:=1, но комментарий к этой строке есть, внезапно да?
Код:
// Присвоить переменной X значение 1
Это бред, вопрос про данный коммент даже не подымался, читайте моих оппонетов более внимательно. Речь была о другом.

Цитата:
При вызове подпрограмм, параметры записываются не только через запятую, но и через пробел:
Про это не вспоминали ибо очевидные вещи. с другой стороны кому то будет полезно.
Цитата:
Говорят, что имена идентификаторов не должны быть слишком длинными. В данный момент я пока НЕ готов выдвигать аргументы за или против. Но с тем, что имена должны отражать их назначение, я согласен полностью.
Идентификаторы должны быть удобными для чтения. Даже если они слишком длинны. Дабы не разжигать полемику - это ИМХО, и я готов объяснить почему.
Цитата:
В некоторых случаях (при довольно большом числе внутренних операторов) после слова End я пишу поясняющий комментарий, в который помещаю часть оператора, который этим словом end завершается, например, так, как это сделано в выше рассмотренном случае.
Потому что Ваша ИДЕ не поддерживает свертку кода. Я не за и не против - удобство при необходимости. В Visual Studio в этом нет нужды.

Цитата:
Наконец, я могу посоветовать НЕ писать слова Do, then и else вместе с тем, частью чего они являются (лучше всего писать так, чтобы эти слова были ЕДИНСТВЕННЫМИ в строке). На мой взгляд, это очень хорошо оправдывает себя при пошаговой трассировке программы.
Согласен на 100 процентов - даже если Иф имеет только истинную ветвь условия - всегда выделяю отдельные строки и блок begin-end. И не только для c# ситуация аналогична. Это позволяет избегать некторые затраты при отладке - проверено на практике.
Цитата:
На мой взгляд, отпадает необходимость использования комментариев при работе с такими идентификаторами, в этом случае можно говорить о самодокументированности в некоторой степени.
Здесь я с Вами не согласен. Что такое Integer (будем говорить в терминах Дельфи, очевидно Вам это ближе)? В рамках алгоритма? Всегда ли это целое число? Ну другой пример - вычисление дискриминанта в рамках квадратного уравнения. Представьте школьника - итак какой тип использует школьник при вычислении дискриминанта - double, extended? Если Вы выберите один из них, то вы не правы. Ибо алгоритму пофигу на тип и это должно быть отражено в комментарии. То что Вы опишите будет стопроценто завязано на типе, а это не верно в корне. Знаю по себе - будучи школьником я решал квадратные уравнения не имея представления что такое double и что такое extended.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика

Последний раз редактировалось Utkin; 05.01.2012 в 23:20.
Utkin вне форума Ответить с цитированием
Старый 05.01.2012, 23:25   #88
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Согласен на 100 процентов - даже если Иф имеет только истинную ветвь условия - всегда выделяю отдельные строки и блок begin-end.
+1.
правда блок я не люблю выделять, но обычно пишу так:
Код:
			if(s&&s_own)
				delete s;
правда эту часть кода надо будет еще переделать(имена переменных и членов, на более подходящие)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 05.01.2012, 23:30   #89
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Цитата:
правда эту часть кода надо будет еще переделать(имена переменных и членов, на более подходящие)
Это не важно. Не понимаю проблему. Повторюсь еще раз банальная автозамена все решает, даже не говоря о рефакторинге. Откуда этот бзик? Дикость, корнями из древности...
По части Иф выделяйте блок - как совет (дело в итоге конечно за Вами), упрощает отладку (есть же автозамены во многих редакторах).
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 05.01.2012, 23:37   #90
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Повторюсь еще раз банальная автозамена все решает, даже не говоря о рефакторинге.
а я не говорил что буду переписывать с нуля.
Цитата:
упрощает отладку
чем?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Правила написания кода на Delphi Virtson Общие вопросы Delphi 17 06.08.2010 08:59
Правила разделов/главные правила Alex Cones О форуме и сайтах клуба 1 30.09.2009 17:49
Оформления текста tae1980 Microsoft Office Excel 6 26.03.2009 18:54
Стили оформления кода Altera Свободное общение 2 30.08.2008 17:23
Проблема оформления SunKnight Общие вопросы Delphi 3 25.02.2008 01:11