Re[13]: DDD протаскивание других слоев через параметры методов Domain
От: samius Япония http://sams-tricks.blogspot.com
Дата: 27.11.20 23:20
Оценка: +1
Здравствуйте, #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>
  код
J>полный пример

J>

J>public class Order
J>{
J>  // ..

J>  public Order(string userId, string userName, Address address, int cardTypeId, string cardNumber, string cardSecurityNumber,
J>                string cardHolderName, DateTime cardExpiration, int? buyerId = null, int? paymentMethodId = null) : this()
J>        {
J>            _buyerId = buyerId;
J>            _paymentMethodId = paymentMethodId;
J>            _orderStatusId = OrderStatus.Submitted.Id;
J>            _orderDate = DateTime.UtcNow;
J>            Address = address;

J>            // Add the OrderStarterDomainEvent to the domain events collection 
J>            // to be raised/dispatched when comitting changes into the Database [ After DbContext.SaveChanges() ]
J>            AddOrderStartedDomainEvent(userId, userName, cardTypeId, cardNumber,
J>                                       cardSecurityNumber, cardHolderName, cardExpiration);
J>        }

J>  public void AddOrderItem(int productId, string productName, decimal unitPrice, decimal discount, int units = 1)
J>        {
J>            var existingOrderForProduct = _orderItems.Where(o => o.ProductId == productId)
J>                .SingleOrDefault();

J>            if (existingOrderForProduct != null)
J>            {
J>                //if previous line exist modify it with higher discount  and units..

J>                if (discount > existingOrderForProduct.GetCurrentDiscount())
J>                {
J>                    existingOrderForProduct.SetNewDiscount(discount);
J>                }

J>                existingOrderForProduct.AddUnits(units);
J>            }
J>            else
J>            {
J>                //add validated new order item

J>                var orderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units);
J>                _orderItems.Add(orderItem);
J>            }
J>        }

J>    // ...

J>     public void SetPaidStatus()
J>        {
J>            if (_orderStatusId == OrderStatus.StockConfirmed.Id)
J>            {
J>                AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems));

J>                _orderStatusId = OrderStatus.Paid.Id;
J>                _description = "The payment was performed at a simulated \"American Bank checking bank account ending on XX35071\"";
J>            }
J>        }
J>}
J>


Но здесь обработчик лишь вызывает метод объекта, хотя мог бы иметь такой метод сам. Ну и какой смысл совать все такие методы в объекты?

J>В ApplicationLayer-e мы можем подписаться на все эти события и на каждое событие написать свой обработчик (DomainHandler). github


J>Из примеров проектов которые можно посмотреть:

J>https://github.com/aspnetboilerplate/aspnetboilerplate
J>https://github.com/zkavtaskin/Domain-Driven-Design-Example
J>https://github.com/dotnet-architecture/eShopOnContainers

J>и книга по ddd без воды: "Alexey Zimarev, Hands-On Domain-Driven Design with .NET Core — Tackling complexity in the heart of software by putting DDD principles into practice (2019)"


Эти примеры не отвечают на вопрос протаскивания других слоев через параметры методов?
Re[14]: DDD протаскивание других слоев через параметры методов Domain
От: #John Европа https://github.com/ichensky
Дата: 28.11.20 02:36
Оценка: :))
Здравствуйте, samius, Вы писали:


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),
что бы агрегат рут без дополнительных проверок, можно было просто взять и сохранить в бд целиком, одной транзакцией, и не получилось что мы потеряли часть данных.
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[15]: DDD протаскивание других слоев через параметры методов Domain
От: alexsoff Россия  
Дата: 28.11.20 06:48
Оценка:
Здравствуйте, #John, Вы писали:

J>Оставлю для дополнительного размышления ссылку на статью "Про Anemic Domain Model" . В принципе там все сказано.

Такие статьи очень трудно рассматривать всерьез, т.к. они используют прием из демагогии "отсылка к авторитету", Посчитайте сколько в статье встречается Фаулер и Мартин.
Еще раз — функциональные программы (т.е. написанные в функциональном сителе) очень легко параллелить между процессорами/машинами и т.д, потому как функциональный стиль предполагает иммутабельность с самого начала. Чего не скажешь о RichModel — в этом случае нужно осуществить много танцев с бубнами.
Для меня на данный момент (2021 год) это один из главных аргументов в пользу выбора подходов к проектированию. Т.е. общая тенденция идет к децентрализации.
Re: DDD протаскивание других слоев через параметры методов D
От: gyraboo  
Дата: 28.11.20 08:19
Оценка: 4 (1) +2
Здравствуйте, #John, Вы писали:

