atomic-global-appenv-package-var.md 3.1 KB

Package-level mutable state: var AppEnv

Контекст: В backend/internal/handlers/errors.go:13 объявлена глобальная переменная var AppEnv string, которая устанавливается из cmd/api/main.go:68. Используется для контроля раскрытия деталей ошибок в production.

Проблема

// handlers/errors.go — ❌ package-level mutable state
var AppEnv string

func writeError(w http.ResponseWriter, status int, msg string, err error) {
    if status == http.StatusInternalServerError && AppEnv == "production" {
        msg = "internal server error"
    }
    writeJSON(w, status, map[string]string{"error": msg})
}
// cmd/api/main.go:68 — установка глобальной переменной
handlers.AppEnv = cfg.AppEnv

Антипаттерн:

  1. Невозможно тестировать — хендлеры зависят от внешнего состояния. Для теста writeError в production-режиме нужно установить AppEnv = "production", а потом сбросить. При параллельных тестах — race condition.
  2. Неявная связь — любой хендлер может изменить AppEnv в любой момент. Нет гарантии консистентности.
  3. Нарушение DI — вместо явной передачи зависимости — глобальный мутабельный синглтон.

Решение

Передавать isProd через конструктор хендлера (как уже сделано в AuthHandler):

type PlaceHandler struct {
    placeSvc *services.PlaceService
    isProd   bool  // ✅ явная зависимость
}

func NewPlaceHandler(placeSvc *services.PlaceService, isProd bool) *PlaceHandler {
    return &PlaceHandler{placeSvc: placeSvc, isProd: isProd}
}

func (h *PlaceHandler) writeError(w http.ResponseWriter, status int, msg string, err error) {
    if status == http.StatusInternalServerError && h.isProd {
        msg = "internal server error"
    }
    writeJSON(w, status, map[string]string{"error": msg})
}

Trade-offs

Подход Плюсы Минусы
DI через конструктор (рекомендую) Тестируемо, явно, потокобезопасно Нужно менять все хендлеры
Context values Не меняет сигнатуры хендлеров Неявно, .Value() без проверки типа
Оставить как есть (status quo) Нет работы Нет тестов, race condition

Связанные заметки

  • [[backend-validation]] — где используется AppEnv
  • [[architecture-overview]] — таблица P0
  • [[MOC-backend-patterns]]

Источник

Code review PhotoPlaces 2026-06. Найдено в handlers/errors.go:13.

Теги

#architecture #anti-pattern #testing #golang #clean-code