Осторожно: В К У С О В Щ И Н А

Я хочу чтобы люди именовали вещи хорошо. Попробую кратко написать как это делать, вместо того чтобы заставлять читать кучу книг.

Для начала поговорим о модульности. Это про декомпозицию программы. Есть несколько уровней модульности, они не обязательны. Возьмём к примеру python.

  • Репозиторий
  • Python-пакет
  • Файл с исходным кодом
  • Класс
  • Функция
  • Переменная

Что у них есть общего? У всего есть название. Каждый вышестоящий уровень модульности можно считать контекстом. Так вот, сущность уже в контексте, не нужно тащить контекст в её название.

Думаю, нужен пример:

# example/foo.py
class Foo(object):
    def __init__(self):
        self.counter = 0
    def increase(self):
        self.counter += 1
    def decrease(self):
        self.counter -= 1
  • Есть python-пакет example. Внутри кода не упоминается то, что это example. Единственное что оно нам говорит — то, что это пакет с какими-то примерами.
  • Есть файл с исходным кодом foo.py. Пусть класс внутри и называется точно так же — ничего страшного. Странно было бы если файл назывался foo.py, а единственный класс внутри — Math или FooMath. Сложно объяснить почему, но на мой взгляд у названия файла либо должен быть смысл, либо, если он содержит только одну сущность, оно должно совпадать с названием этой сущности.
  • Есть класс Foo. Ну, Foo и Foo, просто бессмысленный набор символов. В реальных примерах смысл должен быть, само собой.
  • Функции increase и decrease явно говорят что они увеличивают и уменьшают что-то. Никаких foo в названии нет, это просто глагол, то есть действие, которое мы производим. При вызове foo.increase() очевидно, что действие производится над foo, т.к. никаких других аргументов нет. foo.foo_decrease звучит дико, но это бросается в глаза потому что foo ничего не значит. Как только у foo появляется значение, людям почему-то хочется скорее запихать это значение везде.
  • Переменная counter тоже самодостаточна в названии. Она не привязана ни к example, ни к foo, ни к increase, ни к decrease. Её название описывает предназначение объекта.

А как иначе-то вообще?

Казалось бы, а по другому-то и нельзя. Когда эти “правила” нарушаются?

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

Какие ещё проблемы есть

Ещё одна проблема — при пробрасывании сущности по цепочке функций, языков, api и т.д. её многократно переименовывают.

Мотивация за — соответствие стилю кода этого проекта, удобнее набирать.

К каким проблемам приводит — теряется прозрачность. Прозрачность даёт grep’абельность между несколькими уровнями, а код остаётся менее запутанным. Думаю нужен пример.

Допустим, мы хотим хранить статистику по сетевым интерфейсам и рисовать графики в веб-интерфейсе. Есть база данных “metrics.sqlite”, в ней есть таблица “network”, в которой есть поля:

  • interface (eth0, eth1)
  • direction (rx, tx)
  • metric (packets, bytes)
  • value (1,2,3,4,5)

Есть код в python, который типа API, который делает SQL-запрос и отдаёт набор средних значений прироста счётчиков за минуту в JSON. Здесь легко поддаться соблазну и что-нибудь переименовать, например вернуть:

{
  device: eth0,
  metric: packets,
  direction: rx,
  values: [4,5,2,4,7],
}

Если задуматься, то дело не столько в том, что что-то переименовали и оно стало отличаться, сколько в том, что результат запроса вообще трогали, хотя можно было бы вернуть как есть и написать меньше кода. Но дело даже не в времени потраченном на кодинг. Здесь повторно потратили время на именование. Решение по именованию сущности должно приниматься один раз. Если решение кажется плохим - добейтесь его переименования в точке оригинала. Если вам не удаётся этого сделать - смиритесь.

Запахи плохого кода

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