Re[36]: DDD для небольших проектов.
От: takTak  
Дата: 25.02.20 08:03
Оценка:
T>>велик соблазн выделить оперaцию чтения и , соответственно, калькуляции в отдельную операцию типа чего-то такого: http://www.codinginstinct.com/2011/04/queries-aggregates-ddd.html, но всё-таки ценообразование — , поэтому надо ещё посмотреть, куда это относится

T>>вот само управление скидками-надценками интереснее. как это сейчас реализовано? как эта информация сохраняется? т.е. это было бы реальной задачей агрегата

S>Сейчас? Сейчас у ентити "Реселлер" есть атрибут "Markup". Если он Null, то берётся дефолтный маркап, если не null — то берётся он.
S>Плюс есть ентити "ResellerProductGroupMarkup", которая сопоставляет реселлеру И группе наценку.
S>Так что для каждого товара выполняется следующий алгоритм:
S>1. Если есть запись в ResellerProductGroupMarkup где ResellerID = @CurrentReseller and @ProductGroupID = @ProductGroup, то берём из markup из неё.
S>2. Иначе, если Reseller.Markup is not null там, где Reseller.Id = @CurrentReseller, то берём его
S>3. Иначе берём DefaultMarkup.

S>Как-то так.


это какие-то заранее агрегированные, т.е. заранее подсчитанные величины или они считаются на лету для каждого продукта в списке?

и что будет, когда , например, понадобится менять скидку/надценку в зависимости от суммы сделанных покупок или статуса покупателя?
Отредактировано 25.02.2020 8:04 takTak . Предыдущая версия .
Re[20]: DDD для небольших проектов.
От: Poopy Joe Бельгия  
Дата: 25.02.20 08:14
Оценка: 5 (1)
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Poopy Joe, Вы писали:


PJ>>И что? Это этого количество путей не становится экспотенциальным.

S>Путей — нет. Типов — да.
И типов нет. Но, допустим, что да, целях дискуссии. Если много путей, то это повышает цикломатическую сложность. А в чем проблема с типами? А функций? Чем типы отличаются от функций?

S>Ну, хорошо, если бизнес-сущность. А если состояние бизнес сущности — то типов, на первый взгляд, может оказаться слишком много.

Как ты определяешь много или мало? И что ты делаешь в этом случае в ООП? Кладешь все в один god-class?

S>И без помощи компилятора (например, проверяющего полноту паттерн-матчинга) мы под их объёмом упадём.

Что это значит?

S>>>Да, не зависит. Но мне непонятно, как вы собираетесь получать из ShippableOrder при помощи одной операции два разных типа — UnpaidShippedOrder и PaidShippedOrder.

PJ>>Никак это один тип: UnpaidShippedOrder | PaidShippedOrder, или OneOf<UnpaidShippedOrder, PaidShippedOrder>
S>Хм. Ну вы всего лишь передвинули проверку реального типа дальше по цепочке. Такой трюк выигрывает у if-else только в том случае, если компилятор отлавливает некорректности.
S>В C# нет поддержки OneOf, поэтому никакого улучшения по сравнению с if-else я не вижу.
Че? OneOf c# тип.

PJ>>Т.е. администратор может изменить правила и отправить себе бесплатно посылку, без постоплаты? Тогда мы о разном говорим.

S>Конечно может. В реальных системах администратор может очень много всего. Его контролирует не система типов (это всё равно невозможно), а административные практики.
Система типов гарантирует инваринт системы. Ты сейчас говоришь, что инвариант системы тебя не волнует в принципе и любой залетевший дятел может сломать дом, если не опасается последствий или не знает о таковых.
Такого из начальной постановки задачи никак не следовало и мы просто говорим каждый о своем.

S>Вот у меня лично есть доступ к продакшн-системам в нескольких регионах мира. Скажем, выписать себе подписку OneDrive на десяток терабайт со скидкой 100% я могу не сходя с этого места.

S>Но меня удерживает а) воспитание и б) понимание, что это рано или поздно вскроется (скорость зависит от объёма усилий, которые я потрачу на заметание следов), и меня накажут.
S>Причём мало того, что накажут деньгами — меня обязательно уволят, и шансы получить нормальную работу сразу упадут на порядок.
Злонамеренность это одно, возможность ошибки это другое. Я разговаривал исходя из предположения, что система должна быть устойчивой. То, что требуется в большинстве случаев.