J>как вы боритесь с тем, что в методы entity, через параметры, в Domain слой протягиваютя классы из других слоев?


Тут уже много всего правильного написали. Могу рассказать как это обычно делается в Java энтерпрайзе в слоистой архитектуре:
Классы типа Logger не относятся к обычному слою, они относятся к классу т.н. сквозной функциональности, не связанной с бизнес-логикой, а умеющей внедряться в любой слой. Туда же относятся transaction и security менеджеры. Эти классы DI-фреймворк (Спринг или JEE) сам инжектит в поля класса Enity (когда мы помечаем эти поля @Autowired или @Inject), их не надо передавать в явном виде в методах.

Похоже, что в приведенном примере все протягиваемые туда классы относятся либо к сквозной функциональности, либо к слою Util (DateTimeProvider, NumberProvider — это тоже особый случай, а не обычный слой, набор классов или 3-rdparty библиотек, не знающих про бизнес-логику и который могут использовать все обычные слои приложения).

А если возникает задача протащить между слоями именно доменные объекты, то есть паттерн DTO, причём он есть как в анемичной модели так и в DDD.
Отредактировано 28.11.2020 8:21 gyraboo . Предыдущая версия . Еще …
Отредактировано 28.11.2020 8:20 gyraboo . Предыдущая версия .
Re[15]: DDD протаскивание других слоев через параметры методов Domain
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.11.20 13:45
Оценка:
Здравствуйте, #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
От: #John Европа https://github.com/ichensky
Дата: 28.11.20 16:59
Оценка: 16 (1) +1 -1
Здравствуйте, 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).


Биологические клетки свое состояние держат внутри себя, имеют разный набор данных(митохондрии, рыбосому, цитозоль), имеют разное поведение, и общаются посредством передачи ионов и молекул через каналы.
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[17]: DDD протаскивание других слоев через параметры методов Domain
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.11.20 23:09
Оценка: +2
Здравствуйте, #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
От: #John Европа https://github.com/ichensky
Дата: 29.11.20 01:23
Оценка: +1 -1
Здравствуйте, samius, Вы писали:

S>Как так? Отличия лишь в синтаксисе и такой глубокий вывод о стиле... Метод ChangeSkin заменен методом set_skinColor. Больше ничего не изменилось...


S>А если так?

S>
S>class Chameleon
S>{
S>    public Color skinColor { get; }
S>}
S>


Тоже самое. Стиль программирования `procedural vs oo` зависит от того как используется класс: как структура данных или как объект у которого все данные и логика прописаны в одном месте.

S>Кстати, не считаю, что процедурный стиль плох.

У оо больше возможностей по написанию более независимого, модульного кода.
В процедурном стиле: не используется сокрытие информации(модификаторы доступа), (т.к. поля/свойства всегда public).
потому может произойти такая ситуация, что код по изменению поля структуры будет раскидан в разных местах проекта/класса,
а изменение этого поля будет зависеть от разных условий. А код который меняет это поле будет зависеть еще от другого код,
а тот еще и еще. И когда понадобится добавить новую логику которая будет дополнительно как-то менять поле,
нам придется вместо того что бы подправить код в одном классе/объекте продебажить пол проекта и найти место куда воткнуть наш код.
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[19]: DDD протаскивание других слоев через параметры методов Domain
От: alexsoff Россия  
Дата: 29.11.20 04:50
Оценка: +2
Здравствуйте, #John, Вы писали:

J>У оо больше возможностей по написанию более независимого, модульного кода.

Т.е. вы не видите разницу между двумя понятиями — процедурное и функциональное программирование и думаете, что это одно и тоже?
Re[19]: DDD протаскивание других слоев через параметры методов Domain
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.11.20 05:40
Оценка: 1 (1) +3
Здравствуйте, #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
От: #John Европа https://github.com/ichensky
Дата: 29.11.20 13:39
Оценка:
Здравствуйте, 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?
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[20]: DDD протаскивание других слоев через параметры методов Domain
От: #John Европа https://github.com/ichensky
Дата: 29.11.20 17:04
Оценка:
Здравствуйте, samius, Вы писали:

