Comments 26
1. Нейминг
SessionRepo.SaveSession, SessionRepo.DeleteSession, UserRepo.CreateUser и тд
Зачем нужен постфикс у методов? Это бессмысленное дублирование, у вас же не может быть метода SessionRepo.SaveUser…
2. Мне кажется методы в целом несогласованны:
UserRepo.CreateUser — очевидно Create не является зоной ответственности репозитория.
SaveSession(context.Context, UserID, TokenID, Origin) — из имени метода следует что вы сохраняете сессию а не UserID, TokenID, Origin.
И далее, мне видится что для вас репозиторий это абстракция над бд в вакууме, тогда как, кроме этого, интерфейс репозитория должен быть схож с интерфейсом коллекций. Если следовать этому определению методы типа UpdatePassword(context.Context, UserID, []byte) отпадут сами собой.
И второе, что бросилось в глаза, не забывайте возвращать конекшены обратно в пул:
defer conn.Close(),
в этом месте:
for rows.Next() {
if err != nil {
return
}
...
}
потенциально можете исчерпать все конекшены в базу.
На мой взгляд тут вообще не пахнет чистой архитектурой.
Вы в репозиторий при создании юзера передаете какой то TaskNotification
— как это относится к созданию юзера в персистент слое???
Функция func (a *Application) CreateUser
зачем то делает еще Login
, как это узнать не глядя в код и самое главное зачем вы смешиваете разные действия в одно? Что вы будете делать когда создали юзера а логин по какой то причине упал?
Почему (*User, AuthToken, error)
возвращает юзера по ссылке а остальные данные по значению? Так же в CreateUser
в репозиторий вы этого юзера передаете по значению.
У вас User
публичная структура и ничего не мешает взять ее и создавать с частичными полями. А по правильному архитектура не должна давать создавать невалидные объекты.
Дальше устал писать и разбирать.
Только вот отношения к clean architecture, по-моему, не имеют.
Основной посыл доклада/статьи — бить все на слои и тогда замена реализации CreateUser (при смене MySQL на NoSQL, например) пройдет менее болезненно.
Чистая архитектура это не мы как то разбили криво на слои. Не может быть в чистой архитектуре в слое который сохраняет юзера в базу какого то TaskNotification
или же создание бизнес сущности User
не может быть просто структура в которую можно накидать как угодно какие угодно данные.
Те если бы статья называлась пример наших костылей, то я и слова бы не сказал. А так замахнулись на чистую, понимаете ли, нашу архитектуру. И в результате выкатили какую то поделку.
Хмм. "Независимость от конкретной БД" разбивается в пух и прах наличием RETURNING в INSERT.
На уровень бизнес логики это, опять таки, совершенно никак не влияет.
Ты не будешь менять бизнес логику при такой системе, даже если заменишь pg на mongo.
Ты не будешь менять бизнес логику при такой системе, даже если заменишь pg на mongo.А стоило бы.
Инструмент выбирают под задачу. Если инструмент срочно потребовалось изменить, значит, задача поменялась. А делать возможность в любой момент поменять tcp на почтовых голубей просто ради мнимой универсальности — такое себе.
Если и нужно менять инструмент, значит измени инструмент. Eсли изменилась бизнес логика, меняй бизнес логику, БД лишь деталь и я прикладные задачи нашего проекта в 99% случаев не зависят от БД.
Но в любом случае, нужно понимать, что «чистая архитектура» это не свод законов, за нарушение которых тебя накажут, любой из нас может все вывалить в один файл, разница в том, что страдать будет поддерживающий.
1. либо изменилась сама задача
2. либо изначально ошиблись при проектировании
3. либо старый архитектор уволился, и ему на смену пришел некомпетентный человек, который руководствуется в первую очередь хайпом
Абстрации текут. Если при проектировании закладывать возможность в любой момент перепрыгнуть с постгреса на монгу, то реализация не будет эффективной. Некоторая бизнес-логика может быть просто нереализуема в принципе, либо реализация сопряжена с такими проблемами, что нужно все переписывать от начала до конца.
Вы не правы. Если вы делаете нормальные слои и взаимодействие то заменить какую то имплементацию будет относительно просто. Говорю из своего опыта когда приходилось мигрировать проекты с Монги или ДинамоДБ на Постгрес.
Возьмите обратную ситуацию — когда в типичном запросе используются несколько джоинов, и вы перенесли это на мап-редус, просев в производительности на порядок. Либо начали делать денормализацию и столкнулись с неактуальными данными.
Обобщая: перейти с текстовых файлов на бд — проблем нет, просто заменить «адаптер». Перейти с бд на файлы — проблем не оберешься.
Возможно кто-то подскажет где посмотреть реальные примеры с луковой архитектурой на go?
<портянка кода с четырьмяif err != nil
и возвратом 3 значений>
Это простой императивный код, который легко читается и легко поддерживается.
Хорошая шутка
Лена, спасибо за статью. Мне как раз предстоит рефакторинг сервиса с подобными проблемами, и я думаю, как лучше за это взяться. Теперь есть хорошее понимание
Плюсую, статья хорошая. Докопаться, конечно, и до столба можно, как известно, но суть раскрыта нормально. Думал кстати тоже аналогичную статью запостить с конкретным примером рефакторинга.
Чистая архитектура с Go