Название функции


Любой код не является хаотичным набором знаков, а производит вполне конкретные операции над вполне конкретными величинами, у которых есть естественный человеческий смысл и соответствующие названия.

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

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

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

Всегда спрашивай себя: «Что здесь происходит с точки зрения предметной области?», «Как это называется на человеческом языке?».

Таким способом достигается достигается эффект, описанный Робертом Мартином: «код должен читаться как хорошая проза».

Как давать названия функциям

Мартин Фаулер в своём посте FunctionLength (на который я очень люблю ссылаться) даёт хорошее представление о том, исходя из чего следует выбирать название.

Мартин показывает два аспекта функций:

  • намерение: какого результата достигает функция, какова цель её существования;
  • реализация: каким образом достигается результат, при помощи каких преобразований.

Эти аспекты необходимо разделять по очень простой причине: один и тот же результат может быть достигнут множеством разных способов.

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

Так вот, название функции должно называть намерение, а не реализацию.

Команды и запросы

Согласно рекомендации Роберта Мартина, функция должна либо делать что-то, либо отвечать на какой-то вопрос (запрос), то есть возвращать результат.

Соответственно, название функции должно называть действие или вопрос/запрос.

Называние функции-команды

Функция-команда должна называться в соответствии с тем конечным результатом, которого она достигает, никак не обозначая при этом конкретных шагов, которые для достижения этого результата будут сделаны. Как правило, функция-команда что-то где-то меняет (поля в объекте и/или в таблице БД, создаёт новые объекты и записи в БД, отправляет сообщения и т. п.).

Причём помним, что названия должны выбираться исходя из названий сущности предметной области, в которой «работает» функция.

Название функций-команд принято начинать с глагола, чтобы подчеркнуть их директивный характер.

Пример: команда отмены заказа в интернет-магазине.

$order = Order::find($order_id);
$order->cancel($reason);
public function cancel($reason) {
    $this->status = 'cancelled';
    $this->cancellation_reason = $reason;
    $this->save();
}

В простейшем примере отмена заказа может выглядеть просто как присвоение статуса заказа и сохранение сделанного изменения в БД.

В реальности же при отмене заказа требуется произвести массу операций:

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

Естественно, мы не должны отражать все эти шаги в названии функции, мы говорим лишь о том, что функция должна попытаться сделать, каков будет результат её выполнения (отмена заказа).

Называние функций-запросов (вопросов)

Функции-запросы ничего не меняют, а только возвращают информацию тому, кто её запросил.

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

Иногда название функций-запросов начинается со слова «get» (но мне больше нравится без него). В названиях функций, связанных с транспортировкой, используются глаголы. Названия функций-вопросов принято начинать с глаголов «is» или «has».

В любом случае название должно содержать существительные и прилагательные, описывающие получаемую от функции информацию, опять же, без называния способа, которым функция эту информацию производит. То есть название даётся с точки зрения пользователя функции, а не с точки зрения самой функции. Мы как бы смотрим на функцию извне и видим только её результат (режим «чёрного ящика»), а не внутреннее устройство функции.

Пример

public function concatenated_names() {
    return$this->first_name . ' ' . $this->last_name;
}

concatenated_names называет операцию, которая внутри метода производится со строками (то есть называет реализацию), а поэтому неудачное. Правильное название метода — full_name, оно отражает результат выполнения функции.

Литература

  • Фаулер М. Рефакторинг: улучшение существующего кода. — СПб: Символ-Плюс, 2016.