Итак, - User, Wallet и Amount в моем примере интерфейсами не являются. - Интерфейсы для репозиториев - ок, можем без них обойтись. Однако, на мой вкус, лучше бы их оставить объектами, а не переписывать в ФП (но тут кому как) и использовать для них моки. Кроме того, источники данных, к которым фактически будут обращаться репозитории, могут меняться, и тот, кто от них зависит, лучше чтобы не знал об этом факте. Но ок, предположим, такого никогда не будет, и мы точно об этом знаем. Ноу проблем, интерфейсы убираем. - Интерфейсы в паттерне "спецификации". Вот тут как раз-таки вся соль в том, что конкретная комбинация правил сильно зависит от конкретного случая применения приложения, очень часто вносятся изменения в эту комбинацию. Весь остальной код, обращающийся к антифроду, не должен иметь ни малейшего понятия, с какой комбинацией правил он имеет дело в данный конкретный момент. Он должен знать только, что у него есть сейчас в распоряжении правильно настроенный/собранный объект, и, когда ему нужно, он ему всегда может задать вопрос и получить ответ.
Да, решая одни проблемы, мы можем создать другие, это всегда компромисс.
> Вы ведь понимаете, что можно DDD и в функциональном подходе иметь?
Мое мнение: каждый подход имеет право на существование, и у каждого подхода есть плюсы и минусы. Думаю, я понял вашу мысль, вы топите за функциональное программирование. И это просто отлично, без шуток. Я бы все-таки от вас хотел бы увидеть публикации на Хабре на эту тему. Наверняка у вас есть интересный опыт, которым вы могли бы поделиться, какие-то хорошие идеи, которые читатели могли бы взять на вооружение.
Про агрегаты - интересный вопрос. Врать не буду: в Go мы пока старались без них обходиться. :) Но есть пара идей, и думаю скоро провести серию экспериментов. По результатам напишу)
Ну вот вы тестируете что-то, что зависит от репозитория. Вам удобно будет замокать репозиторий. Мне не до конца понятно, зачем отказываться от чего-то, что удобно. :)
Про antifraud: в этом примере я показал сам паттерн, а не разбивку на пакеты. Вы можете разбивать на пакеты так, как считаете нужным.
Кажется, мы с вами все-таки говорим о разных вещах. По-моему, вы просто триггернулись но одно несоответствие стайлгайдам. :)
Окей, мы получается вернулись к первому вопросу, который не про избыточность интерфейсов как таковых, а про конкретный пример с возвращением интерфейса из конструктора.
Мне пришлось это сделать именно для реализации примера с идеей выноса всех реализаций в internal. Эта идея не претендует на то, чтобы быть единственно верной, и, как и у любого другого подхода, есть свои преимущества и недостатки.
Окей. Если вы про интерфейсы репозиториев, то основная идея - сделать так, чтобы у домена не было зависимостей. Кроме того, в домене не должно быть деталей реализации запросов к БД и прочего.
Я описал в статье один из способов как изолировать разные слои друг от друга. Мне понравился способ максимальной изоляции через полное скрытие конкретных реализаций, и взимодействие слоев только через интерфейсы. Если вы желаете разложить файлики в папочках по-другому, никто и не против. :)
Если отойти от DDD, то такой вам вопрос: юнит-тесты в Go пишете?
Рассуждение о преимуществах и недостатках DDD как такового выходит за рамки данной публикации, но возможно я напишу свои мысли на этот счёт в будущем. Спасибо за идею :)
Это всего лишь доступный в Go способ явно обозначить, что данный метод не меняет состояние объекта. Разумеется, в тех случаях, когда это может создать проблемы с производительностью, так делать не стоит.
Положить на стол полезную для развития книгу, потом поставить на нее монитор, чтоб повыше был
А если например конкретная комбинация зависит от конфига? Что возвращать-то?
Итак,
- User, Wallet и Amount в моем примере интерфейсами не являются.
- Интерфейсы для репозиториев - ок, можем без них обойтись. Однако, на мой вкус, лучше бы их оставить объектами, а не переписывать в ФП (но тут кому как) и использовать для них моки. Кроме того, источники данных, к которым фактически будут обращаться репозитории, могут меняться, и тот, кто от них зависит, лучше чтобы не знал об этом факте. Но ок, предположим, такого никогда не будет, и мы точно об этом знаем. Ноу проблем, интерфейсы убираем.
- Интерфейсы в паттерне "спецификации". Вот тут как раз-таки вся соль в том, что конкретная комбинация правил сильно зависит от конкретного случая применения приложения, очень часто вносятся изменения в эту комбинацию. Весь остальной код, обращающийся к антифроду, не должен иметь ни малейшего понятия, с какой комбинацией правил он имеет дело в данный конкретный момент. Он должен знать только, что у него есть сейчас в распоряжении правильно настроенный/собранный объект, и, когда ему нужно, он ему всегда может задать вопрос и получить ответ.
Да, решая одни проблемы, мы можем создать другие, это всегда компромисс.
> Вы ведь понимаете, что можно DDD и в функциональном подходе иметь?
Мое мнение: каждый подход имеет право на существование, и у каждого подхода есть плюсы и минусы. Думаю, я понял вашу мысль, вы топите за функциональное программирование. И это просто отлично, без шуток. Я бы все-таки от вас хотел бы увидеть публикации на Хабре на эту тему. Наверняка у вас есть интересный опыт, которым вы могли бы поделиться, какие-то хорошие идеи, которые читатели могли бы взять на вооружение.
Про агрегаты - интересный вопрос. Врать не буду: в Go мы пока старались без них обходиться. :) Но есть пара идей, и думаю скоро провести серию экспериментов. По результатам напишу)
Ну вот вы тестируете что-то, что зависит от репозитория. Вам удобно будет замокать репозиторий. Мне не до конца понятно, зачем отказываться от чего-то, что удобно. :)
Про antifraud: в этом примере я показал сам паттерн, а не разбивку на пакеты. Вы можете разбивать на пакеты так, как считаете нужным.
Кажется, мы с вами все-таки говорим о разных вещах. По-моему, вы просто триггернулись но одно несоответствие стайлгайдам. :)
Отойдем от DDD. Юнит-тесты пишете в Go? Как мокаете зависимости?)
Вы отрицаете необходимость интерфейсов в принципе?
Я не согласен, но мне бы получше узнать вашу точку зрения.
Окей, мы получается вернулись к первому вопросу, который не про избыточность интерфейсов как таковых, а про конкретный пример с возвращением интерфейса из конструктора.
Мне пришлось это сделать именно для реализации примера с идеей выноса всех реализаций в internal. Эта идея не претендует на то, чтобы быть единственно верной, и, как и у любого другого подхода, есть свои преимущества и недостатки.
Окей. Если вы про интерфейсы репозиториев, то основная идея - сделать так, чтобы у домена не было зависимостей. Кроме того, в домене не должно быть деталей реализации запросов к БД и прочего.
Я описал в статье один из способов как изолировать разные слои друг от друга. Мне понравился способ максимальной изоляции через полное скрытие конкретных реализаций, и взимодействие слоев только через интерфейсы. Если вы желаете разложить файлики в папочках по-другому, никто и не против. :)
Если отойти от DDD, то такой вам вопрос: юнит-тесты в Go пишете?
Этот вопрос видимо можно перефразировать в “Какую задачу решает DDD?” Это довольно обширная тема, пожалуй потянет для отдельной статьи
Как я и указал в статье, местами приходится отступать от различных go way гайдов. Язык - это всего лишь инструмент. :)
Рассуждение о преимуществах и недостатках DDD как такового выходит за рамки данной публикации, но возможно я напишу свои мысли на этот счёт в будущем. Спасибо за идею :)
Плюсую!
Это всего лишь доступный в Go способ явно обозначить, что данный метод не меняет состояние объекта. Разумеется, в тех случаях, когда это может создать проблемы с производительностью, так делать не стоит.