.gitignore | ||
API.md | ||
ENVS.md | ||
README.md | ||
REFACTORING.md | ||
ZAPLOGGERR.md |
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 не использовать
Предложение
-
Есть мысль, помечать внутренние пакеты суффиксом или префиксом, чтобы при чтении кода быстро определять, что есть что. но она требует рассмотрения на практике
-
Отделять переносами строки разнотипные операции - штука верная, но без фанатизма. Отделять ли объявление переменных от блока кода, в котором они будут использоваться - дело каждого
-
Разбиение на файлы: не вижу технического смысла выносить в отдельный файл сущность, которая чисто техническая и используется только в рамках другой сущности, как например конфиг для приложения, структуры запросов, возвращаемых значений, утилиты, используемые одним пакетом и тому подобное
-
Выбор задачи: сейчас действует установка меток по важности задачи, типа Low, High и так далее. Когда я ставлю задачу, я могу ещё не знать, какой у неё реальный приоритет, потому что на её приоритет могут влиять другие задачи. Например, я могу сегодня поставить задачу с приоритетом Low, потому что там какие-то мелкие правки, но на следующий день прилетит срочная задача с приоритетом High, которую бы сделать после этих мелких правок, чтобы не городить ведро костылей. Поэтому выбор задачи надо производить следующим образом - выбираешь задачу с наивысшим приоритетом, смотришь в список блокирующих задач и если он не пуст, выбираешь одну из них. Почему в Предложеии этот пункт - я не уверен в адекватности и удобстве этого решения