Данным топиком я хочу поднять вопрос о качестве кода, независимо от используемого языка программирования. В топике я приведу пару советов и методик, которых придерживаются у нас в компании. Я не буду утверждать, что они являются верными, ведь у каждого есть свой вкус и свои предпочтения. Но все равно, в каждом кругу разработчиков, работающих вместе, существуют какие либо правила оформления кода.
Так же, не мало важно увидеть в комментариях ваши подходы и «любимый стиль».
Большинство советов в топике — вырезки из книги Макконнелла «Совершенный код» (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.
- Минимизация области видимости переменной:
- Располагать команды использующие одну и туже переменную как можно
ближе друг к другу. - Инициализировать переменные непосредственно перед их использованием
- Располагать команды использующие одну и туже переменную как можно
- Использовать каждую переменную только с одной целью.
- Инициализировать переменные значением по умолчанию.
Ссылкана книгу Code Complete.
Спасибо за внимание.
Автор: hlx