Именование

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

Основные правила именования

  1. название должно отражать происходящую бизнес-логику
  2. если название может иметь двоякий смысл, воспользуйтесь справочником schema.org
  3. если члену команды непонятно название, то к названию должен быть написан комментарий (с точки зрения бизнес-логики)

И прежде чем продолжить, предлагаю ознакомиться с полезными статьями:

  1. неподдерживаемый код
  2. выбор имени функции
  3. psr-конвенции
  4. PHP RFC: Class Naming

Префиксы

В основу соглашения о префиксах положена конвенция сообщества symfony

Именование метода в иммутабельном объекте

XXX это имя соответствующего предмета (обычно), иногда дополненное описанием обстоятельств происходящих с ним действий. Любой метод должен возвращать булевое значение true или в случае проблем выбрасывать эксепшен, за исключением методов, в которых описано что именно должен возвращать метод (см. столбец Описание).

ИменованиеОписание
findXXXИспользуется, когда нужно найти данные по определенным параметрам (применяется вместо filterXXX). Если данные не найдены, то в случае поиска одного предмета обязан возвратить значение значение null, в случае поиска нескольких предметов обязан возвратить пустой массив или пустую коллекцию.
getXXXИспользуется для получения данных, обязан возвратить искомый тип данных или выбросить эксепшен. Так же применяется когда нужно обработать данные, например трансформировать одни данные в другие.
upsertXXXИспользуется для создания или изменения данных (альтернатива syncXXX)
updateXXXИспользуется для изменения данных
replaceXXXИспользуется для перемещения данных из одного места в другое
removeXXXИспользуется для удаления данных (применяется вместо deleteXXX)
restoreXXXИспользуется для восстановления данных (применяется вместо recoverXXX)
createXXXИспользуется для создания чего-либо в памяти (например объект с помощью фабрики)
addXXXИспользуется для добавления данных (например добавить файл в директорию или добавить строку в таблицу б.д.). Применяется вместо attachXXX, linkXXX, registerXXX, saveXXX и т.п.
copyXXXИспользуется для копирования данных (например при копировании заказа будет скопировано все без исключения, что касается этого заказа, кроме номера заказа)
fillXXXИспользуется, когда нужно заполнить/обогатить передаваемые в метод данные (применяется вместо enrichXXX), возвращает тот же тип данных, который был передан в метод
countXXXИспользуется, когда нужно выполнить расчет данных (например countRegisteredUsers), возвращает числовое значение
checkXXXИспользуется, для проверки наличия данных (например checkUserHasMoney)
validateXXXИспользуется, для валидации данных (например validatePassportNumber)
sendXXXИспользуется, для отправки данных в сторонний сервис (например sendMessage)
executeИспользуется, когда имя класса описывает выполняемую логику, при условии в классе одного публичного метода

Сочетания

Допускается использовать сочетание наименований, например:

  • searchAndUpdatePatient
  • findAndFillPatient
  • fillCheckedPatient
  • findAndFillCheckedPatient

Плохое именование

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

Неправильное именованиеОписание
processXXXабстрактное действие
generateXXXвероятнее всего можно заменить на addXXX

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

Именование метода в неиммутабельном объекте

XXX это имя соответствующего предмета.

Неявная связьЯвная связь
addaddXXX
getgetXXX
setsetXXX
hashasXXX
allgetXXXs
replacesetXXXs
removeremoveXXX
clearclearXXX
isEmptyisEmptyXXX
registerregisterXXX
countcountXXX
sendsendXXX
keysне доступно

Неявная связь - используется, когда объект реализует один из паттернов проектирования, а как известно паттерны это абстракции, а какие у абстракций могут быть явные связи - никаких (например: Registry, Pool, Service Locator и т.п.), более конкретный пример:

function add($name)
function get($name)
function remove($name)
function replace(array(['name' => $name, 'name2' => $name2, ...]))

Как видим, имя предмета, с которым имеется связь, передается в параметре $name.

Явная связь - используется, когда объект имеет явную связь с другим объектом, например:

function addUser()
function getUser()
function removeUser()
function setNames(array(['name' => $name, 'name2' => $name2, ...]))

Сложное именование

Первым делом предлагаю освежить знания о частях речи.

имя прилагательное - отвечает на вопросы: какой, какая, какое, какие, чей

имя существительное - отвечает на вопросы:

  1. Имен. П. - кто? что? - озера;
  2. Родит. П. - (не бывает) кого? чего? - озер;
  3. Дат. П. - (давать?) кому? чему? - озерам;
  4. Вин. П. - (винить) кого? что? - озера;
  5. Твор. П. - (восхищаться) кем? чем? - озерами;
  6. Предл. П. - (мечтать) о ком? о чем? - об озерах.

В свою очередь имя существительное может быть двух видов:

Три правила именования

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

1. если нет необходимости подразумевать апостроф в именах существительных мы так и делаем, примеры:

ОписаниеИменование
основная услугаmain_service
дополнительная услугиadditional_service
технологический комплексtechnological_complex

2. если получается подразумевать апостроф в именах существительных мы так и делаем, примеры:

ОписаниеИменование
id услугиservice_id
имя услугиservice_name
имена услугиservice_names
имена услугservices_names

К сожалению часто используемый в литературе привычный подход (подразумевая апостроф) при сложном именовании (имя содержащее существительные в множественном числе или состоящее из двух существительных) не дает возможности правильно передать суть и в этом случае мы переходим к пункту 3.

3. если правило 1 или 2 ошибочно передает описание предмета логики, то используем предлог of, примеры:

ОписаниеПодразумевая `sИменование
услуга группыgroup_serviceservice_of_group
группы услугиgroups_servicegroups_of_service
группа услугиservice_groupgroup_of_service
группа услугservices_groupgroup_of_services
группы услугиservice_groupsgroups_of_service
группы услугservices_groupsgroups_of_services
группа услуг из 1сservices_group_1сgroup_of_services_from_1c

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

Описание:Дополнительная услуга основной услуги технологического комплекса
Именование:AdditionalServiceOfMainServiceOfTechnologicalComplex

На последок

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


23.12.2010 08:09

Комментарии

Круто))))
Omni | 23.12.2010 14:01