Перевод Naming 101: Programmer’s Guide on How to Name Things.
Присвоение имён — одна из главных трудностей в разработке. Невозможно подсчитать, сколько времени мы тратим на обдумывание имён и на попытки разобраться в коде с плохими именами. И не важно, объекты это, методы, классы или что-то другое. Считается доказанным фактом, что мы тратим больше времени на чтение кода, а не на его написание, поэтому хорошие правила присвоения имён в будущем облегчат вам жизнь.
Хорошие имена делают код лучше и чище. Они помогают интуитивно определять, за что отвечает каждая часть кода. В будущем другим разработчикам будет легче читать ваш код, да и вам самим тоже.
Ниже объясним важность хороших правил присвоения имён и поделимся полезными советами.
Уровень абстракции
Методам и переменным нужно присваивать имена в соответствии с их назначением. Прежде чем выбирать имя, поймите, за что отвечает этот кусок кода.
Давайте разберём ситуацию, когда метод возвращает строковое значение расстояния между Варшавой и Парижем:
class DistancePresenter
def to_s
'The distance between Warsaw and Paris is 1591 km'
end
end
Код простой, и вроде бы работает правильно. А если немного поменять требования? Скажем, нужно отображать расстояние в километрах и милях. Для этого введём переменную класса взамен ключевого слова km
в методе to_s
.
Новую переменную нужно назвать на один уровень абстракции выше её значения. Это значит, что в первую очередь нужно думать о назначении переменной. Это поможет давать более общие имена, но в то же время не слишком причудливые. Иными словами, имя должно предполагать назначение переменной, а не её возможные значения.
Так за что отвечает наша новая переменная? Она предоставляет объекту слова km или mi. Так что назвать переменную можно kilometers_or_miles
, но такое наименование будет на том же уровне абстракции, что и сами значения переменной. Если нам нужна возможность использовать другие единицы измерения (к примеру, дни), то имя kilometers_or_miles
будет неверным. Нужно что-то более общее. Раз километры и мили — это единицы измерения, то можем назвать переменную unit
. Получается на один уровень абстракции выше (более общее название), чем назначение переменной. Новая реализация класса:
class DistancePresenter
def initialize(unit)
@unit = unit
end
def to_s
"The distance between Warsaw and Paris is 1591 #{unit}"
end
private
attr_reader :unit
end
Расстояние между Варшавой и Парижем 1591 км, но в милях получается 988. Нужно реализовать метод, возвращающий правильное значение. Правило такое же, как и в случае с переменной unit
. Давайте сначала подумаем о решаемой задаче. Новый метод должен возвращать значения 1591 или 988. Не важно, как метод будет это делать. Можно было бы назвать его distance_warsaw_paris
, но получится тот же уровень абстракции, что и у переменной. То есть имя метода будет предполагать возвращаемые значения. Слишком подробно.
В будущем города могут поменяться, к примеру, на Нью-Йорк и Лондон. Тогда имя distance_warsaw_paris
устареет, а менять его по всему коду будет трудозатратно. Лучше назвать просто distance. Именно то, что нужно: на один уровень абстракции выше тела метода.
Теперь наши методы выглядят так:
class DistancePresenter
def initialize(unit)
@unit = unit
end
def to_s
"The distance between Warsaw and Paris is #{distance} #{unit}"
end
private
attr_reader :unit
def distance
if unit == 'km'
1591
else
998
end
end
end
Уровень абстракции и имена классов
Методы и переменные нужно называть на один уровень абстракции выше, чем их тела, но именование классов подчиняется другому правилу. При создании класса нам не нужно думать о будущем. Именовать класс нужно на основе текущих предположений. Мы не предполагаем, что машина может обрести свойства лодки. Следовательно, если сейчас приложению требуется машина, то класс нужно назвать Car
, а не Vehicle
.
Дочерние классы нужно именовать таким же образом. Если у нас есть класс Car
, можно добавить специфическую версию, например, CarPickup
для машин Car
с большей грузоподъёмностью.
То есть правило, согласно которому именовать нужно на один уровень абстракции выше содержимого, применимо к методам и переменным, но не классам.
Принцип единственной обязанности
Один из SOLID-принципов гласит, что каждый модуль или класс должен отвечать за что-то одно. Гораздо проще выбирать имя элементу, если у него лишь одна функция.
Например, единственная обязанность бутылки — быть контейнером для жидкостей. Не нужно наделять бутылку возможностью двигаться или делать что-то другое, для чего она не предназначена (в приложении). Как бы вы назвали контейнер для жидкостей, который может двигаться? Не так это легко, и бутылка — довольно простой пример. Вместо того, чтобы плодить ходячие (а затем, возможно, танцующие, бегающие и говорящие) бутылки, лучше придерживаться принципа единственной обязанности. Создайте один класс для контейнера под жидкости, назовите Bottle
, а потом создайте класс для перемещения бутылки — BottleCarrier
.
Принцип единственной обязанности применим и к переменным. Каждая переменная должна делать что-то одно, будь она хоть переменной метода, класса или переменной иного типа. Как и в случае с классом, гораздо проще выдумать имя переменной, которая отвечает за что-то одно.
Разбивайте всё на более мелкие части
Хорошая архитектура неотделима от хорошего присвоения имён. Если вы понимаете, какую задачу решает элемент, вам будет легче подобрать ему имя. Есть полезная методика, помогающая создавать хорошую архитектуру: разбивайте каждую часть вашей задачи на более мелкие подзадачи. Тогда выбирать имена будет быстрее и проще.
Задумайтесь, разве не лучше давать имена модулям и объектам, когда вы знаете их назначение? Допустим, нужно описать машину. Трудно в одном классе перечислить каждую функциональность, но если разделить на много маленьких частей, то получим классы Wheel
, Tire
, steeringWheel
и другие, отражающие всевозможные компоненты машины. Этим маленьким компонентам легче подбирать имена, а их назначение легко определить. Так что если вам трудно даются имена компонентов, вероятно, у архитектуры какие-то недостатки.
Итог
Каждое хорошее имя, подобранное для переменной, метода, объекта или класса, рано или поздно облегчит вам жизнь. В этой статье показано несколько простых методик, которые помогут вам выбирать хорошие имена:
- Поднимайтесь на один уровень абстракции выше тела элемента (за исключением имён классов).
- Имя класса должно описывать его обязанность.
- Уважайте принцип единственной обязанности (одно из SOLID-правил).
- Разбивайте задачу на более мелкие подзадачи.
Выбор хороших имён не должен вызывать затруднения. Рекомендуем потратить время на подбор правильных имён, оно того стоит.
* * *
На эту статью вдохновила книга “99 Bottles of OOP”, написанная Сэнди Метц и Катриной Оуэн. Хорошая книга. Из неё можно узнать много полезного, в том числе о хороших методиках рефакторинга кода.
Автор: NIX_Solutions