Посты
9 рекомендаций по созданию выразительных имён
28 октября 2019 г. • 6 мин чтения
Именование субъективно и ситуационно, это искусство, и как в большинстве искусств, мы открываем закономерности. Я многому научился, читая код других людей. В этой статье я собрал 9 рекомендаций, которые я хотел бы, чтобы другие следовали, когда я читал их код.
Когда инженер открывает класс, она должна знать на основе имён ответственность класса. Да, я знаю, что именование — это только одна часть головоломки, физическая и логическая структуры также играют значительную роль в понимании кода, как и сложность. В этой статье я сосредоточиваюсь только на именовании, потому что считаю, что оно оказывает наиболее значительное влияние на понимание кода.
Не включайте тип, если он не уточняет намерение
Тип может быть чем угодно: от типа программирования (string, int, decimal) до группировки ответственности (Util, Helper, Validator, Event и т. д.). Часто это классификация, которая не выражает намерение.
Посмотрим на пример: имя StringHelper не выражает многого. String — это системный тип, а Helper — расплывчато, StringHelper говорит больше о “как” чем об намерении. Если вместо этого мы изменим имя на DisplayNameFormatter, мы получим более ясную картину намерения. DisplayName очень специфичен, а Formatter выражает результат. Formatter может быть типом или нет, но это не имеет значения, потому что он выражает намерение.
Всегда есть исключения; например, в ASP.Net MVC контроллеры должны заканчиваться на “Controller”, иначе приложение не будет работать. Используя парадигмы, такие как Domain Driven Design (DDD), имена вроде “Services”, “Repository”, “ValueType” и “Model” имеют значение в DDD и выражают ответственность.
Например, UserRepository подразумевает, что данные пользователя извлекаются и сохраняются в хранилище данных.
Избегайте метафор
Метафоры культурны, и инженеры из других культур могут не понять намерение.
Распространённые метафоры в Соединённых Штатах:
- Beating a dead horse
- Chicken or the egg
- Elephant in the room
Распространённые метафоры в Новой Зеландии:
- Spit the dummy
- Knackered
- Hard yakka
Используйте глаголы
Steve Yegge написал (очень длинный) пост в блоге об использовании глаголов вместо существительных.
Его точка зрения заключается в использовании глаголов, приложения состоят из существительных, но существительные не делают вещи. Системы бесполезны только с существительными, вместо этого выражайте действие в именах методов.
Например, UserAuthentication*(существительное).AuthenticateUser(действие/глагол)* выражает действие проверки учётных данных пользователя.
Будьте описательны
Будьте описательны, чем больше деталей, тем лучше — выражайте ответственность в имени.
Спросите себя, что одно делает хорошо этот класс или функция?
Если у вас возникают трудности с поиском имени, класс или функция могут иметь более одной ответственности и, таким образом, нарушать Принцип единственной ответственности.
Не полагайтесь на комментарии для выражения намерения
Комментарии — отличный способ предоставить дополнительный контекст к коду, но не полагайтесь на комментарии. Имена классов и методов должны говорить сами за себя.
В книге “Refactoring: Improving the Design of Existing Code” авторов Martin Fowler, Kent Beck, John Brant, William Opdyke и Don Roberts:
… комментарии часто используются как дезодорант. Удивительно, как часто вы смотрите на густо прокомментированный код и замечаете, что комментарии там потому, что код плохой.
Ещё одна замечательная цитата из авторов “Refactoring”:
Когда вы чувствуете необходимость написать комментарий, сначала попробуйте рефакторить код так, чтобы любой комментарий стал ненужным. Страница 88
Много раз, когда код рефакторится и инкапсулируется в метод, вы обнаружите другие места, где можно использовать новый метод, места, которые вы никогда не предполагали использовать новый метод.
Иногда при вызове метода потребителю нужно знать что-то особенное о методе, если эта особенность является частью имени, то потребителю не нужно просматривать исходный код.
Вот пример включения комментария в имя.
С комментариями:
// without tracking
var user = GetUserByUserId(userId);
Рефакторено для включения комментария в имя метода:
var userWithOutTracking = GetUserByUserIdWithoutTracking(userId);
Другие инженеры теперь знают, что этот метод не имеет отслеживания, прежде чем им нужно было бы либо читать исходный код, либо искать комментарий.
Комментарии должны быть вашей последней линией защиты, когда возможно, используйте другие способы выражения намерения, включая использование физической и логической структуры и имён для передачи намерения.
Воздерживайтесь от использования имён с неоднозначным значением
Избегайте имён с неоднозначным значением. Значение неоднозначных имён меняется от проекта к проекту, что затрудняет понимание намерения для нового инженера.
Вот список распространённых неоднозначных имён:
- Helper
- Input
- Item
- Logic
- Manager
- Minder
- Moniker
- Nanny
- Overseer
- Processor
- Shepherd
- Supervisor
- Thingy
- Utility
- Widget
Используйте тот же язык, что и бизнес-домен
Используйте ту же терминологию в коде, что и в бизнес-домене. Это позволяет инженерам и специалистам в предметной области (SME) легко обмениваться идеями, потому что они используют одинаковый словарь. Когда нет общего словаря, происходит перевод, что неизбежно приводит к неправильному пониманию.
В одном проекте, над которым я работал, бизнес начал с “Pupil” и затем переключился на “Student”. Инженеры-программисты никогда не обновляли программное обеспечение, чтобы отразить изменение терминологии. Когда новые инженеры присоединились к проекту, большинство считали, что Pupil и Student — это разные концепции.
Используйте отраслевую терминологию
Когда возможно, используйте терминологию, которая имеет значение во всей индустрии программного обеспечения.
Большинство инженеров-программистов, когда они видят что-то названное “factory”, сразу же думают о паттерне factory.
Использование существующих парадигм приложений, таких как “Clean Architecture” и “Domain Driven Design”, облегчает обмен идеями и создаёт общий язык для инженеров для общения идей между собой.
Худшее возможное именование — это присвоение отраслевой терминологии другого значения.
При именовании логических переменных…
Имена логических переменных всегда должны быть ответом на вопрос со значением либо true, либо false.
Например, isUserAuthenticated, ответ либо да (true), либо нет (false)
Используйте слова вроде:
- Has
- Does
- Is
- Can
Избегайте отрицательных имён, например:
Отрицательное имя переменной:
var IsNotDeleted = true; // this is confusing
if(!IsNotDeleted) { // it gets even more confusing when the value is negated
//Do magic
}
Без отрицательного имени переменной:
var IsDeleted = true; // this is confusing
if(!IsDeleted) {
//Do magic
}
В заключение
Выбор выразительных имён имеет решающее значение для передачи намерения, дизайна и знания домена следующему инженеру. Часто мы работаем с кодом, чтобы исправить дефекты или внедрить новые функции, и мы постоянно компилируем код в нашей голове, пытаясь понять, как он работает. Именование даёт нам подсказки о том, что думал предыдущий инженер, без этого общения между прошлыми и будущими инженерами мы ограничиваем себя в развитии приложения. Потенциально обрекая проект на неудачу.
Автор: Chuck Conway — инженер AI с почти 30-летним опытом разработки программного обеспечения. Он создает практические системы AI — конвейеры контента, агенты инфраструктуры и инструменты, которые решают реальные проблемы — и делится тем, что он узнает на этом пути. Свяжитесь с ним в социальных сетях: X (@chuckconway) или посетите его на YouTube и на SubStack.