codeconv/README.md
2024-07-27 13:09:30 +00:00

7.3 KiB
Raw Blame History

codeconv

Соглашение о написании кода для бэкенда на go. Содержит три секции:

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

Написанное ниже применять без фанатизма, при несогласии - обсуждать.

Утверждённое

  • Скоро будет переделан. Использовать как рекомендацию, а не как правило лейаут - https://penahub.gitlab.yandexcloud.net/pena-services/docs/-/blob/main/architecture/golang/README.md

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

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

  • Если можно обойтись без указателя, стоит обойтись без указателя. Мы не боимся распухания стека, но npd ошибки и создание объектов на куче нас пугают. Предварительная оптимизация - зло, поэтому вопросы экономии на передаче по указателю будут подниматься после релиза, по необходимости. На будущее, критериями для замены передачи по значению на передачу по указателю могут являться: escape analisis покажет, что память так же будет выделяться на стеке, уменьшится среднее время выполнения операций - изолированный тест не подходит, ибо тут включается вопрос процессорного кеша и надо понять, будет ли проц чаще обновлять кеш, - количество аллокаций и объём потребляемой памяти.

  • Избегать чрезмерного разбиения на файлы и пакеты. Сейчас по проекту часто можно встретить в рамках пакета файлы, содержащие 1-2 структуры. Или несколько констант. Иногда это оправдано, например модель данных действительно может содержать только 1-2 структуры. Но зачастую это излишне и мешает нормальному ревью, например выносить константы названия полей в модели в отдельный пакет, по одному файлу на каждую сущность

  • Именование: сокращения допустимы только в рамках согласованного списка сокращений

  • Именование: стремимся к оптимальному соотношению сигнал\шум. Т.е. сокращения это зло, но слишком длинное именование - не меньшее зло

  • контекст всегда передавать вне структуры с зависимостями

  • Клиенты к сервису располагать рядом с сервисом, в каталоге /pkg/client

  • Стандартные сокращения: err, ctx, resp, deps, opts

  • Ресиверы сокращать до первой буквы названия типа. НИЧЕГО другого до одной буквы не сокращать.

  • Ветвиться от main или staging можно только в исключительных случаях, если тимлид так сказал. Во всех остальных случаях ветвимся от dev или с верхушки ветки своей последней задачи. Исходим из логики "одна задача - одна ветка"

Рассматриваемое

  • Именование: одно и то же именование не должно соответствовать концептуально разным сущностям. Пример называть все ошибки err нормально, пока они выполняют одну и ту же роль - единственной возвращаемой ошибки, но называть разные ресиверы одним именем вредно

  • Именование: если сущность имеет длинное наименование, но используется почти везде - стоит вынести на обсуждение вопрос о стандартизации сокращения

  • Использовать else только в случае, если обе ветки умещаются в 12 строк. else if не использовать

Предложение

  • Есть мысль, помечать внутренние пакеты суффиксом или префиксом, чтобы при чтении кода быстро определять, что есть что. но она требует рассмотрения на практике

  • Отделять переносами строки разнотипные операции - штука верная, но без фанатизма. Отделять ли объявление переменных от блока кода, в котором они будут использоваться - дело каждого

  • Разбиение на файлы: не вижу технического смысла выносить в отдельный файл сущность, которая чисто техническая и используется только в рамках другой сущности, как например конфиг для приложения, структуры запросов, возвращаемых значений, утилиты, используемые одним пакетом и тому подобное