Задать вопрос
@doflare123

Как должна выглядит правильная структура «внедрение зависимостей»?

Добрый день, я начал изучать написание серверов на golang на фреймворке gin. Сейчас настраиваю все вспомогательные структуры и зависимости. В первом своем проекте я использован всего лишь одну бд, но сейчас я планирую огромный проект, который включает в себя postgresql, mongoDB и Redis. И вот проблема:

Когда была всего одна бд, то container выглядел так:

type container struct {
	config *config.Config
	rep    repository.Repository
	logger logger.Logger
}

А репозиторий реализовывал postgresql методы.

type Repository interface {
	Model(value interface{}) *gorm.DB
	Select(query interface{}, args ...interface{}) *gorm.DB
	Find(out interface{}, where ...interface{}) *gorm.DB
	Exec(sql string, values ...interface{}) *gorm.DB
	First(out interface{}, where ...interface{}) *gorm.DB
	Raw(sql string, values ...interface{}) *gorm.DB
	Create(value interface{}) *gorm.DB
	Save(value interface{}) *gorm.DB
	Updates(value interface{}) *gorm.DB
	Delete(value interface{}) *gorm.DB
	Where(query interface{}, args ...interface{}) *gorm.DB
	Preload(column string, conditions ...interface{}) *gorm.DB
	Scopes(funcs ...func(*gorm.DB) *gorm.DB) *gorm.DB
	ScanRows(rows *sql.Rows, result interface{}) error
	Transaction(fc func(tx Repository) error) (err error)
	Close() error
	DropTableIfExists(value interface{}) error
	GetSQLDB() (*sql.DB, error)
	Clauses(conds ...clause.Expression) *gorm.DB
	AutoMigrate(value interface{}) error
}

type repository struct {
	db *gorm.DB
}

type filmRepository struct {
	*repository
}


Если сейчас все закидывать в один репозиторий, то получится перегруженный интерфейс. Возникла идея реализации:

type Repository interface {
	Postgres() PostgresRepository
	Mongo() MongoRepository
	Redis() RedisRepository
}


То есть в интерфейсе хранить еще три интерфейса. Насколько это разумная структура? Просто все хочется делать сразу по уму, а не как чувствуется. Если есть альтернативные решения таких задач, то я готов их выслушать и принять к сведению
  • Вопрос задан
  • 113 просмотров
Подписаться 1 Простой 7 комментариев
Помогут разобраться в теме Все курсы
  • Нетология
    Go-разработчик с нуля
    9 месяцев
    Далее
  • Skillfactory
    Профессия Backend-разработчик на Go
    12 месяцев
    Далее
  • Яндекс Практикум
    Go-разработчик с нуля
    8 месяцев
    Далее
Решения вопроса 1
@historydev
long long long long long .... int
Лучше оставить их раздельно:
Postgres() PostgresRepository
Mongo() MongoRepository
Redis() RedisRepository


Repository поверх излишняя абстракция, потому что никакой связи между postgres и mongo быть не может, соответственно и методов у Repository которые работают с некоторыми или всеми базами тоже.
- А если понадобится, на другом уровне можно реализовать.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
1. Интерфейсы лучше всего объявлять в тех местах, где они используются. То есть, внутри слоя бизнес-логики.
2. Репозиторий не должен возвращать/принимать никаких транспортно-специфичных типов (никаких *gorm.DB, пакета sql и прочих). Только структуры слоя бизнес-логики.
3. Репозитории лучше всего разделить, если у вас данных идут из монги, постгреса и редиса, это будут 3 разных репозитория, не надо их пытаться объединить под один интерфейс.
4. Передавать все зависимости чтобы сделать "внедрение" лучше всего в конструкторе. somepkg.New(pgRepo, mongoRepo). Внутри somepkg у вас будут определены интерфейсы под эти все репозитории, причем там будут только те методы, которые используются внутри этого пакета. В другом someotherpkg у нас будет определен уже другой интерфейс, содержащий методы, которые использует someotherpkg. Таким образом лучше видно что откуда используется и сохраняется чистота кода.
5. Делите обязательно все на слои, хендлеры импортят бизнес-логику, репозитории импортят бизнес-логику, но бизнес-логика не импортит ничего из хендлеров и репозиториев (для этого как раз интерфейсы и нужны). В итоге главная логика будет очень простая и изолированная от бойлерплейта транспортных слоев, не нужно будет переписывать тесты если что-то изменится в транспорте.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы