fix backend
This commit is contained in:
+164
@@ -0,0 +1,164 @@
|
||||
# План GO-002: разорвать зависимости modules от repos и services
|
||||
|
||||
## Цель
|
||||
|
||||
Технические modules не импортируют прикладные `services` и storage `repos`.
|
||||
Модуль получает собственные входные типы, а преобразование repository-моделей
|
||||
делается на границе service.
|
||||
|
||||
Не меняем:
|
||||
|
||||
- protobuf/API и сгенерированные файлы;
|
||||
- формат `scenario.json`, ZIP-архива и публичные ответы;
|
||||
- бизнес-правила и SQL;
|
||||
- `internal/modules/storytelling`, пока он не импортирует repos/services;
|
||||
- GO-006 (`*_utils`) и GO-003 (единый error mapping).
|
||||
|
||||
## Фактические нарушения
|
||||
|
||||
| Module | Нарушение | Callers |
|
||||
| --- | --- | --- |
|
||||
| `modules/game_model` | импортирует `repos` и `services/scenarios_service` | game, gameplay, answer, team, MCP, app |
|
||||
| `modules/scenario_archive` | `Pack` принимает `*repos.Scenario` | `scenarios_service`, module tests |
|
||||
| `modules/scenario_archive` | импортирует `repos` только для storage-модели | только archive implementation |
|
||||
|
||||
## Правило миграции
|
||||
|
||||
Каждый кусок заканчивается рабочим компилятором и targeted-тестами. После
|
||||
каждого шага проверять запрещённые импорты:
|
||||
|
||||
```sh
|
||||
cd evening_detective_server
|
||||
rg -n '"evening_detective_server/internal/(repos|services)' internal/modules --glob '*.go' --glob '!*_test.go'
|
||||
go test ./internal/modules/... ./internal/services/...
|
||||
```
|
||||
|
||||
## Маленькие этапы
|
||||
|
||||
### GO-002.0 — зафиксировать baseline
|
||||
|
||||
1. Сохранить список runtime-файлов с нарушениями:
|
||||
`modules/game_model/game.go`, `game_mapper.go`, `team_mapper.go` и
|
||||
`modules/scenario_archive/interface.go`/`archive.go`.
|
||||
2. Проверить чистое состояние тестов:
|
||||
|
||||
```sh
|
||||
GOCACHE=/tmp/evening-detective-go-cache go test ./internal/modules/... ./internal/services/...
|
||||
```
|
||||
|
||||
3. Не менять callers и не создавать `common`, `domain` или `utils` только для
|
||||
обхода импортов.
|
||||
|
||||
Готово, если baseline проходит и список зависимостей зафиксирован.
|
||||
|
||||
### GO-002.1 — выделить собственный входной тип archive module
|
||||
|
||||
Файлы: `internal/modules/scenario_archive/interface.go`, `archive.go` и
|
||||
`archive_test.go`.
|
||||
|
||||
1. Добавить в module небольшой тип входа для упаковки архива, содержащий только
|
||||
нужные поля: `Name`, `Description`, `Image` и сериализованную `Story`.
|
||||
2. Изменить `IScenarioArchive.Pack` так, чтобы он принимал этот тип, а не
|
||||
`*repos.Scenario`.
|
||||
3. В implementation заменить обращения к `scenario.Scenario`,
|
||||
`scenario.Description` и другим полям на поля нового типа.
|
||||
4. Перевести module tests на новый тип. Формат `ScenarioJSON` не менять.
|
||||
|
||||
Проверка:
|
||||
|
||||
```sh
|
||||
cd evening_detective_server
|
||||
find internal/modules/scenario_archive -name '*.go' -print0 | xargs -0 gofmt -w
|
||||
go test ./internal/modules/scenario_archive
|
||||
! rg 'internal/repos' internal/modules/scenario_archive --glob '*.go'
|
||||
```
|
||||
|
||||
Ожидаемый результат: archive module полностью независим от storage package.
|
||||
|
||||
### GO-002.2 — сделать mapping repository → archive в scenarios service
|
||||
|
||||
Файлы: `internal/services/scenarios_service/service.go`, mapper и тесты.
|
||||
|
||||
1. В `scenarios_service` собрать новый archive input из уже полученного
|
||||
`*repos.Scenario`.
|
||||
2. Передавать его в `scenarioArchive.Pack`; repository-зависимость остаётся
|
||||
только в service, где ей место.
|
||||
3. Не переносить в module права, запросы, storage и protobuf.
|
||||
4. Сохранить поведение изображений, `nil`-описания и ссылок на story.
|
||||
5. Добавить/обновить один round-trip тест `DownloadArchive` → `UploadArchive`.
|
||||
|
||||
Проверка:
|
||||
|
||||
```sh
|
||||
cd evening_detective_server
|
||||
go test ./internal/services/scenarios_service ./internal/modules/scenario_archive
|
||||
! rg 'internal/repos' internal/modules/scenario_archive --glob '*.go'
|
||||
```
|
||||
|
||||
### GO-002.3 — отделить game model от modules
|
||||
|
||||
Файлы: текущий `internal/modules/game_model/*` и callers.
|
||||
|
||||
1. Переместить типы `Game` и `Team` в пакет с той же предметной ответственностью
|
||||
под `internal/services/game_model`.
|
||||
2. Сохранить имена типов и поля, чтобы это была механическая смена import path,
|
||||
а не новая модель или DTO.
|
||||
3. Перенести вместе с типами текущие `MapGame`, `MapGames`, `MapTeam`,
|
||||
`MapTeams`; они являются преобразованием storage-моделей в use-case-модели.
|
||||
4. Обновить callers в `game_service`, `gameplay_service`, `answer_service`,
|
||||
`team_service`, `mcp_service`, app и тестах.
|
||||
5. Не делать пакет `common` и не дублировать структуры.
|
||||
|
||||
Проверка после механического переноса:
|
||||
|
||||
```sh
|
||||
cd evening_detective_server
|
||||
find internal/services/game_model internal/services/game_service internal/services/gameplay_service internal/services/answer_service internal/services/team_service internal/services/mcp_service internal/app -name '*.go' -print0 | xargs -0 gofmt -w
|
||||
go test ./internal/services/game_model ./internal/services/game_service ./internal/services/gameplay_service ./internal/services/answer_service ./internal/services/team_service ./internal/services/mcp_service ./internal/app
|
||||
! rg 'internal/modules/game_model' --glob '*.go'
|
||||
```
|
||||
|
||||
### GO-002.4 — удалить старый module game_model
|
||||
|
||||
1. После успешного переноса убедиться, что `internal/modules/game_model` больше
|
||||
не импортируется и не нужен через тесты.
|
||||
2. Удалить только старые файлы package; новые копии не оставлять параллельно.
|
||||
3. Проверить `go list ./...`, чтобы не осталось пустого/дублирующего пакета.
|
||||
|
||||
Проверка:
|
||||
|
||||
```sh
|
||||
cd evening_detective_server
|
||||
go list ./...
|
||||
go test ./...
|
||||
! test -d internal/modules/game_model
|
||||
```
|
||||
|
||||
### GO-002.5 — финальная проверка направления зависимостей
|
||||
|
||||
1. Runtime modules не импортируют `internal/repos`, `internal/services` или
|
||||
`internal/app`.
|
||||
2. `scenario_archive` принимает только собственные типы и callbacks; SQL,
|
||||
права и storage остаются снаружи.
|
||||
3. `cmd` по-прежнему собирает concrete repositories/modules/services.
|
||||
4. Проверить, что сценарный архив и game/team responses побайтно/структурно не
|
||||
изменились в существующих тестах.
|
||||
5. Запустить финальный gate:
|
||||
|
||||
```sh
|
||||
cd evening_detective_server
|
||||
find internal -type f -name '*.go' -print0 | xargs -0 gofmt -l
|
||||
go vet ./...
|
||||
go test ./...
|
||||
```
|
||||
|
||||
6. Только после успешного полного gate отметить GO-002 как `DONE` в `todo.md`.
|
||||
|
||||
## Критерий готовности GO-002
|
||||
|
||||
- `rg 'internal/(repos|services)' internal/modules --glob '*.go' --glob '!*_test.go'` не находит runtime-импортов.
|
||||
- Нет дубликатов `Game`, `Team` или archive input model.
|
||||
- Все callers используют один пакет `services/game_model`.
|
||||
- ZIP/`scenario.json`, game/team responses и существующие error semantics не
|
||||
изменились.
|
||||
- `gofmt`, `go vet ./...` и `go test ./...` проходят.
|
||||
@@ -33,6 +33,12 @@
|
||||
|
||||
### GO-002 — разорвать неправильные зависимости modules от application layers
|
||||
|
||||
- Статус: `DONE` (этапы GO-002.1–GO-002.5 выполнены)
|
||||
- Результат: archive module использует собственный input type, `game_model`
|
||||
перенесён в `internal/services/game_model`, старые module-зависимости удалены.
|
||||
- Проверка: runtime modules не импортируют repos/services/app; `gofmt`,
|
||||
`go vet ./...` и `go test ./...` проходят.
|
||||
|
||||
- `internal/modules/game_model` импортирует `internal/repos` и
|
||||
`internal/services/scenarios_service`.
|
||||
- `internal/modules/scenario_archive` импортирует типы `internal/repos`.
|
||||
|
||||
Reference in New Issue
Block a user