Вурдалак
Продвинутый новичок
Какая еще нафиг компиляция, когда значение приходит из рантайма.Тогда выражение cons<11> просто вызовет ошибку компиляции, потому что возникнет нередуцируемое выражение cons<-1>).
Какая еще нафиг компиляция, когда значение приходит из рантайма.Тогда выражение cons<11> просто вызовет ошибку компиляции, потому что возникнет нередуцируемое выражение cons<-1>).
Enum. В терминологии scala он назвал - sealed trait.У тебя есть более удачный термин?
Сохранение инвариантов === enum? Прости, я не понимаю о чем ты.Enum. В терминологии scala он назвал - sealed trait.
В ООП задача решается добавлением уровня абстракции - например, абстрактной фабрикой.
Enum — это конечный набор значений.@Вурдалак, enum - это конечный набор инвариантов.
final class CorpMail
{
private $value;
public function __construct(string $value)
{
Assertion::email($value);
Assertion::inArray($this->getDomain($value), ['corp.mail.ru', 'corp.list.ru', 'corp.bk.ru']);
$this->value = $value;
}
// ...
}
Это не имеет отношения к ООП. Объект должен контролировать собственные инварианты сам. Иначе ты придешь к той же anemic domain model, когда «модель» вообще ничего о себе не контролирует, а всё делегирует каким-то «сервисам». Это процедурное программирование.Фабрика отлично решает проблему сохранения инвариантов того объекта, который «выпускает» - именно потому что она контролирует инициализацию
i) Я согласен, что IntRange<0,10> может быть реализовано как ValueObject, но может быть реализовано и по-другому: через везде определённое или частично определённое преобразование типов, посредством конечного числа отдельных конструкторов, перечислением или псевдонимом элемента списка [0..10]. IntRange<0,10> -- это абстракция.предлагаешь декомопозировать один VO на несколько более мелких VO без какой-либо разумной аргументации
if (<bool expression>)
{
//on true
}
else
{
//on false
}
try {
if ( to_bool(<any_expression>) )
{
}
else
{
}
} catch(IncompatibleType)
{
}
Не совсем так.Получается, мы бизнес-инварианты нужного нам VO фактически выставляем наружу
Еще раз бегло пройдясь по постам, мне кажется, что основной проблемой в нашем диалоге является то, что ты делаешь упор на проверки на уровне компиляции, я же говорю, что это не требуется. Если ты конструируешь AvailableMana в 10-ти разных кейсах, и значение почти всегда приходит извне (от пользователя, например), то тебе всегда придется принимать решение о том как скастить обычный int в int<0, 10>. А учитывая, что для бизнеса каст не будет являться чем-то осмысленным, то тебе придется как-то завершать работу программы (исключение, return, etc.), т.е. везде будет один и тот же какой-то мусорный код с if (Is_castable_to(...)).может обеспечить проверку на этапе компиляции, если в коде где-то была логическая ошибка
Ага, или инвариантом будет утверждение «числа a и b не должны совпадать». Ты введешь тип NotFuckingEqualIntCouple<0,10>?В частности: можно затребовать два числа IntRange<0,10> и IntRange<0,10>, но инвариантом будут не два числа, а их сумма IntRange<0,20>
Я сделаю каст стрелочного типавезде будет один и тот же какой-то мусорный код с if (Is_castable_to(...))
to_range (Int a) => a (Int b) => b :: Int -> IntRange<a,b> | Error
panic_on_error a :: a | Error -> IO() -> IO() | ()
panic_on_error Error IO() = panic(IO(),Error)
painc_on_error a _ = ()
Да, конечно.Ты введешь тип EmailStringWithCorpDomain?
А, т.е. логика при невозможности каста лежит отдельно. И panic() — это типа примерно как exit()? Но в реальности при ошибке будет показана либо страница ошибки, либо задача выпадет из очереди и т.д. Поскольку мы не знаем контекста (web, CLI, queue consumer, API, etc.), то мы выкинем исключение. И будет фактически то же самое.Код:panic_on_error a :: a | Error -> IO() -> IO() | () panic_on_error Error IO() = panic(IO(),Error) painc_on_error a _ = ()
Так с исключениями будет то же самое.i) Я могу регулировать политику: сегодня программа просто падает, а завтра переспрашивает у пользователя число.
Так с таким же успехом ты можешь напрямую юзать VO, чо. new CorpEmail('trash') тоже укажет на ошибку в том месте, где она произошла.ii) Я получаю релевантную ошибку, т.е. ровно в том месте, где она произошла -- при получении данных. А не чёрт знает где.
Замечательно. Значит для VO DateTime ты введешь тип DateTimeString?Да, конечно.
Это тип, отвечающий за часть моей модели. Он является элементом моего макроязыка.
Я не отрицаю, что можно использовать исключения, когда у Вас нет возможности продвигать программу далее.И будет фактически то же самое.
Да, можно.Так с таким же успехом ты можешь напрямую юзать VO
Если нужно преобразовать строку в DateTime, то будет стрелочный объект DateTimeFromString, в который мы будем внедрять актор on_fail.DateTime ты введешь тип DateTimeString
http://stackoverflow.com/questions/9169691/how-to-check-constructor-arguments-and-throw-an-exception-or-make-an-assertion-iScala, к примеру, не позволит Вам ничего проверить во время конструирования. По сути, в Scala конструктор -- это просто список private данных. Scala, в хорошем смысле, заставляет делать правильно.
Scala, к примеру, не позволит Вам ничего проверить во время конструирования.
Взаимоисключающие параграфы?Конечно, никто не запрещает Вам редуцировать объект к исключению.
A better approach might be to provide a factory method.
Что до цитаты, которую ты вырвал из контекста (там даже не точки после слова «method»), то там автор советует какую-то хрень. Result/Validation object почти всегда будет хуже, чем исключение.Именно это и есть эквивалент ваших проверок.
Нет. Вы продвигаете объект, Вы его создали и вызвали на нём метод.Взаимоисключающие параграфы?
class MyData {
};
class MyErrorClass {
public:
MyErrorClass(int i): data(i) { };
private:
MyData data;
};
Да, объект компаньон для того и придуман. Придуман для написания явных стрелочных объектов (выражены в Scala подобно методам), которые, в том числе, могли бы заниматься преобразованием типов. Всё очень похоже... Это тёмная сторона Scala... Влияние Rapid Application Development. Скорость превыше качества.это тот же named constructor
Я обрезал цитату, потому что судьба вариантов уже не имеет особенного значения.которую ты вырвал из контекста (там даже не точки после слова «method»)
Смотря для каких целей.Result/Validation object почти всегда будет хуже, чем исключение.