Здравствуйте, #John, Вы писали: J>Здравствуйте, samius, Вы писали: S>>Бизнес логики я в этом примере не увидел. Хотелось посмотреть на чуть более сложном примере, где взаимодействуют покупатель, корзина товаров, набор акций на отдельные группы товаров, накопительные бонусные программы или что-то в этом роде. S>>Я не прошу приводить код, я его довольно ясно представляю, в том числе с тестами и обилием моков. J>>>Если придется работать с внешним сервисом, придется создавать DomainService и дробить бизнес логику в rich-моделях. S>>Проблема рич в том, что чем больше сценариев, тем больше придется дробить бизнес логику в рич моделях. S>>Та же валидация внутри рич моделей говорит "ой", когда внезапно выясняется, что для одних процессов должна быть одна валидация, а для других — другая. J>В DDD есть такие понятия как Entity, Value Object, Aggregate, Aggregate Root. J>Entity/Value Object — это объекты. Концепция эквивалентности ссылок относится к Entity (User), в то время как структурая эквивалентность — к Value Object(Contact Information). швабра. J>Aggregate: набор Entities или Value Objects, связанных друг с другом через объект Aggregate Root. J>Aggregate Root: каждый агрегат имеет корень (в примере выше: User) и границу, агрегатный корень владеет агрегатом и служит шлюзом для всех модификаций внутри агрегата, J>Бизнес логику желательно писать в самых конечных объектах (Value Objects).
Что? Бизнес логика в ContactInformation? ИмейлАдрес.Отправляйся(), Земля.Копайся() ??? J>В моделях валидацию можно рассматривать как инварианты. Проверка того что объекты всегда в правильном состоянии, J>весь остальной код в моделях относится только к бизнес логике.
Объекты всегда в правильном состоянии для чего? Для какого процесса? J>Валидация типа J>
J>if(repo.GetUserById(id) != null)
J>{
J> throw new NotFoundException();
J>}
J>
J>будет в Application Layer-e. J>Бизнес логика — это все что говорит заказчик. Сначала определяется уникальный язык(термины) которые заказчик/менеджеры/бизнес аналитик/девы будут использовать чтобы понимать друг друга. J>Потом договаривают что напр. "Хотим изменить `Info` и `email` у пользователя". J>Т.к. это относится к сущности User, в моделе User создается метод `UpdateInformation(string info, string email)`, который является прокси методом к бизнес логике, J>которая будет писаться во вложеных Entitites и Value Objects.
метод UpdateInformation вероятно будет и в анемике тоже. Ключевой поинт анемика лишь в том, нахрена этот метод нужен User-у? Не отменяя того, что User- агрегат для изменения его информации, можно записать
UpdateInformation(User user, string info, string email),
Не говоря уж о том, что можно сделать из этого целый workflow с подтверждением имейла и мобилы, не затрагивая код User-а. J>Покупатель, корзина товаров, набор акций — это все будут разные агрегаты/агрегат руты. J>Для взаимодействия агрегатов, что бы проще было расширять бизнес логику и меньше было локов при сохранении данных в бд, в DDD есть понятие как DomainEvents. msdn J>Напр. у нас есть агрегат руты: User, Order, Product. Пользователь делает заказ. J>В модель `Order` при создании будет передается 'userId' (Id агрегат рута пользователя) и кидается event создания заказа. J>После мы можем добавить товар или изменить статус, при изменении статуса будет кидаться другой event.
Вот, DomainEvents — это такой мост между ричем и анемиком в моем понимании. Т.е. появляется обработчик — это что-то внешнее по отношению к модели данных. J>
S>метод UpdateInformation вероятно будет и в анемике тоже. Ключевой поинт анемика лишь в том, нахрена этот метод нужен User-у? Не отменяя того, что User- агрегат для изменения его информации, можно записать S>UpdateInformation(User user, string info, string email),
Это процедурный стиль программирования, типы данных отдельно, логика отдельно.
Объектно ориентированный подход — это когда данные и логика в одном объекте и мы работаем с объекатами.
В ОО объекты представляют сущности из реального мира(ограниченные условиями проекта).
Напр. хамелеон умеет менять цвет кожи. В коде мы и должны описывать хамелеона:
class Chameleon
{
public Color skinColor { get; private set; };
public void ChangeSkin(Color color) => skinColor = color;
}
ObjectsAndDataStructures
S>Объекты всегда в правильном состоянии для чего? Для какого процесса?
Что бы можно было создать/достать из бд агрегат рут, вызвать любой метод и объект был в валидном состоянии, и ни каких ошибок не выкинуло(напр. NRE),
что бы агрегат рут без дополнительных проверок, можно было просто взять и сохранить в бд целиком, одной транзакцией, и не получилось что мы потеряли часть данных.
Підтримати Україну у боротьбі з країною-терористом.
Здравствуйте, #John, Вы писали:
J>Оставлю для дополнительного размышления ссылку на статью "Про Anemic Domain Model" . В принципе там все сказано.
Такие статьи очень трудно рассматривать всерьез, т.к. они используют прием из демагогии "отсылка к авторитету", Посчитайте сколько в статье встречается Фаулер и Мартин.
Еще раз — функциональные программы (т.е. написанные в функциональном сителе) очень легко параллелить между процессорами/машинами и т.д, потому как функциональный стиль предполагает иммутабельность с самого начала. Чего не скажешь о RichModel — в этом случае нужно осуществить много танцев с бубнами.
Для меня на данный момент (2021 год) это один из главных аргументов в пользу выбора подходов к проектированию. Т.е. общая тенденция идет к децентрализации.
Re: DDD протаскивание других слоев через параметры методов D
Здравствуйте, #John, Вы писали:
J>как вы боритесь с тем, что в методы entity, через параметры, в Domain слой протягиваютя классы из других слоев?
Тут уже много всего правильного написали. Могу рассказать как это обычно делается в Java энтерпрайзе в слоистой архитектуре:
Классы типа Logger не относятся к обычному слою, они относятся к классу т.н. сквозной функциональности, не связанной с бизнес-логикой, а умеющей внедряться в любой слой. Туда же относятся transaction и security менеджеры. Эти классы DI-фреймворк (Спринг или JEE) сам инжектит в поля класса Enity (когда мы помечаем эти поля @Autowired или @Inject), их не надо передавать в явном виде в методах.
Похоже, что в приведенном примере все протягиваемые туда классы относятся либо к сквозной функциональности, либо к слою Util (DateTimeProvider, NumberProvider — это тоже особый случай, а не обычный слой, набор классов или 3-rdparty библиотек, не знающих про бизнес-логику и который могут использовать все обычные слои приложения).
А если возникает задача протащить между слоями именно доменные объекты, то есть паттерн DTO, причём он есть как в анемичной модели так и в DDD.
Здравствуйте, #John, Вы писали:
J>Здравствуйте, samius, Вы писали:
S>>метод UpdateInformation вероятно будет и в анемике тоже. Ключевой поинт анемика лишь в том, нахрена этот метод нужен User-у? Не отменяя того, что User- агрегат для изменения его информации, можно записать S>>UpdateInformation(User user, string info, string email),
J>Это процедурный стиль программирования, типы данных отдельно, логика отдельно.
Единственное, что я изменил в этой записи — передал неявный параметр явно и в коде метода придется к полям user-а обращаться с явным указанием, а не с неявным (this.)
J>Объектно ориентированный подход — это когда данные и логика в одном объекте и мы работаем с объекатами. J>В ОО объекты представляют сущности из реального мира(ограниченные условиями проекта). J>Напр. хамелеон умеет менять цвет кожи. В коде мы и должны описывать хамелеона: J>
J>class Chameleon
J>{
J> public Color skinColor { get; private set; };
J> public void ChangeSkin(Color color) => skinColor = color;
J>}
J>
и чем же следующий хамелеон хуже?
class Chameleon
{
public Color skinColor { get; set; };
}
J>ObjectsAndDataStructures
Не, ну это детский сад какой-то. Я предпочитаю опираться на принципы, сформулированные Кэйем. У него ничего нет про "данные и логика в одном объекте".
S>>Объекты всегда в правильном состоянии для чего? Для какого процесса? J>Что бы можно было создать/достать из бд агрегат рут, вызвать любой метод и объект был в валидном состоянии, и ни каких ошибок не выкинуло(напр. NRE), J>что бы агрегат рут без дополнительных проверок, можно было просто взять и сохранить в бд целиком, одной транзакцией, и не получилось что мы потеряли часть данных.
Я о том, когда валидное состояние для одного процесса(активности) подразумевает потерю части данных, необходимых для другого процесса (активности). При большом и все время растущем наборе активностей все данные не могут быть валидными для любых активностей.
Re[16]: DDD протаскивание других слоев через параметры методов Domain
Здравствуйте, samius, Вы писали:
J>>Напр. хамелеон умеет менять цвет кожи. В коде мы и должны описывать хамелеона: J>>
J>>class Chameleon
J>>{
J>> public Color skinColor { get; private set; }
J>> public void ChangeSkin(Color color) => skinColor = color;
J>>}
J>>
S>и чем же следующий хамелеон хуже? S>
S>class Chameleon
S>{
S> public Color skinColor { get; set; }
S>}
S>
Он попадает под описание процедурного стиля программирования: разбиение задачи программирования на набор переменных, структур данных и подпрограмм.
S>Не, ну это детский сад какой-то. Я предпочитаю опираться на принципы, сформулированные Кэйем. У него ничего нет про "данные и логика в одном объекте".
OOP to me means only messaging, local retention and protection and
hiding of state-process, and extreme late-binding of all things.
"local retention" — это и есть отсылка к тому что состояние объекта находится внутри объекта.
Там же он пишет:
I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages (so messaging came at the very beginning – it took a while to see how to do messaging in a programming language efficiently enough to be useful).
Биологические клетки свое состояние держат внутри себя, имеют разный набор данных(митохондрии, рыбосому, цитозоль), имеют разное поведение, и общаются посредством передачи ионов и молекул через каналы.
Підтримати Україну у боротьбі з країною-терористом.
Здравствуйте, #John, Вы писали:
J>Здравствуйте, samius, Вы писали:
S>>и чем же следующий хамелеон хуже? S>>
S>>class Chameleon
S>>{
S>> public Color skinColor { get; set; }
S>>}
S>>
J>Он попадает под описание процедурного стиля программирования: разбиение задачи программирования на набор переменных, структур данных и подпрограмм.
Как так? Отличия лишь в синтаксисе и такой глубокий вывод о стиле... Метод ChangeSkin заменен методом set_skinColor. Больше ничего не изменилось...
Кстати, не считаю, что процедурный стиль плох.
А если так?
class Chameleon
{
public Color skinColor { get; }
}
S>>Не, ну это детский сад какой-то. Я предпочитаю опираться на принципы, сформулированные Кэйем. У него ничего нет про "данные и логика в одном объекте".
J>Алан Кэй пишет J>
J>OOP to me means only messaging, local retention and protection and
J>hiding of state-process, and extreme late-binding of all things.
J>"local retention" — это и есть отсылка к тому что состояние объекта находится внутри объекта.
J>Там же он пишет: J>
J>I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages (so messaging came at the very beginning – it took a while to see how to do messaging in a programming language efficiently enough to be useful).
J>Биологические клетки свое состояние держат внутри себя, имеют разный набор данных(митохондрии, рыбосому, цитозоль), имеют разное поведение, и общаются посредством передачи ионов и молекул через каналы.
Да, сокрытие состояние объекта таки приветствуется. Но есть некоторое "но". Анемик не пытается делать из всего объекты. В нем моделируется не поведение пользователя, а поведение сервиса, производящего над пользователем некие действия. Поведение обработчика доменного события, если угодно. Пользователь в нем — сообщение и не стоит рассматривать его поля как его состояние. Не более, чем символы — состояние (неизменяемой) строки.
Re[18]: DDD протаскивание других слоев через параметры методов Domain
Здравствуйте, samius, Вы писали:
S>Как так? Отличия лишь в синтаксисе и такой глубокий вывод о стиле... Метод ChangeSkin заменен методом set_skinColor. Больше ничего не изменилось...
S>А если так? S>
S>class Chameleon
S>{
S> public Color skinColor { get; }
S>}
S>
Тоже самое. Стиль программирования `procedural vs oo` зависит от того как используется класс: как структура данных или как объект у которого все данные и логика прописаны в одном месте.
S>Кстати, не считаю, что процедурный стиль плох.
У оо больше возможностей по написанию более независимого, модульного кода.
В процедурном стиле: не используется сокрытие информации(модификаторы доступа), (т.к. поля/свойства всегда public).
потому может произойти такая ситуация, что код по изменению поля структуры будет раскидан в разных местах проекта/класса,
а изменение этого поля будет зависеть от разных условий. А код который меняет это поле будет зависеть еще от другого код,
а тот еще и еще. И когда понадобится добавить новую логику которая будет дополнительно как-то менять поле,
нам придется вместо того что бы подправить код в одном классе/объекте продебажить пол проекта и найти место куда воткнуть наш код.
Підтримати Україну у боротьбі з країною-терористом.
Здравствуйте, #John, Вы писали:
J>У оо больше возможностей по написанию более независимого, модульного кода.
Т.е. вы не видите разницу между двумя понятиями — процедурное и функциональное программирование и думаете, что это одно и тоже?
Re[19]: DDD протаскивание других слоев через параметры методов Domain
Здравствуйте, #John, Вы писали:
J>Здравствуйте, samius, Вы писали:
S>>Как так? Отличия лишь в синтаксисе и такой глубокий вывод о стиле... Метод ChangeSkin заменен методом set_skinColor. Больше ничего не изменилось...
S>>А если так? S>>
S>>class Chameleon
S>>{
S>> public Color skinColor { get; }
S>>}
S>>
J>Тоже самое. Стиль программирования `procedural vs oo` зависит от того как используется класс: как структура данных или как объект у которого все данные и логика прописаны в одном месте.
Что же все так радикально? В вашем примере видел UserInformationDto. Ваш пример — образец процедурного стиля?
S>>Кстати, не считаю, что процедурный стиль плох. J>У оо больше возможностей по написанию более независимого, модульного кода. J>В процедурном стиле: не используется сокрытие информации(модификаторы доступа), (т.к. поля/свойства всегда public).
Информацию скрывали и до изобретения модификаторов доступа.
J>потому может произойти такая ситуация, что код по изменению поля структуры будет раскидан в разных местах проекта/класса, J>а изменение этого поля будет зависеть от разных условий. А код который меняет это поле будет зависеть еще от другого код, J>а тот еще и еще. И когда понадобится добавить новую логику которая будет дополнительно как-то менять поле, J>нам придется вместо того что бы подправить код в одном классе/объекте продебажить пол проекта и найти место куда воткнуть наш код.
Модификаторы доступа здесь не наводят ясность, т.к. публичные методы продолжают торчать из объекта. И если пол проекта не меняют поля объекта, которые хотелось бы скрыть, то этим занимаются методы объекта, которые никто не мешает вызывать в разных местах проекта.
Самая простая возможность контролировать изменения объекта — сделать его неизменяемым.
Re[20]: DDD протаскивание других слоев через параметры методов Domain
Здравствуйте, alexsoff, Вы писали:
J>>У оо больше возможностей по написанию более независимого, модульного кода. A>Т.е. вы не видите разницу между двумя понятиями — процедурное и функциональное программирование и думаете, что это одно и тоже?
Эм, за функциональное программирование никто не говорит.
Вопрос в том как отличить процедурное от ОО.
Меня вполне устраивают описания этих различай в английской вики, т.к. они логичны.
Еще раз процитирую:
The focus of procedural programming is to break down a programming task into a collection of variables, data structures, and subroutines,
whereas in object-oriented programming it is to break down a programming task into objects that expose behavior (methods) and data (members or attributes) using interfaces.
Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data and code:
data in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods).
Или есть мнение что ооp и procedural programming различаются по другим критериям?
A>Т.е. вы не видите разницу между двумя понятиями — процедурное и функциональное программирование и думаете, что это одно и тоже?
Или вы хотите сказать что когда используете anemic модели, то пишите код на C# в функциональном стиле, а не в процедурном?
Хотел бы глянуть пример проекта (.net default: music store или что-то подобное) реализованного в функциональном стиле на C#.
Чем отличается oop, fp, pp?
Підтримати Україну у боротьбі з країною-терористом.
Здравствуйте, samius, Вы писали:
J>>В процедурном стиле: не используется сокрытие информации(модификаторы доступа), (т.к. поля/свойства всегда public). S>Информацию скрывали и до изобретения модификаторов доступа.
Да, можно скрыть неявным образом даже в паскале, напр. написав комментарий:"//Use this struct only from the XXX procedure.".
S>Модификаторы доступа здесь не наводят ясность, т.к. публичные методы продолжают торчать из объекта. И если пол проекта не меняют поля объекта, которые хотелось бы скрыть, то этим занимаются методы объекта, которые никто не мешает вызывать в разных местах проекта.
Публичные методы дают легальную возможность изменить состояние объекта, отсекая все остальные пути(не в счет рефлексию).
Что бы класс в ооп использовался правильно придумали: SOLID, GoF patterns.
Классическая идея ооп — изменяемый объект со временем.
S>Что же все так радикально? В вашем примере видел UserInformationDto. Ваш пример — образец процедурного стиля?
Нет, DTO — это объект без логики который используется,
_только_ для пересылки данных между подсистемами. Обычно это не неизменяемый объект. Но он так же может содержать логику по сериализации/десериализации.
S>Самая простая возможность контролировать изменения объекта — сделать его неизменяемым.
Ок. Делать все анемик модели неизменяемыми — это функциональный подход.
У функционального подхода есть свои минусы; C# не заточен по фп.
Підтримати Україну у боротьбі з країною-терористом.
Здравствуйте, #John, Вы писали:
J>Или вы хотите сказать что когда используете anemic модели, то пишите код на C# в функциональном стиле, а не в процедурном?
Я хочу сказать, что Anemic модель — шаг в сторону функционального программирования, а если и соблюдать иммутабельность для anamic моделей — то можно говорить, что это почти целевая точка движения современных языков. Я не спорю, что процедурная программа хуже ООП в плане понимания и поддержки, но я хочу сказать, что будущее все-таки за FP стилем, а тут уже Rich Model — очень трудно вписать.
Re[21]: DDD протаскивание других слоев через параметры методов Domain
Здравствуйте, #John, Вы писали:
J>Здравствуйте, samius, Вы писали:
J>>>В процедурном стиле: не используется сокрытие информации(модификаторы доступа), (т.к. поля/свойства всегда public). S>>Информацию скрывали и до изобретения модификаторов доступа.
J>Да, можно скрыть неявным образом даже в паскале, напр. написав комментарий:"//Use this struct only from the XXX procedure.".
В паскале есть модули, нет необходимости обходиться подобными комментариями. Можно создать полную аналогию PIMPL.
S>>Модификаторы доступа здесь не наводят ясность, т.к. публичные методы продолжают торчать из объекта. И если пол проекта не меняют поля объекта, которые хотелось бы скрыть, то этим занимаются методы объекта, которые никто не мешает вызывать в разных местах проекта.
J>Публичные методы дают легальную возможность изменить состояние объекта, отсекая все остальные пути(не в счет рефлексию).
Т.е. сокрытие модификатором доступа в C# — и есть тот самый комментарий // Use this field only from the XXX J>Что бы класс в ооп использовался правильно придумали: SOLID, GoF patterns.
не соглашусь.
SRP был сформулирован для модулей, мало касался объектов напрямую.
OCP был сформулирован так же для модулей, хоть и любителем объектов Мейером. Но активно использовался при проектировании ранее.
LSP — тут соглашусь, это касается исключительно объектов.
ISP — да, Мартин для программных интерфейсов. Но не думаю, что он был первый тут.
DIP — специфичная для объектов форма связности модулей.
В большинстве случаев принципы были сформулированы ранее для модулей, но переформулированы для объектов позднее.
GoF — целиком и полностью адаптация ранее использовавшихся практик для функций высших порядков (и не только), функторов и т.п.
Применение паттерна "Стратегия" можно обнаружить в стандартной процедуре сортировки в "C", в WinAPI и т.п... Остальное так или иначе использовалось за десятки лет до GoF-а в функциональных языках.
J>Классическая идея ооп — изменяемый объект со временем.
Я думаю, что идея ооп в декларации поведения при обработке сообщений. Не всякое поведение должно меняться со временем и зависеть от состояния объекта. Те же компараторы — вполне себе объекты и в большинстве случаев им не нужны изменения.
S>>Что же все так радикально? В вашем примере видел UserInformationDto. Ваш пример — образец процедурного стиля?
J>Нет, DTO — это объект без логики который используется, J>_только_ для пересылки данных между подсистемами. Обычно это не неизменяемый объект. Но он так же может содержать логику по сериализации/десериализации.
О, все-таки есть в ооп объекты без логики? А я встречал соображения что DTO — это структура данных, а не объект.
S>>Самая простая возможность контролировать изменения объекта — сделать его неизменяемым. J>Ок. Делать все анемик модели неизменяемыми — это функциональный подход.
Модель — это все-таки про поведение. В анемике у тех сущностей, которые в рич принято считать объектами, нет поведения. Т.е. это не модели, а описания структур, используемых в сообщениях.
J>У функционального подхода есть свои минусы; C# не заточен по фп.
Я бы сказал, что у C# есть свои минусы — он не заточен под фп. Но с каждым обновлением эти минусы значительно сокращаются. Сейчас писать на нем фп далеко не так кошмарно, как это было в 2005-м, например.
Re[22]: DDD протаскивание других слоев через параметры метод
Здравствуйте, alexsoff, Вы писали:
J>>Или вы хотите сказать что когда используете anemic модели, то пишите код на C# в функциональном стиле, а не в процедурном?
A>Я хочу сказать, что Anemic модель — шаг в сторону функционального программирования, а если и соблюдать иммутабельность для anamic моделей — то можно говорить, что это почти целевая точка движения современных языков.
Насчёт целевой точки, я бы добавил: если говорить про энтерпрайз, то долгое время властвовал подход анемичной модели с подачи Фаулера и Ко. Эта модель была ненастоящим ООП и ненастоящим процедурным, а неким бастардом, потом по мере распространения ФП этому бастарду в кровь впрыснули ДНК функциональщины, но тоже не-по "настоящему", а в виде эпизодических функциональных вставок, типа "тут мы заменим итератор на стрим с лямбдой". Мне кажется, анемик властвовал в умах потому, что энтерпрайз ещё только формировался, а у всемирного программистского разума есть некое ограничение по мощности, и первые пару десятков лет этот разум был занят формированием базовых основ энтерпрайза и поиском оптимальных решений типичных проблем (продумывание разных видов архитеуктур — слоистых, луковых, гексагональных... придумыванием EE-паттернов, разработкой транзакционных механизмов, механизмов DI, отимистик и пессимистик блокировок и т.д.), и у этого всеобщего разума не хватало сил на качественное продумывание самой сердцевины — бизнес-логики, поэтому первое время порешили что наиболее простым решением будет сделать тупо анемик-классы "почти как во взрослом ООП", а бизнес-логику тупо кидать в "почти процедурные" бизнес-сервисные методы (да, был SOLID, но он слишком был абстрактен и скорее как база и предтеча появления DDD). Но сейчас многие типичные проблемы решены и всеобщий энтерпрайзный разум обратил внимание на реализацию бизнес-логики и решил что пора вводить взрослое ООП — и всё больше проектов начинает обращать внимание на DDD (и главное, иметь силы и компетенции чтобы это самое DDD реализовывать, правда с разной степенью успеха и похожести на оригинальный DDD). Допустим, взять типичные энтерпрайз проекты 20-10 летней давности — основные усилия команды разрабов в том время заключались в том, чтобы реализовать типичные задачи энтерпрайза (и были жуткеи случаи когда целые команды разрабов не владели ни понятием транзакционности, ни блокировок, и всё это выкатывалось на прод и уже на живом продукте внешние более опытные консультанты накатывали на продукт транзакции и прочие патчи, чтобы система работала как энтепрайз), а сейчас каждый средний энтерпрайз-разраб уже ориентируется в этих типичных энтерпрайзных проблемах и умеет их решать "на раз", не нагружая свой мозг, и может направить высвободившуюся ментальную энергию на проработку фишек DDD — "настоящий" ООП: агрегаты, поведение в объектах (вместо поведения в процедурных бизнес-методах как в анемик-модели) с сохранением инварианта, репозитории, единый язык и т.д. Хотя делается это часто отвратно (на прод выводятся проекты, где DDD реализован криво), т.к. разрабы ещё не освоили DDD в полной мере, знаю эту дисциплину не полностью (а она вообще непроста к освоению), но уже пишутся реальные проекты на нём, на хабре всё больше статей, т.е. культура разработки в плане DDD развивается, что только радует. Ситуация с DDD сейчас очень похожа на паттерны: в начале про них все говорили (даже были требования от бизнеса и аналитиков о применении конкретных паттернов, конечно же часто вообще не к месту), разрабы очень часто готовили их неправильно или вообще дальше разговоров дело не заходило, а сейчас паттерны являются частью обще культуры разработки. И получается, что DDD — это ещё одна целевая точка развития, в которой ФП играет лишь роль а-ля "замены итераторов на стримы+лямбды", а скажем иммутабельность в DDD имеет самостоятельную ценность и без ФП, а как одна из стратегий сохранения инварианта объекта или как многопоточный паттерн.
>> Я не спорю, что процедурная программа хуже ООП в плане понимания и поддержки, но я хочу сказать, что будущее все-таки за FP стилем
Здравствуйте, gyraboo, Вы писали:
G>Здравствуйте, alexsoff, Вы писали:
J>>>Или вы хотите сказать что когда используете anemic модели, то пишите код на C# в функциональном стиле, а не в процедурном?
A>>Я хочу сказать, что Anemic модель — шаг в сторону функционального программирования, а если и соблюдать иммутабельность для anamic моделей — то можно говорить, что это почти целевая точка движения современных языков.
G>Насчёт целевой точки, я бы добавил: если говорить про энтерпрайз, то долгое время властвовал подход анемичной модели с подачи Фаулера и Ко. Эта модель была ненастоящим ООП и ненастоящим процедурным, а неким бастардом, потом по мере распространения ФП этому бастарду в кровь впрыснули ДНК функциональщины, но тоже не-по "настоящему", а в виде эпизодических функциональных вставок, типа "тут мы заменим итератор на стрим с лямбдой". Мне кажется, анемик властвовал в умах потому, что энтерпрайз ещё только формировался, а у всемирного программистского разума есть некое ограничение по мощности, и первые пару десятков лет этот разум был занят формированием базовых основ энтерпрайза и поиском оптимальных решений типичных проблем (продумывание разных видов архитеуктур — слоистых, луковых, гексагональных... придумыванием EE-паттернов, разработкой транзакционных механизмов, механизмов DI, отимистик и пессимистик блокировок и т.д.), и у этого всеобщего разума не хватало сил на качественное продумывание самой сердцевины — бизнес-логики, поэтому первое время порешили что наиболее простым решением будет сделать тупо анемик-классы "почти как во взрослом ООП", а бизнес-логику тупо кидать в "почти процедурные" бизнес-сервисные методы (да, был SOLID, но он слишком был абстрактен и скорее как база и предтеча появления DDD). Но сейчас многие типичные проблемы решены и всеобщий энтерпрайзный разум обратил внимание на реализацию бизнес-логики и решил что пора вводить взрослое ООП — и всё больше проектов начинает обращать внимание на DDD (и главное, иметь силы и компетенции чтобы это самое DDD реализовывать, правда с разной степенью успеха и похожести на оригинальный DDD). Допустим, взять типичные энтерпрайз проекты 20-10 летней давности — основные усилия команды разрабов в том время заключались в том, чтобы реализовать типичные задачи энтерпрайза (и были жуткеи случаи когда целые команды разрабов не владели ни понятием транзакционности, ни блокировок, и всё это выкатывалось на прод и уже на живом продукте внешние более опытные консультанты накатывали на продукт транзакции и прочие патчи, чтобы система работала как энтепрайз), а сейчас каждый средний энтерпрайз-разраб уже ориентируется в этих типичных энтерпрайзных проблемах и умеет их решать "на раз", не нагружая свой мозг, и может направить высвободившуюся ментальную энергию на проработку фишек DDD — "настоящий" ООП: агрегаты, поведение в объектах (вместо поведения в процедурных бизнес-методах как в анемик-модели) с сохранением инварианта, репозитории, единый язык и т.д. Хотя делается это часто отвратно (на прод выводятся проекты, где DDD реализован криво), т.к. разрабы ещё не освоили DDD в полной мере, знаю эту дисциплину не полностью (а она вообще непроста к освоению), но уже пишутся реальные проекты на нём, на хабре всё больше статей, т.е. культура разработки в плане DDD развивается, что только радует. Ситуация с DDD сейчас очень похожа на паттерны: в начале про них все говорили (даже были требования от бизнеса и аналитиков о применении конкретных паттернов, конечно же часто вообще не к месту), разрабы очень часто готовили их неправильно или вообще дальше разговоров дело не заходило, а сейчас паттерны являются частью обще культуры разработки. И получается, что DDD — это ещё одна целевая точка развития, в которой ФП играет лишь роль а-ля "замены итераторов на стримы+лямбды", а скажем иммутабельность в DDD имеет самостоятельную ценность и без ФП, а как одна из стратегий сохранения инварианта объекта или как многопоточный паттерн.
alexsoff писал о целевой точки движения именно языков, а не энтерпрайза как такового. Тут я с ним соглашусь. Движение именно языков в сторону DDD вовсе не видно. В сторону ФП — очевидно.
Re[24]: DDD протаскивание других слоев через параметры метод
Здравствуйте, samius, Вы писали:
S>alexsoff писал о целевой точки движения именно языков, а не энтерпрайза как такового. Тут я с ним соглашусь. Движение именно языков в сторону DDD вовсе не видно. В сторону ФП — очевидно.
Ну да, невнимательно прочитал исходную мысль)
Re[23]: DDD протаскивание других слоев через параметры метод
Здравствуйте, gyraboo, Вы писали:
G>И/или за DDD, по причинам, описанным выше))
Я ставлю на FP по одной причине = она из-коробки поддерживает параллельность и децентрализацию. Но это не значит, что я предлагаю DDD выкидывать на свалку. Многие верхнеуровневые концепции оттуда (например ограниченные контексты и т.д.) можно применять и в функциональном подходе.
Re[24]: DDD протаскивание других слоев через параметры метод
Здравствуйте, alexsoff, Вы писали:
A>Многие верхнеуровневые концепции оттуда (например ограниченные контексты и т.д.) можно применять и в функциональном подходе.
А что нового в этой концепции? Можно подумать логическое разделение не применялось раньше.
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re[25]: DDD протаскивание других слоев через параметры метод
Здравствуйте, AndrewJD, Вы писали:
AJD>А что нового в этой концепции? Можно подумать логическое разделение не применялось раньше.
применялось, но общеупотребимый термин сложился благодаря DDD