Senior .Net Developer
  • Предметно-орієнтоване проєктування (DDD): у чому користь підходу і хто його використовує

    ДДД/гексональна архітектура

    ДДД != гексональна архітектура

    хопа — монго на касандру поміняли!

    Із практики: хопа і GDPR => хопа і потрібно зберігати частину даних в окремій базі у зашифрованому вигляді. І при цьому об’єкт потрібно зібрати з декількох баз або навіть сервісів. В одному випадки ви лише змінюєте внутрішню реалізацію репозіторію, у випадку з лейзи лоадінг (де ви де факто зав’язані на можливості ОРМ) вам буде дуже боляче.

    або сподіваючись

    Не сподіваючись, а розпитуючи у бізнесу реальні сценарії. Інакше ви будете оптімізувати те, що нікому взагалі не потрібно і чого ніколи не станеться. Замість того щоб сконцентруватися на оптимізації реальних сценаріїв.

    OrderItems завжди завантажуються? Навіть для completeOrder?

    Якщо ви маєте на увазі кінцевий стан, то у вас вже немає мутацій, читайте як хочете використовуючи рид модель.

    У key-value БД може і не проблема весь документ витягувати, але для реляційних БД це занадто дорогий підхід.

    Ну то використовуйте технічні інструменти які більш оптимальні для вашої задачи.

    де агрегат в рядок таблиці влізає, а колекції і колекції колекцій.

    Тут інше питання, як буде виглядати код і скільки буде коштувати його підтримка якщо ви будете особливим чином вибирати дані під кожен сценарій агрегату. І так, якщо дійсно буде проблема з перформансом, то можливо вам доведеться це робити. Але у багатьох випадках це може означати що у вас невірно вибрані границі агрегату.

  • Предметно-орієнтоване проєктування (DDD): у чому користь підходу і хто його використовує

    Якщо правильно зрозумів, у ДДД домен — це бізнес-суть, ентіті — це домен + id (і, скоріш за все, version),

    Не впевнений що ви правильно це розумієте.

    Спочатку у сенсі DDD. Entity це частина бізнес моделі, яку вам потрібно відслідковувати і змінювати на проміжку часу що має сенс з точки зору вашого бізнесу. Коли мы говоримо про identity, ми маємо на увазі логічну унікальність з точки зору бізнесу.

    Наведу такий приклад, у вас є програма лояльності та учасник програми лояльності LoyaltyMember. У фізичному житті це людина. З точки зору бізнесу вам важливий проміжок часу з моменту реєстрації у програмі лояльності до виходу із програми лояльності. Тому що вам потрібно нараховувати та списувати бонуси. Якщо одна і таж фізична людина вийде з програми лояльності, а через рік вирішить зареєструватися знов, вам може бути не цікаво з точки зору бізнесу що це знову таж сама людина. У вашому бізнес домені це вже новий LoyaltyMember, якому ви нараховуєте бонуси з нуля. Це логічна унікальність.

    У ролі логічної унікальності може використовуватись як бізнес властивість, наприклад номер картки лояльності, ключова умова, ця характеристика не повинна змінюватись протягом логічного життя бізнес сутності, так і сурогатний Id (автоінкремент, GUID і т.п.), який формально не є частиною домену, але дозволяє технічно ідентифікувати збережений бізнес об’єкт.

    І тут ми повільно переходимо до технічної реалізації. Навіть якщо ви використовуєте бізнес властивість у якості унікального ключа, на рівні DataAccess технічно простіше оперувати сурогатними ключами. І тут у нас з’являється сурогатний Id який ми можемо використовувати наприклад в джоінах.

    Version це так само технічна частина, яка, наприклад може допомогти в контролі паралельного доступу (наприклад реалізації оптимістичних блокувань) інвалідації кешу і т.п. Але наврядчи ваш бізнес оперує поняттям версії учасника програми лояльності. У той же самий час, якщо вам технічно треба мати версію на рівні класів Domain Model, не бачу великого сенсу її не добавити тільки тому що це не відповідає догмам.

    Підтримав: Andriy Slobodyanyk
  • Предметно-орієнтоване проєктування (DDD): у чому користь підходу і хто його використовує

    Гадаю, в загальному випадку можна прийняти, що читання «як один документ» вдарить по перформансу.

    Загальний випадок це абстрактний кінь у вакуумі.

    Бо в кожному випадку можуть бути різні кордони агрегату. Умовно, атачмент як файл це не частина проекту, але проект містить референс на збережений файл.

    Також з точки зору конкретного домену можуть бути логічні рестрікшени з огляду на які технічні проблеми які ви вирішуєте, можуть взагалі не бути проблемами у реальному житті. Умовно, ви вирішуєте як оптімізувати загрузку графа з мільйоном тасок. А на практиці у 99% юзерів буде не більше 50-100 тасок.

  • Предметно-орієнтоване проєктування (DDD): у чому користь підходу і хто його використовує

    Досить умовна схема:

    1. Завантажити агрегат.
    2. Перевірити те, що команда може бути виконана на поточному стані агрегату.
    3. Мутувати агрегат (операція може бути імперативною, де класична Rich Model перевіряє себе та мутує себе, або функціональною, де state може бути виражений за допомогою імутабельної Anemic Model (яка не обов’язково дорівнює Data Model), бізнес операції за допомогою чистих функцій, умовно Project state n+1 = CompleteTask(Project state n, taskId), але ви повинні гарантувати що наступна команда буде виконуватись на Project state n+1).
    4. Зберегти зміни.

    Якщо у вас є черга команд, п.1 можно виконувати не для кожної команди, а для пачки команд із черги. Після п.4 беремо наступну команду із черги і переходимо до п.2. На схожому принципі побудована т.з. Actor Model.

    Команди повинні аплаїтись послідовно, навіть якщо немає черги (або песімистичне блокування ДО завантаження, на період виконання команди, або оптімістичне блокування) інакше п.2 може дати помилковий результат.

  • Предметно-орієнтоване проєктування (DDD): у чому користь підходу і хто його використовує

    Давайте визначимось з терміном Entity. За контекстом я так розумію що ви маєте на увазі Entity не у сенсі DDD, а модель класів які відповідають структурі БД та мапляться на БД за допомогою ORM. Я пропоную далі називати це Data Model.

    Чи є догмою що Data Model і Domain Model повинні бути розділені? Загальна відповідь — ні, це не догма. У простих випадках ви можете мапити Domain Model на базу напряму, і не мати проміжної Data Model.

    Але з підвищенням складності моделі у такому випадку у вас практично не буде простору для маневру.

    На вашому прикладі, Domain Model може виглядати як Project (root task) яка має колекцію Task. Кожен Task має свою колекцію Subtasks.

    А ось на рівні Data Model, це може бути таблиця
    Tasks(Id, ProjectId, ParentTaskId, Description, Status)

    Наявність ProjectId дозволить швидко за допомогою одного плейн запиту завантажити увесь Project.

    Або це навіть може бути таблиця Project(Id, Name, ProjectJson, Version) і відповідна ProjectEntity (яка не повинна виходити за контур Data Access Layer).

    Репозіторій приймає і повертає об’єкти Domain Model.
    Конвертація Domain Model в Data Model, це внутрішні знання реалізації репозіторію. Зміна концепції зберігання (умовно ви вирішили зберігати ваш Project не в базі а в S3 у вигляді файлу) не повинна вплинути на Domain Model ніяким чином.

    Repeatable Read вам жодним чином не допоможе. Бо по перше, щоб заблокувати усі таски проекту за його допомогою, вам потрібно (сюрпрайз) їх усі «прочитати», а по друге, тримати відкритим конекшн до бази між усіма ітераціями lazy load.

  • Предметно-орієнтоване проєктування (DDD): у чому користь підходу і хто його використовує

    Питання не про DDD. Точніше від DDD (і то тактичного) тут лише те, що кожна рут таска включно зі своєю ієрархією виглядає як агрегат. І потрібно знайти технічне рішення для забезпечення кінцевого набору можливих мутацій цього агрегату, таким чином, щоб він у цілому залишався у консістентному стані. Ви навели лише декілька юзкейсів. Наприклад, чи можно додати нову сабтаску до сабтаски до таски яка вже done? Як це вплине на статуси? Чи можно повернути сабтаску із done в in-progres? Що при цьому повинно статись з парент тасками? Окреме питання, — скільки юзерів у системі? Чи можуть два юзера змінювати статуси тасок із однієї ієрархії у паралель? Якщо так, завантаження ієрархії в пам’ять, або навіть тримання її в пам’яті під час активної роботи може виявитись меншим злом порівняно з боротьбою з дідлоками на базі, якщо ви будете намагатись зробити це за рахунок підвищення рівня ізоляції (якщо ми розглядаємо реляційні бази). Якщо сотні юзерів можуть змінювати одну ієрархію, можливо взагалі потрібна черга команд. Якщо ієрархія належить тільки одному юзеру, наврядчи у ній буде більш ніж декілька сотень тасок. Можливо має сенс зберігати та читати ієрархію як один документ. Але ж, це все технічна реалізація.

    P.S. якщо є зміни у паралель lazy load левела за левелом це погана ідея. Бо у вас різні частини графу можуть належати вже до різних версій ієрархії в цілому. Взагалі lazy load у більшості випадків створює більше проблем ніж вирішує.

  • Предметно-орієнтоване проєктування (DDD): у чому користь підходу і хто його використовує

    Парадигма це лише інструмент висловлювання, такий самий як мова програмування, фреймворки, патерни тощо. Як саме цей інструмент використовувати, — це вже інше питання. Як було сказано вище, DDD це про філософію. Хоч з Rich Model, хоч з Anemic Model, хоч з OOP, хоч з FP, хоч з CQRS на додачу з Event Sourcing, хоч без можно написати код так, що буде виглядати що основна мета бізнесу це Add, Update та Delete строк у БД, а можно намагатись висловлювати бізнес процеси, звісно на тому рівні абстракцій та з тим рівнем деталей, який нам важливий с точки зору задачі, яку ми вирішуємо. Events, Commands можуть мати бізнес сенс а можуть бути у стилі UpdateRowCommand, SomeRowUpdatedEvent і т.п.

    Взагалі, якщо брати книгу Еванса, там лише декілька розділів можно напряму притягнути до ООП. Але 80..90% статей про DDD пишуть нажаль ті, хто тільки початок книги і прочитав.

    «Raw Data», це, до речі, також абстракція, яка містить ті дані та під тим кутом зору які важливі для конкретної задачі а не описують «весь всесвіт».

  • Предметно-орієнтоване проєктування (DDD): у чому користь підходу і хто його використовує

    Взагалі то ДДД це про висловлювання бізнес різонінгу у коді а не про парадигму програмування.

    Умовно BulkUpdatePaymentsStatuses (сугубо технічна назва, апдейтимо статус але фіг його знає чому, сказали потрібно на учора от і апдейтимо, можемо хоч з Paid у New, нам не шкода) vs SubmitPaymentsToProcessor, де вже виражена конкретна бізнес операція конкретного процесу і інкапсульовані перевірки (мабуть ми не хочемо сабмітити транзакцію по другому колу).

    Чомусь усі вважають что обов’язково DDD==OOP==Reach Model. OOP це тільки одна з технік яка може бути корисною (якщо вміти її готувати). Але не гірше, а іноді і краще, це можно і на FP зробити.

    Підтримав: Dmitry Bugay
  • Абстрактный класс и интерфейс :D

    Самое прикольное, что те кто не могут ответить на этот вопрос, или отвечает на него чисто с технической точки зрения, потом радостно создадут абстрактный класс размеры и унаследуют от него слона и дом. Дом is Размеры и Слон is Размеры, логически маразм, но технически то все работает.

    Підтримали: Oleg Beloy, Andrii Zaiats
  • Как правильно извлечь связанные данные без ORM?

    Гм, а причем тут с ОРМ или без? С ОРМ вам придется отвечать на теже самые вопросы. В чем великий смысл гарантировать целостность для вашей задачи? Что будет если новая книга или новый автор добавятся через пол секунды после вычитки данных?

    Підтримав: Gennady Dogaev
  • Пандемия коронавируса SARS-CoV-2

    Тут вопрос корректно ли сравнивать разные года в разрезе регионов наиболее сильно пострадавших от данного конкретного вируса в этом году. В предыдущие года повышение смертности от чего то еще могло приходится на другие регионы. Ну это как, к примеру, если в году X была бы вспышка вируса А в пределах Европы и одиночные случаи в Азии, а в году Y была бы вспышка вируса Б в пределах Азии и единичные случаи в Европе, сделать вывод сравнив годы X и Y взяв данные по Азии что вирус Б более смертельный чем вирус А. Т.е. потенциально, такое утверждение могло бы оказаться истиной, но это было бы совпадением, а не железобетонным выводом из такого сравнения.

  • Пандемия коронавируса SARS-CoV-2

    Ну скажем так, в моем понимании численность населения это путь. Карантин влияет на скорость (ну или пожалуй если точнее, то на ускорение, но смысл будет тем же). Если один проехал за час 10% от 100 км а второй 5% от 200 км, то это не говорит о том что у первого скорость в 2 раза больше, а говорит о том что у него путь в два раза меньше. Как то так если очень утрированно. А вот на счет отсутствия прямой зависимости между строгостью мер в разных странах и скоростью распространения, абсолютно согласен. Но тут сильно могут влиять разные методики подсчета, национальные особенности, иррациональность действий с перепугу, психология (слабее карантин, на подсознание могут больше сами себя ограничивать, опасаясь недостаточных действий со стороны властей) и куча других факторов. Карантин очень выраженный эффект дал в Австрии. В противоположность Швеции, по крайней мере на данном этапе, получилось выстроить эдакую самобалансирующуюся систему, что намного круче в долгосрочной перспективе (если конечно таки не пойдет в разнос).

  • Пандемия коронавируса SARS-CoV-2

    Так в Бельгии и численность населения почти в два раза меньше. Если скорость распространения одинакова, то за один и тот же промежуток времени от начала распространения число заболевших должно быть ± одинаково вне зависимости от численности населения (по крайней мере на начальных этапах когда плотность людей с иммунитетом еще не велика). Что при отличии в численности населения в два раза, даст в два раза больший процент заболевших от численности населения ну или в расчете на миллион.

  • Anemic Domain Model vs Rich Domain Model в Spring

    З.Ы. а вообще я побывал в обоих лагерях, как ярых противников, так и сторонников. И действительно, проблема в том, что мало кто умеет готовить те самые модели. Часто приходится наблюдать классическое «из чего состоит слон? Из хобота ушей и бегемота». Ну или классический пример, с Product.IsAvailable который вы привели выше. С другой стороны меня еще больше кумарят помойки с «SuperUtility» в которые пихают все подряд, вместо того, чтобы разбросать ответственность по специфичным классам. Тоже классика, если не знаешь что это, назови «Utility» и запихни куда нить в инфрастрактучур.

    Підтримали: Dmytro Lapshyn, Denys Poltorak
  • Anemic Domain Model vs Rich Domain Model в Spring

    товар з каталогу не має вирішувати, чи він доступний, наприклад, клієнту з якоїсь країни.

    дык я и не писал что это будет решать сам товар с каталога. В модели такую применимость я бы выразил спецификацией (спецификацию я тоже отношу к модели).

    До того ж, каталог товарів read only, немає зміни стану об’єктів, немає запису їх в базу, тобто це, ну, ніяк не загальний кейс rich domain model.

    Именно поэтому я написал оговорку

    (формально это уже не про рич модель)

    На счет агрегата и его мутабельности, ну можете не мутировать агрегат, а считать его срез на момент времени суммой всех иммутабельных событий по данному агрегату на тот самый момент времени и хранить только события. Дело вкуса. В большинстве случаев, как по мне, удобно хранить и события и последний срез стейта агрегата.

  • Anemic Domain Model vs Rich Domain Model в Spring

    В третьем примере их нет (если это чистое проксирование, плюс, возможно, секьюрити). Во втором условно нет, но зависит от того, из чего собирается продукт. Допустим под капотом, может быть поход еще в три сервиса, на основании которых вы соберете и вернете «продукт каталога». Возможно, у вас будет логика вычисления применимости продукта для разных групп потребителей или еще что то в этом духе. Ее можно выразить стейтлес сервисом, а можно методами модели. Мне больше нравится когда доменный сервис отвечает за получение данных (в самом простом случае это может быть даже аппликейшн сервис), а модель за вычисления, гораздо проще покрыть логику вычисления юнит тестами ничего не мокая от слова совсем. Если вы будете кешировать данные, и у вас нет иммутабельности из коробки, то написание рид онли моделей поможет реализовать иммутабельность для безопасного кеширования. Или еще вариант, вы не доверяете полученным данным, и хотите сразу создать объект модели, который проверит их валидность и будет гарантированно в валидном состоянии либо упадет с исключением (формально это уже не про рич модель), и только после етого смапить его на ДТО и отдать наружу. В первом примере результат начисления процентов может быть представлен в виде явно выраженного агрегата который будет сохраняться, и как вариант проценты по вкладу будут набрасываться на этот агрегат в виде доменных событий каждый месяц. Дисклаймер: все выше перечисленное не является единственно «правильным» вариантом реализации, а скорее одним из вариантов решения проблемы.

  • Anemic Domain Model vs Rich Domain Model в Spring

    Сильно зависит от того какого рода сервис. Сервис начисления процентов по банковским вкладам, сервис который просто возвращает каталог продуктов и сервис который является фасадом для внешних вызовов, и проксирует вызовы на внутренние сервисы, три абсолютно разных примера. Это примерно как «что лучше танк или снайперская винтовка»

  • Anemic Domain Model vs Rich Domain Model в Spring

    Имхо как раз наоборот, Rich Model гораздо сложнее неправильно использовать, ибо стейт защищен методами и костыль который что то мутирует сбоку сложнее пропустить на ревью. Ну и при правильном написании она практически не связана с моделью базы (репозитории принимающие и возвращающие исключительно объекты доменной модели в помощь, а что там внутри репозитория его сложности, пусть хоть в несколько баз раскладывает в соответствии с требованиями того же GDPR). Но с чем согласен, что, как минимум, на начальных этапах разработки требуется достаточно высокая квалификация разработчиков. Ну и весьма дорога в разработке на начальном этапе, поэтому имеет смысл применять на долгоиграющих проектах.

  • Курс гривні

    minfin.com.ua/ua/2019/05/27/37889128

    Вот собственно и ответ. Чуть повысился спрос, чуток подрос, и вообще посмотрите историю курса скажем за 2018 год.

  • Вибори президента України 2019. 2-й тур. [Опитування]

    Ну так все верно. Не понятно только почему теперь оппоненту закидывают мол «вы слышали, он еще и референдум проводить собирается»

← Сtrl 123456...10 Ctrl →