👨💻 Скрытая цена чрезмерной абстракции в Go — 25 мая 2026 г. в 07:24:59.301
👨💻 Скрытая цена чрезмерной абстракции в Go Интерфейсы повсюду, многослойные пакеты, DI-контейнеры, generic-репозитории. Код выглядит солидно на ревью. Но стоит починить баг, и вы проходите шесть слоёв абстракции ради пяти строк логики. В Go это обходится дороже, чем кажется. Почему это происходит Интерфейсы в Go не требуют implements, любой тип удовлетворяет им неявно. Это удобно, но создаёт ловушку. Интерфейсы легко определять, поэтому их определяют слишком много. Пакеты легко создавать, поэтому кодовая база обрастает слоями ради диаграммы, а не ради задачи. Чем это бьёт Вы видите s.repo.Find(ctx, query.NewUserQuery().WithID(id)) и не знаете, это база, кэш или мок. Индирекция без пользы, просто шум. Интерфейсы создаются под единственную реализацию ещё до первого теста. Тесты обрастают моками для моков. Файл теста длиннее кода, который он тестирует. Как оставаться простыми Начинайте с конкретики. Напишите структуру, заставьте работать. Интерфейс выносите, когда появится вторая реализация. Так устроена стандартная библиотека Go. io.Reader не определили заранее: type UserStore struct { db *sql.DB } func (s *UserStore) GetByID(ctx context.Context, id string) (*User, error) { // реальная реализация } // Интерфейс только когда нужен type UserGetter interface { GetByID(ctx context.Context, id string) (*User, error) } Пакеты должны делать, а не транслировать. Если пакет только переводит между другими пакетами, это шов без назначения. Для большинства сервисов плоская структура cmd/, internal/store/, internal/api/ работает лучше. Функции вместо интерфейсов, где уместно. Не каждое поведение нужно выражать через интерфейс: func SendWelcome(ctx context.Context, user User, send func(context.Context, string, string) error) error { return send(ctx, user.Email, welcomeMessage(user)) } Называйте по действию, а не по слою. UserActivator, SessionIssuer, PasswordResetter вместо UserService, UserManager, UserHandler. Точность в имени сопротивляется желанию сваливать всё в одну абстракцию. Простой симптом. Если для одной фичи вы трогаете интерфейс, структуру, конструктор, мок и фикстуру до написания логики, архитектура работает против вас.

