---  
name: golang-tswf-codestyle-skill  
description: ТЫ ДОЛЖЕН использовать этот скилл для всех Go проектов, модуль которых содержит подстроку tswf.io или если пользователь явно выбрал этот скилл.
---  

# Naming Conventions

## Базовые инструкции

* __Запрещено использовать короткие имена__ - `i`, `j`, `k`, `temp` и так далее - под запретом. Все переменные и методы должны иметь осмысленные имена.
* __Локальные переменные__ - camelCase, `:=`
* __Слайсы__ - всегда инициализируются через `make`.
* __Поля переменные__ - camelCase
* __Function Receiver__ - первая буква структуры, владелец по указателю.
* __Структура, скрытая за интерфейсом__ - camelCase с маленькой буквы (`myPrivateStuct`)
* __Публичная структура__, _например Dto_ - camelCase с большой буквы (`MyPublicStruct`)
```go
type Something struct {}

func (s /*<--- первая буква слова Something*/ *Something) somethingFunction() {  }
```

## Пакеты в именах типов

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

__Плохой пример__
```go
dtos.SomethingApiUserDto
```

__Хороший пример__
```go
somethingapi.UserDto
```

## Лаконичные, достаточные названия

Если класс что-то делает, а так чаще всего - старайся вложить это в название. 

Например класс для регистрации - `Registrar`, а класс для продвинутого конфигурирования чего-то - `AdvancedConfigurer`.  


Если ты видишь, что тебе в имени нужно указать что-то слишком длинное, вроде `SomethingApiUserDtoMapperToOurEntity`, то постарайся закрыть вопрос контекста в имени класса его пакетом и придумай название получше. 

# Interfaces

Ты ДОЛЖЕН скрывать компоненты за интерфейсами.

Это позволит подстраховаться от жесткой связанности на структуру. 

Например:

**ПЛОХОЙ пример**

```go
type MyComponent struct {
  // ...
}

func NewMyComponent() *MyComponent {}
```

**ПРАВИЛЬНЫЙ ПРИМЕР**

```go
type MyComponent interface {
  // Все нужные публичные методы из myComponent
}

type myComponent struct {
  // ...
}

// Этот пример правильный - используется интерфейс
func NewMyComponent() MyComponent {
  return &myComponent{}
}
```

Даже в рамках одного пакета при возможности используй интерфейсы вместо структур для инъекций компонентов

# Инстанцирование 

Все новые объекты создаются через конструктор. 

Конструктор принимает все объекты зависимости и внедряет их в создаваемый объект прямо при конструировании. 

Если возникает циклическая зависимость, то можно применить паттерн "Фасад" 

__Плохой пример__

```go
type MyComponent interface{ 
  SetDependency1(dep Dependency1)
  SetDependency2(dep Dependency2)
}

// Плохой пример
// Конструктор не гарантирует полного инстанцирования объекта. 
// Такой конструктор может вернуть объект в некорректном состоянии (если вызывающий код сам не использует сеттеры для зависимостей)
func NewMyComponent() MyComponent { /** ... **/ }
```

__Хороший пример__

```go
type MyComponent interface{ 

}

// Хороший пример
// Конструктор явно принял все зависимости
// Параметры конструктора для читаемости каждый на новой строке
func NewMyComponent(
  dep1 Dependency1,
  dep2 Dependency1,
) MyComponent
{ 
  /** ... **/
}
```

# Перенос строк

Для читаемости кода человеком и улучшения его визуальной структуры в коде применяются переносы строк.

Ты можешь применять их более креативно, но приведу два кейса: __вложенность__ и __много параметров__ функции

## Вложенность

Если вызовы вложены один в другой, то человеку-читателю легко потерять структуру. Например:

__Плохой пример__

```go
// Вся цепочка смешивается в кашу.
// Сразу не видно, кто в кого вложен. Читателю приходится напрягаться просто чтобы это понять. Это очень плохой пример
SomeMethod1(SomeMethod2(SomeMethod3()), SomeMethod4(&myStruct{1, 2, 3}))
```

__Хороший пример__

```go
// Вся цепочка вызовов структурно сразу визуализируется глазами читателя. 
// Видно, кто в кого вложен. Это хороший пример
SomeMethod1(
  SomeMethod2(
    SomeMethod3(),
  ), 
  SomeMethod4(
    &myStruct{1, 2, 3},
  ),
)
```

## Множество параметров функции

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

__Плохой пример__

```go
// Все в кучу. Чем больше параметров, тем тяжелее читать человеку
// Это плохой пример.
func funcOne(a string, b int, c bool, g pos.Position, e user.Controller) {}

func main() {
  funcTwo("hello world", 1, false, resolvePos().absolute(), resolveController())
}
```

__Хороший пример__

```go
// Четко видно структуру. Человеку просто такое читать.
// Это хороший пример.
func funcOne(
  a string,
  b int,
  c bool, 
  g pos.Position, 
  e user.Controller,
) {}

func main() {
  funcTwo(
    "hello world", 
    1,
    false, 
    resolvePos().absolute(), 
    resolveController(),
  )
}
```

# Project Structure

## Обязательно для любого Go проекта

* Makefile с кросс-платформенной сборкой
* README.md + русская версия
* Весь код лежит в папках `pkg`, `cmd` или `resources` ( код для доступа к embed ресурсам )
* Папка `bin` - туда попадают собранные через Make бинари. Она в gitignore

## Для микросервисов

Если это сервис, то добавляется 
* Dockerfile
* Docker-compose
* k8s chart

## CLI приложение
* Папка `cmd`, в подпапках которой реализуются консольные команды на `cobra`(!)  

## Структура файлов

* Root
  * bin # ОБЯЗАТЕЛЬНО в .gitignore!!
  * doc
  * deploy
    * docker (_тут если делаешь Docker, то добавь сразу compose. и посмотри релевантные скиллы для этого_)
    * k8s
    * e.t.c. 
  * pkg
    * domain
    * adapters 
    * infrastructure
  * cmd
    * \<cmdname\>
  * resources
    * \<embed go resources\>
  * go.mod
  * go.sum
  * README.md
  * README.ru.md
  * .gitignore
  * Makefile

# Имя модуля

Спроси имя модуля проекта, если пользователь явно его не задал. 
Если пользователь дал базовый путь (он оканчивается на `/`), то прибавь к нему имя корневой папки проекта