PJ>>В случае администратора, который поменял правила не запуская компилятора, этот код может просто грохнуться.

S>Что такое "просто грохнуться"?
У тебя что-то проверяется только в дебаге. Забыл assert или другие условия в продакшене и ты получаешь исключение.

PJ>>Если у тебя поменяется любое из правил, тебе придется руками найти все места где это надо исправить, делать так каждый раз и компилятор тебе ничем не поможет.

S>Все — это какие? Код структурирован; изменение, скажем, региональных правил валидности адресов (типа перехода от 5 к 9-значному ZIP коду) делаются в одном месте.
При этом у тебя нет никаких гарантий, что нечто полученное под видом 9 значного кода на самом деле 9 значный код и прошло через то самое место. Или что-то не изменило его на мусор в другом месте, просто потому что параметры местами перепутались.

S>>>По моему опыту, sunny day path — это 7% кода. Как раз он и есть boilerplate. Всё остальное — это детальные политики того, что делать, когда всё пойдёт не так.

PJ>>В примере выше у тебя как раз sunny day и есть, с крэшем во всех остальных случаях.
S>Крэш в данном случае — это откат транзакции. Детали обработки каждого из фейлов спрятаны внутрь соответствующих методов.
Крэш это, в первую очеред, разрушение стека. Если ты при этом правильно откатишь транзакцию это хорошо, но это лишь вероятное следствие, причем даже правильность отката ты гарантировать не можешь. В этих местах, как правило, все утечки и случаются.

S>То есть F# не проверяет полноту матчей композитных типов? Тогда я не вижу способа выиграть в выразительности у классического if-else кода за счёт системы типов.

Откуда ты это вывел? Проверяет разумеется. И совершенно не проблема сделать то же самое в c#. Что и сделано в том же oneof, который порт dicriminated union в c#

PJ>>Как именно, это не про DDD, это просто паттерн IO/Actions.

S>Почитаем.
Не повредит, но предупреждаю, что просто почитать мало что даст. Тут надо покурить... Я еще не встречал человека, который бы осилил с первого раза. Хотя идея простая как три копейки.
Re[2]: DDD для небольших проектов.
От: Stalker. Австралия  
Дата: 26.02.20 00:37
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Наша задача — сделать правильную накрутку на базовую цену.

S>Работать должно примерно так:
S>- на все товары мы делаем фиксированную накрутку. Например, 4%. Или 7%.
S>- могут быть исключения для некоторых групп товаров — там, где нам поставщик даёт слишком маленькую скидку, мы хотим урезать наценку, иначе цена выходит дороже розницы
S>- могут быть исключения для некоторых продавцов — на их заказы мы хотим накручивать меньше.
S>- могут быть исключения для некоторых продавцов и товаров — по тем же причинам.
S>- иногда мы можем захотеть сделать скидку на конкретный заказ. Но это только если мы сами размещаем заказ от имени продавца. А когда они сами — см. требования выше.

S>Вот мне интересно, какие объекты будут появляться в DDD, и как они будут работать. Будет ли rich object model, или анемика?


эти вещи делаются при помощи rules engine, DDD к данному вопросу вообще ортогонален
Re[21]: DDD для небольших проектов.
От: Gadsky Россия  
Дата: 29.02.20 15:13
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

PJ>Здравствуйте, Gadsky, Вы писали:


G>>Коллеги, проясните, OneOf<UnpaidShippedOrder, PaidShippedOrder> создает два новых типа, или таки при создании следующего этапа потребуется рантайм проверка?


PJ>https://github.com/mcintyre321/OneOf/


Ну таки это рантайм...


public TResult Match<TResult>(Func<T0, TResult> f0, Func<T1, TResult> f1)
        {
            if (_index == 0 && f0 != null)
            {
                return f0(_value0);
            }
            if (_index == 1 && f1 != null)
            {
                return f1(_value1);
            }
            throw new InvalidOperationException();
        }
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.