Pull to refresh

Оформление кода

Programming *
Данным топиком я хочу поднять вопрос о качестве кода, независимо от используемого языка программирования. В топике я приведу пару советов и методик, которых придерживаются у нас в компании. Я не буду утверждать, что они являются верными, ведь у каждого есть свой вкус и свои предпочтения. Но все равно, в каждом кругу разработчиков, работающих вместе, существуют какие либо правила оформления кода.
Так же, не мало важно увидеть в комментариях ваши подходы и «любимый стиль».


Большинство советов в топике — вырезки из книги Макконнелла «Совершенный код» (Steve McConnell — «Code Complete»).

Многочисленные статистические исследования показывают, что среднестатистический программист проводит гораздо больше времени за чтением кода, а не его написанием. Читать код сложнее, чем писать его. Особенно если речь идет о чужом программном коде. Но вы можете серьезно облегчить работу себе и коллегам, если ваш код будет качественным, понятным. “Качество кода” довольно обширный термин, включающий в себя достаточно много разных аспектов, среди которых проектирование интерфейсов классов и методов, реализация методов, правильное взаимодействие классов и методов друг с другом, конвенции по форматированию и оформлению кода, именованию классов, методов и переменных, принятые в конкретной корпоративной среде.

Правило Ноль: строго следуйте code style «гайдам», принятым в вашей корпоративной среде.

Качественные методы


Метод должен служить одной четко определенной цели

Эта цель должна быть полностью отражена в его имени: получить текущего пользователя — getСurrentUser(). Размытое, неоднозначное и откровенно плохое имя метода чаще всего является
главным свидетельством его неудачной реализации.

Примеры хороших имен методов:
Customer::getFullName() – получить полное имя клиента UserMapper::createAndGetUser(userId) – исключение, в контексте User-маппера побочная роль метода (вернуть вновь созданный user-объект) достаточно очевидна.

MonthRevenue.calculate(), MonthRevenue.export() – неинформативные сами по себе имена методов оказываются полностью достаточными в контексте ООП вызовов этих методов «на себя» (другими словами, метод призван совершить действие над вызвавшим его объектом и его данными).


Примеры плохих имен методов:
computeMonthRevenueAndDoExport() – несколько несвязанных целей
processInput(), handleCalculation() – невыразительность, размытость цели
метода

  • Следует использовать парные антонимы для методов, выполняющих парные (противоположные) действия: open/close, show/hide, add/remove, insert/delete.
  • Метод должен быть отформатирован в строгом соответствии с принятыми конвенциями, «код стайлами» и так далее.
  • Метод должен быть документирован (как сам интерфейс метода, так и комментарии к важным и сложным участкам).
  • Метод не должен изменять глобальные переменные.
  • Метод не должен иметь слишком большое количество параметров (не более 7).
  • Параметры следует упорядочивать по степени их важности либо порядку их использования внутри метода:
    setMonthExchangeRate(month, exchangeRate)
    getCustomerMonthRevenue(customerId, month)

  • Неизменяемые параметры не должны передаваться по ссылке.
  • Не должно быть неиспользуемых «брошенных» переменных и параметров.
  • Не используйте входные параметры в качестве рабочих переменных.
  • Метод должен быть защищен от плохих данных, которые могут нарушить его работу.
    monthRevenue = fixedValue * 0.6 / inputParam

  • Метод не должен быть слишком большим (не более 100 строк).

Качественные переменные

Переменная должна полно описывать представляемую сущность

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

Умеренная длина

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

Спецификаторы

В именах переменных следует использовать спецификаторы Count и Index вместо Num. Это логично, так как они четко отражают назначение переменной (количество и номер), а вот Num выглядит достаточно двусмысленно и может в некоторых случаях ввести в заблуждение.

Индексы циклов

Это нормально, когда небольшой цикл из 1-3 строк имеет индекс под названием I,j или k. Но если тело цикла заметно больше, то лучше давать индексам осмысленные имена. И вам будет проще разобраться с таким кодом со временем (сразу же становится понятно, что делает цикл) и другим программистам, которые будут работать с вашим кодом, тоже станет легче.

Префиксы при перечислениях

При использовании перечислений имеет смысл ставить префикс. Например, в случае таких переменных STATUS_OPENED, STATUS_TO_CONFIRM, STATUS_CONFIRMED перечисление идет с префиксом STATUS_.

Константы

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

Конвенции

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

Меньше обобщенности

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

Примеры хороших имен переменных:

employeesCount, userMonthWorkDaysCount, yearTax, maxComputedSalary


Примеры плохих имен переменных:

x, $fb, f_ar_type_data, f_obj_result, inputData, returnValue, resultArray, obj1, obj2


  • Хорошее правило — давать более короткие имена переменным с более узкой областью видимости, соответственно, более длинные и подробные имена — переменным с более глобальной (в рамках метода) областью видимости.
  • Для переменных-счетчиков коротких циклов допускаются традиционные односимвольные имена — i, j, k, …. Если переменная будет использоваться вне цикла, ее имя должно быть более выразительным и понятным:

    teamScoresCount = 0;
    teamScores = array();
    
    while (teamScoresIterator.nextScore())
    {
    	teamScores[teamScoresCount++] =
    	teamScoresIterator.getCurrentScore();
    }
    
    foreach ($teamScores as $teamScoreIndex => $teamScoreValue)
    	foreach ($aTeamScores as $iTeamScoreIndex => $iTeamScore)
    	{
    		// over 9000 lines of code
    	}
    		

  • Избегать аббревиатур и неочевидных сокращений. Плохо: cl (call stack), gfx (graphics), dpt (department).
  • Использовать только согласованные сокращения: только max либо только maximum; только num либо только no; месяцы либо по первым трем буквам (Jan, Feb, Mar) либо полностью.
  • Избегать имен с похожими значениями (в рамках конкретной области видимости): fileNumber/fileIndex; scoresNumber/scoresCount. Применять только один из вариантов. Пишите имена без орфографических ошибок и опечаток
  • Избегайте именования переменных ничего не значащими (значащими только для вас) именами (snuffi, elizabeth) если только они не являются представляемыми в программе сущностями.
  • Имена булевых переменных должны быть в утвердительной форме и подразумевать булево значение: done, error, found, finished. Плохо: status, source.
  • Минимизация области видимости переменной:

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

  • Использовать каждую переменную только с одной целью.

  • Инициализировать переменные значением по умолчанию.



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

Согласитесь, читать такой код:
function()
{
	$a = 1;
	$b = 2;
	$c = 3;
	$sql = '
		SELECT
			*
		FROM
			tbl
		WHERE
			a = 1';
}


Более приятно, чем

function(){
  $a = 1;
 $b = 2; $c = 3;

 $sql = 'SELECT	* FROM tbl
WHERE a = 1';
}


Ссылка на книгу Code Complete.
Спасибо за внимание.
Tags:
Hubs:
Total votes 57: ↑34 and ↓23 +11
Views 58K
Comments Comments 109