Re[16]: DDD для небольших проектов.
От: Poopy Joe Бельгия  
Дата: 17.02.20 10:49
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

S>Это понятно. Просто на ассемблере придётся писать руками вообще всё, на шарпе — чуть меньше, а F#, как я понимаю, обходится без бойлерплейта.
Не в этом дело. Они зависимые потому, что не всякий тип создает ветвление. Если есть трансформации a -> b -> c -> d, то путь ровно один, хотя типов 4 штуки.

PJ>>Вообще никакой разницы. Возможет только для PaidOrder

S>Я не понимаю что такое "вообще никакой разницы". Вы только что мне привели в пример простыню кода, которая всё ещё ничего не делает, кроме как описывает статические бизнес-правила.
S>Не умаляю полезности этого, но по соотношению "логика на строчку кода" этот пока не выигрывает у любого другого варианта.

Никакой разницы потому, что функция refund принимает только параметр PaidOrder, что логично не так ли?
Если валидность PaidOrder гарантирована, то это все что надо знать refund. Оно по-определению, в этом случае, не зависит от остальных компонентов системы.
Что, в конечном итоге, уменьшает размер кода и делает его более надежным.
Если есть валидные a, b и c, и корректные a -> b, b -> c, то функция a -> b -> c будет тоже корректна. А компилятор не даст тебе собрать d -> c.

S>У меня и до этого был один Delivered.

Ну т.е. типы не расползаются. Начал с одного и закончил одним. Какая же это экспонента?

S>Ну, вы продолжаете хитрить на ровном месте. Каким образом вы склеили PaidShippableOrder с UnpaidShippableOrder?

Что значит склеил? ShippableOrder их ко-произведение. Я использую логику процесса, как я его понимаю. На мой взгляд готовность к отправке не зависит от статуса оплаты, по твоим объяснениям.

S>Если бы вы этого не сделали, то стало бы видно, как появление признака "Paid/Unpaid" удваивает количество классов. Пока что у нас получилось 2 (количество стадий оплаты) * 3 (количество стадий поставки) классов.

А зачем бы мне это делать? Paid/Unpaid содержит разную информацию, поэтому типы разные. И дает две дополнительные функции refund : PaidOrder -> Result<> и requestPayment : PaidOrder -> Result<>
Зачем нужен второй prepareToShip я не представляю, но вполне допускаю, что смысл в этом может быть. Но, в этом случае, хоть с типами, хоть без, у тебя ровно два решения: две функции или две ветки if-else. А как еще?

PJ>>И, второй вопрос, как ты это обычно выражешь по-своему?

S>Обычно это выражается ровно в тех правилах, которые описывают переход состояний. В том методе, который пытается изменить статус отгрузки, проверяется наличие пре-реквизитов отгрузки. И ему всё равно, сколько ещё есть признаков и какие там у них значения. В терминах типов, этот метод полиморфен — он принимает и PaidShippableOrder, и UnpaidShippableOrder, и любой другой ShippableOrder.
Ты сам говорил про важность кода. Вот тут как раз такой случай.

S>Код, конечно, живёт в типах. Но вопрос, в том числе, и в том, сколько будет этих типов — сколько будет бойлерплейта вокруг реально значимого кода.

Реально заначимый код это sunny day path. Все остальное это бойлерплейт. Удачи с таким кодом.

S>Ну, это хорошо. А компилятор С# будет проверять всё то же, что и F#? Ну там — полноту паттерн-матчинга? Или можно декомпилировать F# в C#, потом внести небольшое изменение, и C# всё отлично откомпилирует, а F# бы дал по рукам?

Смысл моей фразы в том, что все описанное на f# можно сделать и на c#. Я вовсе не призываю тебя писать на c#, если есть возможность писать на f#, это было бы слабоумно. Но такая возможность не всегда доступна.

PJ>>Несомненно на F# все это сильно проще, короче и лучше. Ну так и используй F#, если цель не страдать, а получить код который не надо отлаживать. Но если, по какой-то причине, надо использовать C#, то это не является шоустоппером.

S>Ну, опять же — можно всё то же самое и на ассемблере написать. Шоустоппером ничто не является. Вопрос в том, будет ли ассемблер проверять инварианты, которые проверяет F#.

Ну вот мы, например, заморочились и используем IO на f#. Разумеется чистоту функций компилятор не проверяет, приходится делать через код-ревью. Тайп-классов тоже нет.
Больше писать? Да, больше. Меньше компилятор помогает? Да, меньше.
Тем не менее возможность вынести сайд-эффекты на границы домена многократно повышеат читаемость, тестируемость и, в конечном итоге, надежность.
Дебажить практически не надо, а тех редких случаях когда приходится, ты точно знаешь место где это надо посмотреть.
То же самое и в C# или любом другом языке. Либо ты больше используешь компилятор, либо дебаггер. Как-то так...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.