J>>В процедурном стиле: не используется сокрытие информации(модификаторы доступа), (т.к. поля/свойства всегда public).

S>Информацию скрывали и до изобретения модификаторов доступа.

Да, можно скрыть неявным образом даже в паскале, напр. написав комментарий:"//Use this struct only from the XXX procedure.".

S>Модификаторы доступа здесь не наводят ясность, т.к. публичные методы продолжают торчать из объекта. И если пол проекта не меняют поля объекта, которые хотелось бы скрыть, то этим занимаются методы объекта, которые никто не мешает вызывать в разных местах проекта.


Публичные методы дают легальную возможность изменить состояние объекта, отсекая все остальные пути(не в счет рефлексию).
Что бы класс в ооп использовался правильно придумали: SOLID, GoF patterns.
Классическая идея ооп — изменяемый объект со временем.

S>Что же все так радикально? В вашем примере видел UserInformationDto. Ваш пример — образец процедурного стиля?


Нет, DTO — это объект без логики который используется,
_только_ для пересылки данных между подсистемами. Обычно это не неизменяемый объект. Но он так же может содержать логику по сериализации/десериализации.

S>Самая простая возможность контролировать изменения объекта — сделать его неизменяемым.

Ок. Делать все анемик модели неизменяемыми — это функциональный подход.

У функционального подхода есть свои минусы; C# не заточен по фп.
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[21]: DDD протаскивание других слоев через параметры методов Domain
От: alexsoff Россия  
Дата: 29.11.20 17:49
Оценка:
Здравствуйте, #John, Вы писали:

J>Или вы хотите сказать что когда используете anemic модели, то пишите код на C# в функциональном стиле, а не в процедурном?


Я хочу сказать, что Anemic модель — шаг в сторону функционального программирования, а если и соблюдать иммутабельность для anamic моделей — то можно говорить, что это почти целевая точка движения современных языков. Я не спорю, что процедурная программа хуже ООП в плане понимания и поддержки, но я хочу сказать, что будущее все-таки за FP стилем, а тут уже Rich Model — очень трудно вписать.
Re[21]: DDD протаскивание других слоев через параметры методов Domain
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.11.20 19:16
Оценка: +1
Здравствуйте, #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 протаскивание других слоев через параметры метод
От: gyraboo  
Дата: 29.11.20 19:29
Оценка: :)
Здравствуйте, alexsoff, Вы писали:

J>>Или вы хотите сказать что когда используете anemic модели, то пишите код на C# в функциональном стиле, а не в процедурном?


A>Я хочу сказать, что Anemic модель — шаг в сторону функционального программирования, а если и соблюдать иммутабельность для anamic моделей — то можно говорить, что это почти целевая точка движения современных языков.


