2. Качественный код

Прежде всего следует признать простую истину: программист не может заставить машину делать то, чего не знает сам. То есть любая программа есть просто инструмент автоматизации выполнения некоторых известных действий. Для того, чтобы написать программу нахождения корней квадратного уравнения, программист должен сам знать как это делается; чтобы создать приложение для сортировки данных, программист должен понимать как это делается и т.п.

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

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

  • программа должна состоять как минимум из трех блоков:
    • получения двух чисел (ввод пользователем, результаты другого расчета или нечто другое),
    • сравнение чисел и определение максимального из них,
    • вывод результата.
  • Для расчета необходимы две переменные для хранения исходных чисел, возможно одна переменная для результата (текстовой строки или числа).
  • Тип используемых переменных зависит от типа входных данных. Для универсальности можно выбрать вещественный тип.
  • Последовательность действий:
    1. выдача запроса на ввод двух чисел;
    2. ввод чисел a1 и a2 с клавиатуры;
    3. если первое число больше второго, то присвоить переменной result значение первого числа. Иначе присвоить переменной result значение второго числа;
    4. вывести значение переменной result на экран.

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

Большие программные проекты не могут обойтись без стандартизации написания разрабатываемого кода. Чаще всего стандарт оформления кода включает в себя следующее:

  • способы выбора названий и используемый регистр символов для имён переменных и других идентификаторов:
    • запись типа переменной в её идентификаторе
    • регистр символов (нижний, верхний, «верблюжий», «верблюжий» с малой буквы), использование знаков подчёркивания для разделения слов;
  • стиль отступов при оформлении логических блоков — используются ли символы табуляции, ширина отступа;
  • способ расстановки скобок, ограничивающих логические блоки;
  • использование пробелов при оформлении логических и арифметических выражений;
  • стиль комментариев и использование документирующих комментариев.

Рассмотрим все по порядку.

Именование переменных

Имена перменных должны отражать суть хранимого в них значения. Это позволит читать код как обычный текст, так называемый "самодокументированный код". Однако формировать имя переменной лучше не полными словами, а их сокращениями. Рассмотрите следующие два примера исходного кода:

Простой код Самодокументированный код
b = 0.13*a + 0.01*a;
c = 0.15*a + 0.5*a;
d = a + c - b;
Vychet = 0.13*Oklad + 0.01*Oklad;
Nadbv = 0.15*Oklad + 0.5*Oklad;
NaRuki = Oklad + Nabv - Vychet;

Второй вариант кода более информативен и позволяет любому сразу же вникнуть в суть выполняемых действий. Однако и в нем присутствуют изъяны. Дело в том, что профессиональные программисты стремятся, по возможности, избегать использования в математических выражения чисел, записанных цифрами. Вот как может выглядеть этот же код, но в еще более информативной форме:

Nalog = 0.13;
Profs = 0.01;
RegnCoeff = 0.15;
Premia = 0.5;

Vychet = Nalog*Oklad + Profs*Oklad;
Nadbv = RegnCoeff*Oklad + Premia*Oklad;
NaRuki = Oklad + Nabv - Vychet;

Если проект разрабатывается при помощи программистов из нескольких стран, то необходимо именовать переменные с использованием английских слов. Тогда код примет следующий вид:

Taxs = 0.13;
Profs = 0.01;
RegnCoeff = 0.15;
Prem = 0.5;

Dedct = Taxs*Salry + Profs*Salry;
Add = RegnCoeff*Salry + Prem*Salry;
Totl = Salry + Add - Dedct;

В приведенных примерах все имена переменных начинаются с большой буквы. Обычно так именуются переменные, хранящие какие-то конкретные значения. Имена переменных NaRuki и RegnCoeff содержат две заглавные буквы, что позволило явно выделить в их именах два слова. Это, так называемая, "верблюжья нотация". Однако не стоит слишком усердствовать и давать слишком длинные имена вроде NumberOfPeopleForEachGroupOfUniversity

Исследования показывают, что отладка программы требует меньше всего усилий, если имена переменных состоят в среднем из 10-16 символов. Отладка программ с именами, состоящими в среднем из 8-20 символов, была почти столь же легкой. Это не значит, что следует присваивать всем переменным имена из 9-15 или 10-16 символов, — это значит, что, увидев в своем коде много более коротких имен, вы должны проверить их ясность.

Слишком длинные имена: numberOfPeopleOnTheUsOlympicTeam
numberOfSeatsInTheStadium
maximumNumberOfPointsInModernOlympics
Слишком короткие имена: n, nр, ntm
n, ns, nsisd
m, mр, max, points
То, что надо: numTeamMembers, teamMemberCount
numSeatsInStadiumrseatCount
teamPointsMaxrpointsRecord

Одним из спорных вариантов именования переменных является венгерская нотация (более подробно об этом можно прочитать в Wikipedia). Ее суть в следующем: первые два-три символа указывают на тип, хранимого в данной переменно, значения. Эти символы еще называют префиксами. Ниже приведен пример такой таблицы.

Префикс Сокращение от Смысл Пример
s string строка sClientName
sz zero-terminated string строка, ограниченная нулевым символом szClientName
n, i int целочисленная переменная nSize, iSize
l long длинное целое lAmount
b boolean булева переменная bIsEmpty
a array массив aDimensions
t, dt time, datetime время, дата и время tDelivery, dtDelivery
p pointer указатель pBox
lp long pointer двойной (дальний) указатель lpBox
r reference ссылка rBoxes
h handle дескриптор hWindow
m_ member переменная-член m_sAddress
g_ global глобальная переменная g_nSpeed
C class класс CString
T type тип TObject
I interface интерфейс IDispatch
v void отсутствие типа vReserved


Отступы в коде и расстановка скобок

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

Плохой вариант оформления кода

Хороший вариант оформления кода