Насчёт целевой точки, я бы добавил: если говорить про энтерпрайз, то долгое время властвовал подход анемичной модели с подачи Фаулера и Ко. Эта модель была ненастоящим ООП и ненастоящим процедурным, а неким бастардом, потом по мере распространения ФП этому бастарду в кровь впрыснули ДНК функциональщины, но тоже не-по "настоящему", а в виде эпизодических функциональных вставок, типа "тут мы заменим итератор на стрим с лямбдой". Мне кажется, анемик властвовал в умах потому, что энтерпрайз ещё только формировался, а у всемирного программистского разума есть некое ограничение по мощности, и первые пару десятков лет этот разум был занят формированием базовых основ энтерпрайза и поиском оптимальных решений типичных проблем (продумывание разных видов архитеуктур — слоистых, луковых, гексагональных... придумыванием EE-паттернов, разработкой транзакционных механизмов, механизмов DI, отимистик и пессимистик блокировок и т.д.), и у этого всеобщего разума не хватало сил на качественное продумывание самой сердцевины — бизнес-логики, поэтому первое время порешили что наиболее простым решением будет сделать тупо анемик-классы "почти как во взрослом ООП", а бизнес-логику тупо кидать в "почти процедурные" бизнес-сервисные методы (да, был SOLID, но он слишком был абстрактен и скорее как база и предтеча появления DDD). Но сейчас многие типичные проблемы решены и всеобщий энтерпрайзный разум обратил внимание на реализацию бизнес-логики и решил что пора вводить взрослое ООП — и всё больше проектов начинает обращать внимание на DDD (и главное, иметь силы и компетенции чтобы это самое DDD реализовывать, правда с разной степенью успеха и похожести на оригинальный DDD). Допустим, взять типичные энтерпрайз проекты 20-10 летней давности — основные усилия команды разрабов в том время заключались в том, чтобы реализовать типичные задачи энтерпрайза (и были жуткеи случаи когда целые команды разрабов не владели ни понятием транзакционности, ни блокировок, и всё это выкатывалось на прод и уже на живом продукте внешние более опытные консультанты накатывали на продукт транзакции и прочие патчи, чтобы система работала как энтепрайз), а сейчас каждый средний энтерпрайз-разраб уже ориентируется в этих типичных энтерпрайзных проблемах и умеет их решать "на раз", не нагружая свой мозг, и может направить высвободившуюся ментальную энергию на проработку фишек DDD — "настоящий" ООП: агрегаты, поведение в объектах (вместо поведения в процедурных бизнес-методах как в анемик-модели) с сохранением инварианта, репозитории, единый язык и т.д. Хотя делается это часто отвратно (на прод выводятся проекты, где DDD реализован криво), т.к. разрабы ещё не освоили DDD в полной мере, знаю эту дисциплину не полностью (а она вообще непроста к освоению), но уже пишутся реальные проекты на нём, на хабре всё больше статей, т.е. культура разработки в плане DDD развивается, что только радует. Ситуация с DDD сейчас очень похожа на паттерны: в начале про них все говорили (даже были требования от бизнеса и аналитиков о применении конкретных паттернов, конечно же часто вообще не к месту), разрабы очень часто готовили их неправильно или вообще дальше разговоров дело не заходило, а сейчас паттерны являются частью обще культуры разработки. И получается, что DDD — это ещё одна целевая точка развития, в которой ФП играет лишь роль а-ля "замены итераторов на стримы+лямбды", а скажем иммутабельность в DDD имеет самостоятельную ценность и без ФП, а как одна из стратегий сохранения инварианта объекта или как многопоточный паттерн.

>> Я не спорю, что процедурная программа хуже ООП в плане понимания и поддержки, но я хочу сказать, что будущее все-таки за FP стилем


И/или за DDD, по причинам, описанным выше))
Отредактировано 29.11.2020 19:31 gyraboo . Предыдущая версия .
Re[23]: DDD протаскивание других слоев через параметры метод
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.11.20 19:36
Оценка:
Здравствуйте, 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 протаскивание других слоев через параметры метод
От: gyraboo  
Дата: 29.11.20 19:52
Оценка:
Здравствуйте, samius, Вы писали:

S>alexsoff писал о целевой точки движения именно языков, а не энтерпрайза как такового. Тут я с ним соглашусь. Движение именно языков в сторону DDD вовсе не видно. В сторону ФП — очевидно.


Ну да, невнимательно прочитал исходную мысль)
Re[23]: DDD протаскивание других слоев через параметры метод
От: alexsoff Россия  
Дата: 30.11.20 02:51
Оценка: +1
Здравствуйте, gyraboo, Вы писали:

G>И/или за DDD, по причинам, описанным выше))

Я ставлю на FP по одной причине = она из-коробки поддерживает параллельность и децентрализацию. Но это не значит, что я предлагаю DDD выкидывать на свалку. Многие верхнеуровневые концепции оттуда (например ограниченные контексты и т.д.) можно применять и в функциональном подходе.
Re[24]: DDD протаскивание других слоев через параметры метод
От: AndrewJD США  
Дата: 30.11.20 16:39
Оценка:
Здравствуйте, alexsoff, Вы писали:

A>Многие верхнеуровневые концепции оттуда (например ограниченные контексты и т.д.) можно применять и в функциональном подходе.

А что нового в этой концепции? Можно подумать логическое разделение не применялось раньше.
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re[25]: DDD протаскивание других слоев через параметры метод
От: alexsoff Россия  
Дата: 30.11.20 18:47
Оценка:
Здравствуйте, AndrewJD, Вы писали:

AJD>А что нового в этой концепции? Можно подумать логическое разделение не применялось раньше.

применялось, но общеупотребимый термин сложился благодаря DDD
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.