Re[9]: Начать ли использовать Code Contracts?
От: Poopy Joe Бельгия  
Дата: 13.08.15 12:05
Оценка:
Здравствуйте, DarkEld3r, Вы писали:

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


PJ>>И? Допустим метод принимает возраст и требует, чтобы он был больше 18 лет. Тогда параметр будет например Adult<Age>. Вызываемый метод гарантированно имеет правильные значения, а вызывающие метод просто физически не сможет послать неверные данные, об этом заботится компилятор. А чем тут помогут контракты? Выкинут исключения во времени исполнения? Очень "полезно".

DE>Дык, Adult<Age> где-то будет из обычного Age получаться? В итоге всё равно без рантайм проверок не обойтись.

Одна в любом случае необходимая проверка в момент создания типа, против множества проверок в разных местах.
Будучи созданным один раз этот тип остается валидным на протяжении всей жизни объекта.

...
var adults = ages.Where(IsLegalAdultAge).Select(a => new Adult(a));
var x = adults.Map(Func1)); // Зачем в Func1 может понадобится контракт? 
...
Отредактировано 13.08.2015 12:37 Poopy Joe . Предыдущая версия .
Re[2]: Начать ли использовать Code Contracts?
От: Venom  
Дата: 13.08.15 12:20
Оценка: 36 (1) +1
Здравствуйте, SergeyT., Вы писали:

ST>Поэтому полноценный ответ здесь: Начать ли использовать контракты?.


Привет.
Нашел пару опечаток, без которых было бы лучше
Можно искать по ctrl+f и заменять на.

>Dопрос

Вопрос

>верифиатор

верификатор

>поноценные

полноценные

>конатрактов

контрактов

>серечера

реceчера
Re[9]: Начать ли использовать Code Contracts?
От: Poopy Joe Бельгия  
Дата: 13.08.15 12:25
Оценка:
Здравствуйте, Doc, Вы писали:

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


PJ>>Надо! Или нет гарантии, что радианы не будут складываться с градусами, а размер головы с размером ноги.

Doc>Вот как раз в вашем варианте это и надо. Например: HumanHeight = HeadHeigh + BodyHeight + LegHeight
Doc>В варианте с контрактами это будут три поля int или float и просто будет сумма. А гарантии будут в тестах.
Т.е. вместо проверки валидности типа на этапе компиляции ты предлагаешь выполнять проверку в рантайме и наедятся на полноту и корректность тестов? Здорово, чо.

Doc>Да, эти тесы и у вас будут, но к ним еще бонусом тесты приведения типов для сложения.

И что в варианте с контрактами мне помешает прибавить туда же и FootSize вместе/вместо LegHeight?

PJ>>Что значит приведение? Другая величина это другая величина.

Doc>А как еще сложить HeadHeigh и BodyHeight?
Да так же как и складывают матрицы. Никому, в здравом уме, в голову не придется из-за перегрузки оператора держать их в float[]. Что в этом особенного?

Doc>*) у вас класс Adult должен знать о Age, уметь извлекать из него значения. Лишний класс, лишние тесты, да еще и с жесткой связью.

Что значит лишний класс? У нас есть какие-то ограничения по количеству классов?

Doc>*) Если у вас будут методы для "до 16", "до 18" и для всех. Будете еще классы создавать на каждый чих?

Эээ... зачем?

PJ>>А чем тут помогут контракты?

Doc>Contract.Requires(18 < age);
Прелестно. А потом потребуется изменить возраст в зависимости от страны...

PJ>>Выкинут исключения во времени исполнения? Очень "полезно".

Doc>А что сделает Adult<Age> если Age будет больше 18?
Вернет ошибку в момент создания, разумеется.

Doc>Кстати, исключение тут вполне уместно, т.к. скорее всего это означает что у вас как-то или малолетка "пролез" через авторизацию, или где-то ошибка в логике загрузки юзеров. Ведь для метода, например, логина такой контракт не уместен (получится что вы хотите BL в контракты зашить)

Исключения вообще не слишком уместны, так как прерывают логику в случайном месте, но это отдельный разговор. В данном случае с типами ошибка обнаружится гораздо раньше. "Загрузку юзеров" просто нельзя будет сломать, так как она может вернуть только правильный тип.
Строго говоря, контракты они не для обнаружения ошибок авторизации, а для контроля программиста. Ситуация когда нарушается Contract.Requires(18 < age) никогда не должна случится. Ради этого там и колхозят статический анализатор кода. В нем весь смысл. Непонятно только зачем нужны костыли, когда компилятор уже имеет тот же самый анализатор только на уровне типов. И гораздо лучше работающий.
Re[10]: Начать ли использовать Code Contracts?
От: DarkEld3r  
Дата: 13.08.15 13:32
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

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

С этим не спорю. Не понравилось именно противопоставление типов и "рантайм проверкам", так как совсем без проверок всё-таки не обойтись.
Re[10]: Начать ли использовать Code Contracts?
От: Doc Россия http://andrey.moveax.ru
Дата: 13.08.15 17:14
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

PJ>Т.е. вместо проверки валидности типа на этапе компиляции ты предлагаешь выполнять проверку в рантайме и наедятся на полноту и корректность тестов? Здорово, чо.


Ну если так параноить, то что помешает в LegHeight записать размер ноги?

Doc>>*) у вас класс Adult должен знать о Age, уметь извлекать из него значения. Лишний класс, лишние тесты, да еще и с жесткой связью.

PJ>Что значит лишний класс? У нас есть какие-то ограничения по количеству классов?

Ну да, чем больше классов тем проще жить? Даешь Hello World из 100500 классов Как там "wow: Здорово, чо."

PJ>>>А чем тут помогут контракты?

Doc>>Contract.Requires(18 < age);
PJ>Прелестно. А потом потребуется изменить возраст в зависимости от страны...

Сравнивай не с константой. Да и мне кажется что опять начинаешь мешать контракты и бизнес-логику.

PJ>>>Выкинут исключения во времени исполнения? Очень "полезно".

Doc>>А что сделает Adult<Age> если Age будет больше 18?
PJ>Вернет ошибку в момент создания, разумеется.

И как у нас конструктор вернет ошибку? Или мы еще и factory с возвратом ошибок замутим?

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


Ну во первых не в случайном месте, а вполне в конкретном.
Далее, в метод, где не может быть возраст меньше заданного пролез такой возраст. Значит программа уже в не консистентном состоянии. Так что исключению тут самое место.
Ну и опять ты путаешь BL и контракты метода.
Re[11]: Начать ли использовать Code Contracts?
От: Poopy Joe Бельгия  
Дата: 13.08.15 18:28
Оценка:
Здравствуйте, Doc, Вы писали:

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


Doc>Ну если так параноить, то что помешает в LegHeight записать размер ноги?

Тип и помешает. Если ты имел ввиду что мне помешает записать в LegHeight неверные данные по видом размера? То ответ — ничего, конечно. Как можно программисту помешать намеренно что-то сделать?! Речь о том, что программисту типы помогают не совершать ошибки.

Doc>Ну да, чем больше классов тем проще жить? Даешь Hello World из 100500 классов Как там "wow: Здорово, чо."

Да что значит больше/меньше? Откуда вообще это взялось? Ну давай все запихаем в один класс, так нормально будет?

Doc>Сравнивай не с константой. Да и мне кажется что опять начинаешь мешать контракты и бизнес-логику.

Почему? Это константа и есть.

Doc>И как у нас конструктор вернет ошибку? Или мы еще и factory с возвратом ошибок замутим?

Ну в примере выкинет исключение, но там это скорее перестраховка, а в обычном случае можно использовать статический метод и вернуть тип Either<Adult<Age>, Error>.

Doc>Ну во первых не в случайном месте, а вполне в конкретном.

С точки зрения перехватывающего метода — с случайном. Можно конечно на каждую операцию писать try/catch, но кто это будет читать потом?

Doc>Далее, в метод, где не может быть возраст меньше заданного пролез такой возраст.

Что значит "пролез"? Как он туда может пролезть?
Re[3]: Начать ли использовать Code Contracts?
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 14.08.15 04:16
Оценка:
Здравствуйте, Venom, Вы писали:

V>Привет.

V>Нашел пару опечаток, без которых было бы лучше

Спасибо! Поправил.
Re[12]: Начать ли использовать Code Contracts?
От: Doc Россия http://andrey.moveax.ru
Дата: 14.08.15 04:23
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

PJ>Речь о том, что программисту типы помогают не совершать ошибки.


Помогают. Но при этом, чем больше самого кода — тем больше вероятность ошибки.

Doc>>Ну да, чем больше классов тем проще жить? Даешь Hello World из 100500 классов Как там "wow: Здорово, чо."

PJ>Да что значит больше/меньше? Откуда вообще это взялось? Ну давай все запихаем в один класс, так нормально будет?

Причем тут запихаем все в один? Но при этом же не надо плодить сущностей сверх меры. Понятно что у каждого она своя. Однако, создавать класс на каждый чих BL (там где вполне подходят стандартные), это перебор.

Doc>>Сравнивай не с константой. Да и мне кажется что опять начинаешь мешать контракты и бизнес-логику.

PJ>Почему? Это константа и есть.

Определись, ты хочешь менять возраст или нет. )

Doc>>И как у нас конструктор вернет ошибку? Или мы еще и factory с возвратом ошибок замутим?

PJ>Ну в примере выкинет исключение, но там это скорее перестраховка

Угу. Т.е. exception из контракта это ой ужас, а из конструктора — это прям прелесть

> а в обычном случае можно использовать статический метод и вернуть тип Either<Adult<Age>, Error>.


Т.е. как я сказал вместо 1 строки с float(или int), в месте которое хорошо покрывается тестами, ты делаешь уже Age, Adult<Age>, фабричный метод в статик классе, ну и общие Either и Error. Добавь тесты на все это добро.

Но главное, ты опять путаешь BL и контракты. Давай на примере покажу
Допустим у нас есть закрытая область (раз уж взяли это Age). Посмотрим на 2 метода
1) Login(User user). Тут просто обычная проверка user.Age и возврат кода. У этого метода не может быть в контракте 18 < user.Age, т.к. попытаться залогиниться у нас может любой юзер. Если что — вернем Error, HttpStatusCode.Forbidden или что еще там надо
2) GetShopContent(..., User user). А вот тут уже контракт что user обязан быть старше 18. И если сюда как-то попал младше, то как я сказал явно проблема в реализации BL. Поэтому кидаем исключение и ловим его на самом верху, программу закрываем, т.к. дальше уже работать нет по сути смысла.

PJ>С точки зрения перехватывающего метода — с случайном. Можно конечно на каждую операцию писать try/catch, но кто это будет читать потом?


Как я уже сказал, ловим такое на самом верху, сохраняем/отправляем что надо для дебага, завершаем работу.

Doc>>Далее, в метод, где не может быть возраст меньше заданного пролез такой возраст.

PJ>Что значит "пролез"? Как он туда может пролезть?

Вот именно. См чуть выше пункт (2).
Re[13]: Начать ли использовать Code Contracts?
От: Poopy Joe Бельгия  
Дата: 14.08.15 05:43
Оценка:
Здравствуйте, Doc, Вы писали:

Doc>Помогают. Но при этом, чем больше самого кода — тем больше вероятность ошибки.

Кэп, ты? Больше то оно больше, только в одном случае ошибку можно сделать в одном, очевидном, месте, а в другом в куче мест.

Doc>Причем тут запихаем все в один? Но при этом же не надо плодить сущностей сверх меры. Понятно что у каждого она своя. Однако, создавать класс на каждый чих BL (там где вполне подходят стандартные), это перебор.


А причем тут 100500, которые ты выдумал? Откуда взялась какая-то мера? Как ты определяешь где перебор, а где нет? Типа в проекте уже слишком много классов будет пихать в существующие?

Doc>Определись, ты хочешь менять возраст или нет. )

18 это константа у тебя в тексте. Причем тут хочу я менять или нет? У меня логика проверки в одном месте у тебя во всех методах с контрактом.

Doc>Угу. Т.е. exception из контракта это ой ужас, а из конструктора — это прям прелесть

Ужас. Но там заведомо известно, что он не случиться.

Doc>Т.е. как я сказал вместо 1 строки с float(или int), в месте которое хорошо покрывается тестами, ты делаешь уже Age, Adult<Age>, фабричный метод в статик классе, ну и общие Either и Error. Добавь тесты на все это добро.


Фраза "хорошо покрывается тестами" ужасно смешная. Она покрывается тестами так как программисту кажется достаточным его покрыть, что, собственно, не гарантирует ничего, а в отличии от типов. Если весь метод MakeAdult состоит из одной проверки, то тесты там вообще не нужны. И кстати какие еще фабричные методы? Зачем они?

Doc>Но главное, ты опять путаешь BL и контракты. Давай на примере покажу

Doc>Допустим у нас есть закрытая область (раз уж взяли это Age). Посмотрим на 2 метода
Doc>1) Login(User user). Тут просто обычная проверка user.Age и возврат кода. У этого метода не может быть в контракте 18 < user.Age, т.к. попытаться залогиниться у нас может любой юзер. Если что — вернем Error, HttpStatusCode.Forbidden или что еще там надо
Doc>2) GetShopContent(..., User user). А вот тут уже контракт что user обязан быть старше 18. И если сюда как-то попал младше, то как я сказал явно проблема в реализации BL. Поэтому кидаем исключение и ловим его на самом верху, программу закрываем, т.к. дальше уже работать нет по сути смысла.

Ты так и не понял о чем я говорю. Да, у тебя проблема в реализации BL, так как не может быть никакого User в GetShopContent с возрастом меньше 18, так как тип должен быть Adult<User> или Validated<User>. И в отличии от "проблема, исключение, креш, недовольный юзер" — это просто не может сломаться.
Контракты это способ искать где ты сломал логику, а типы это способ ее не ломать.

Doc>Как я уже сказал, ловим такое на самом верху, сохраняем/отправляем что надо для дебага, завершаем работу.

Ну т.е. в случайном месте прервалось выполнения, поэтому просто свалились. Так оно и происходит, я не понимаю почему ты это описываешь как что-то хорошее?

Doc>>>Далее, в метод, где не может быть возраст меньше заданного пролез такой возраст.

PJ>>Что значит "пролез"? Как он туда может пролезть?

Doc>Вот именно. См чуть выше пункт (2).

Что вот именно? Это был вопрос? Как возраст меньше 18 может пролезть в Adult<Age>, чисто технически?
Отредактировано 14.08.2015 7:53 Poopy Joe . Предыдущая версия .
Re[14]: Начать ли использовать Code Contracts?
От: Doc Россия http://andrey.moveax.ru
Дата: 14.08.15 07:53
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

PJ>А причем тут 100500, которые ты выдумал? Откуда взялась какая-то мера? Как ты определяешь где перебор, а где нет? Типа в проекте уже слишком много классов будет пихать в существующие?


Я не буду еще раз считать сколько ты уже привел классов для замены одной единственной строчки проверки.
Предложу тебе идти еще дальше и заворачивать каждый if в отдельный класс (жаль тут нет :irony: )

Doc>>Определись, ты хочешь менять возраст или нет. )

PJ>18 это константа у тебя в тексте. Причем тут хочу я менять или нет?

Ну замени 18 на вызов метода. Не пойму в чем сложность, что ты к замене значения пристал.

Doc>>Угу. Т.е. exception из контракта это ой ужас, а из конструктора — это прям прелесть

PJ>Ужас. Но там заведомо известно, что он не случиться.

Так, я вызываю new Adult(new Age(5)) что будет? С чего тут Exception не случится? А что будет?

PJ> И кстати какие еще фабричные методы? Зачем они?


"а в обычном случае можно использовать статический метод и вернуть тип Either<Adult<Age>, Error>." (с) ты

PJ>Ты так и не понял о чем я говорю. Да, у тебя проблема в реализации BL, так как не может быть никакого User в GetShopContent с возрастом меньше 18, так как тип должен быть Adult<User> или Validated<User>. И в отличии от "проблема, исключение, креш, недовольный юзер" — это просто не может сломаться.

PJ>Контракты это способ искать где ты сломал логику, а типы это способ ее не ломать.

Угу, только вот наворачивать класс на каждую проверку раздует код. Нет, я не понимаю когда такой класс обусловлен BL и используется повсеместно. Но делать на каждый чих? Вот у тебя есть Adult, а если завтра надо будет передать только пользователей мужского пола? Male? А если только взрослых мужчин — создаешь AdultMale? А если взрослых женщин с ростом более 170 — AdultFemaleWithMinHeight? Да еще по фабричному (стат.) методу на каждый?

Doc>>Как я уже сказал, ловим такое на самом верху, сохраняем/отправляем что надо для дебага, завершаем работу.

PJ>Ну т.е. в случайном месте прервалось выполнения, поэтому просто свалились. Так оно и происходит, я не понимаю почему ты это описываешь как что-то хорошее?

Потому что у приложение уже ненормальное состояние. Выполнять его дальше нет смысла.

PJ>Что вот именно? Это был вопрос? Как возраст меньше 18 может пролез в Adult<Age> чисто технически?


Вообще-то речь про контракты шла.
Re[15]: Начать ли использовать Code Contracts?
От: Poopy Joe Бельгия  
Дата: 14.08.15 08:15
Оценка:
Здравствуйте, Doc, Вы писали:

Doc>Я не буду еще раз считать сколько ты уже привел классов для замены одной единственной строчки проверки.

Doc>Предложу тебе идти еще дальше и заворачивать каждый if в отдельный класс (жаль тут нет :irony: )
Одна единственная строчка? Да у тебя эти строчки будут размазаны по всему коду, во всех методах. Если надо проверить, что возраст соответствует легальному это должно быть сделано. Можно это сделать в типе, можно это сделать во всех методах контрактами или ifми или еще как. Ну будут огромные методы с кучей проверок, зато типов меньше, ага.

Doc>Ну замени 18 на вызов метода. Не пойму в чем сложность, что ты к замене значения пристал.

Ну замени и что у тебя получится? Либо тот же самый дополнительный тип, отвечающие за проверку возраста, либо логика размазанная по всей программе. И это вместо того, чтобы просто передать готовый тип...

Doc>Так, я вызываю new Adult(new Age(5)) что будет? С чего тут Exception не случится? А что будет?

К чему этот пример? Если человек хочет специально писать кривой код, то разумеется ничего ему не сможет помешать.

Doc>"а в обычном случае можно использовать статический метод и вернуть тип Either<Adult<Age>, Error>." (с) ты

А где тут фабрики?

Doc>Угу, только вот наворачивать класс на каждую проверку раздует код.

А просто проверки нет?

Doc>Нет, я не понимаю когда такой класс обусловлен BL и используется повсеместно. Но делать на каждый чих? Вот у тебя есть Adult, а если завтра надо будет передать только пользователей мужского пола? Male?

Вот завтра у меня будет Male и я просто удалю тип Adult и сделать тип Male и компилятор мне автоматически покажет все места где мне надо изменить логику. Либо вообще просто изменю тип Validated<User> добавив в него какие угодно ограничения.
А у тебя с контрактом User.Age > 18 надо найти все места и прописать все руками, добавив новое ограничение. Это конечно не увеличит ни код, ни требуемое время.

Doc>Потому что у приложение уже ненормальное состояние. Выполнять его дальше нет смысла.

Это я понял. Я не понял почему вообще возможность перехода приложения в ненормальное состояние у тебя допустима и это считается правильным?

PJ>>Что вот именно? Это был вопрос? Как возраст меньше 18 может пролез в Adult<Age> чисто технически?

Doc>Вообще-то речь про контракты шла.
И сейчас, надеюсь, идет. С этого и разговор начался. Контракт проверят что сломано, тип гарантирует, что ничего сломать нельзя.
Re[16]: Начать ли использовать Code Contracts?
От: Doc Россия http://andrey.moveax.ru
Дата: 14.08.15 11:24
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

PJ>Одна единственная строчка? Да у тебя эти строчки будут размазаны по всему коду, во всех методах.


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

Doc>>Ну замени 18 на вызов метода. Не пойму в чем сложность, что ты к замене значения пристал.

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

Заменил, выйдет
Contract.Requries(this.GetMinAge() < age)
где тут доп типы?

Doc>>Так, я вызываю new Adult(new Age(5)) что будет? С чего тут Exception не случится? А что будет?

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

Стоп! Ты сам говорил про конструкторы, про исключения.

PJ>Вот завтра у меня будет Male и я просто удалю тип Adult и сделать тип Male и компилятор мне автоматически покажет все места где мне надо изменить логику. Либо вообще просто изменю тип Validated<User> добавив в него какие угодно ограничения.


Вот тут огромный LOL... посмешил.
Если Adult дает гарантию возраста при передаче в метод, то передача Validated вообще ничего не гарантирует. Что помешает создать Validated который содержит юзера-мужчину и передать в метод, который ожидает что юзер будет женщиной? Тип тот же. Компиляция пройдет на ура. Так что у тебя в Validated может быть любая комбинация условий, что никакой гарантии уже не дает.

PJ>А у тебя с контрактом User.Age > 18 надо найти все места и прописать все руками, добавив новое ограничение. Это конечно не увеличит ни код, ни требуемое время.


Зато метод определяет свой контракт, а не какой-то внешний Validated в котором может быть все что угодно. А после завтра вообще придет твой коллега и перепишет Validated на свой лад.

Doc>>Потому что у приложение уже ненормальное состояние. Выполнять его дальше нет смысла.

PJ>Это я понял. Я не понял почему вообще возможность перехода приложения в ненормальное состояние у тебя допустима и это считается правильным?

Где я сказал что это допустимо и более того что это правильно. Прочитай что процитировал сам же "у приложение уже ненормальное состояние". Это не нормально, не допустимо и не правильно. Может быть из-за ошибки в коде или логики. Именно поэтому экстренное

PJ>И сейчас, надеюсь, идет. С этого и разговор начался. Контракт проверят что сломано, тип гарантирует, что ничего сломать нельзя.


Ну ты уже показал что ничего невозможного нет, заменив Adult на Validated :D
Re[17]: Начать ли использовать Code Contracts?
От: Poopy Joe Бельгия  
Дата: 14.08.15 11:47
Оценка:
Здравствуйте, Doc, Вы писали:

Doc>Ну у тебя и фантазия. Если у тебя возраст проверяется в каждом метода то да, это основание его вынести в конкретный класс.

Doc>Если поглядеть на код, то контракты методов обычно 1 в 1 совпадают редко (ибо наборы параметров разные).
Ничего не понял. Причем тут совпадение параметров? Если у тебя контракт декларируется только в одном месте, то нафиг тогда они тебе вообще нужны?

Doc>Заменил, выйдет

Doc>Contract.Requries(this.GetMinAge() < age)
Doc>где тут доп типы?
Тут код размазанный про всему приложению, что еще хуже. Какой-то класс ответственный за скажем за покупку еще и должен знать про возраст?
Отличный пример как не надо делать хоть с контрактами, хоть без.

Doc>Стоп! Ты сам говорил про конструкторы, про исключения.

Там было больше двух слов.

Doc>Вот тут огромный LOL... посмешил.

Doc>Если Adult дает гарантию возраста при передаче в метод, то передача Validated вообще ничего не гарантирует. Что помешает создать Validated который содержит юзера-мужчину и передать в метод, который ожидает что юзер будет женщиной? Тип тот же. Компиляция пройдет на ура. Так что у тебя в Validated может быть любая комбинация условий, что никакой гарантии уже не дает.
Он гарантирует, что тип проверен. Разумеется от дураков он не защищает. Если кто-то хочет создать тип, а потом обмануть его, то он сможет это сделать. Я не понял только, что мешает написать точно так же неверный контракт? Это ровно тоже самое.
Я тебе пытаюсь сказать, что можно создать тип которые защитит тебя, а ты в ответ говоришь, что можешь его сломать специально. Ну да можешь, ты вообще все можешь сломать. В этом цель?

Doc>Зато метод определяет свой контракт, а не какой-то внешний Validated в котором может быть все что угодно. А после завтра вообще придет твой коллега и перепишет Validated на свой лад.

Это не какой-то внешний Validated, это тип с которым готов работать метод. Тебя название смущает? Так это от твоей привычки пихать все в общие типы, который потом будет использоваться везде, чтобы не дай бог не создать лишний класс. А так-то это название просто для примера.

Doc>Где я сказал что это допустимо и более того что это правильно. Прочитай что процитировал сам же "у приложение уже ненормальное состояние". Это не

нормально, не допустимо и не правильно. Может быть из-за ошибки в коде или логики. Именно поэтому экстренное

Это прямо следует из твоего описания. Дизайн предполагает, что ошибки будут и с ними надо бороться. Еще раз — ДИЗАЙН в котором неверное состояние ОЖИДАЕМО.

Doc>Ну ты уже показал что ничего невозможного нет, заменив Adult на Validated :D

Ну если ты это можешь делать в бессознательном состоянии, то да. Хотят не понимаю, чем тут контракты помогут. У меня речь шла про непреднамеренные ошибки. Если ты мне хочешь доказать, что ты все можешь сломать, то признаю — тут любые методы бессильны. Ты победил.
Re[18]: Начать ли использовать Code Contracts?
От: Doc Россия http://andrey.moveax.ru
Дата: 14.08.15 12:38
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

PJ>Ничего не понял. Причем тут совпадение параметров? Если у тебя контракт декларируется только в одном месте, то нафиг тогда они тебе вообще нужны?


При том что контракт метода это не одна строка. Это условия для всех параметров, это при необходимости еще и инварианты, это выходные значения. И вот сочетания всего этого редко повторяются от метода к методу.

PJ>Тут код размазанный про всему приложению, что еще хуже.


С чего он размазанный? Но находится ровно в своем месте.

PJ>Он гарантирует, что тип проверен. Разумеется от дураков он не защищает. Если кто-то хочет создать тип, а потом обмануть его, то он сможет это сделать. Я не понял только, что мешает написать точно так же неверный контракт? Это ровно тоже самое.


Ну юли, это не тоже самое. Вот ты передаёшь другим разработчикам библиотеку. Там есть 2 метода:

public void DoSomething1(..., int userAge) 
{
    ...
    Contract.Requires(_minAge < userAge);
    ...
}

public void DoSomething2(..., ValidatedUser user) 
{
    ...
}


Если ты попробуешь не читая документации передать не валидный возраст в DoSomething1(), то получишь по рукам исключением (причем вполне конкретным).

Что сделает DoSomething2() если там будет не валидное состояние user — зависит исключительно от конкретной реализации. Может просто молча фигню сделает, или что выкинет ... неизвестно. Причем догадаться можно будет только или прочитав документацию или изучив исходники. И все твои рассказы что типизация тут мол спасет от ошибки тут не чем.

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


Как раз не специально. По ошибке. Не прочитал документацию, допустил ошибку где-то в коде и загрузил в user не то... Но типы то сошлись Твой метод работает только если за конкретное условие будет отвечать конкретный класс.

PJ>Это не какой-то внешний Validated, это тип с которым готов работать метод.


Это просто два жестко связанных класса. И надо помнить, что их реализации связанны. Шикарно.

PJ>Это прямо следует из твоего описания. Дизайн предполагает, что ошибки будут и с ними надо бороться. Еще раз — ДИЗАЙН в котором неверное состояние ОЖИДАЕМО.


Ага, тогда любой код с try {} catch () это такой дизайн. А сэр не использует catch вообще? :D
А вообще нормально когда дизайн предполагает что могут пытаться некорректно использовать, что могут пытаться ломать (особенно там где безопасность важна).

Но как я понимаю для тебя — лучше неопределенное поведение DoSomething2() чем определенное DoSomething1().

Doc>>Ну ты уже показал что ничего невозможного нет, заменив Adult на Validated :D

PJ>Ну если ты это можешь делать в бессознательном состоянии, то да.

Я тебе выше показал пример с библиотекой. Контракт вполне защищает от некорректного использования, а твой метод — нет. О чем еще говорить.

PJ>Хотят не понимаю, чем тут контракты помогут. У меня речь шла про непреднамеренные ошибки.


О них и речь. Пример опять же выше — другой программист использующий твой код. И ты предлагаешь довериться что другой программист все будет делать без ошибкой и карать его неопределенным поведением. По твоему получится это лучше предсказуемого контракта.
Re[19]: Начать ли использовать Code Contracts?
От: Poopy Joe Бельгия  
Дата: 14.08.15 13:04
Оценка:
Здравствуйте, Doc, Вы писали:

Doc>При том что контракт метода это не одна строка. Это условия для всех параметров, это при необходимости еще и инварианты, это выходные значения. И вот сочетания всего этого редко повторяются от метода к методу.

И? Я про то и говорил, что кода с контрактами у тебя будет еще больше. О чем ты вообще?

Doc>С чего он размазанный? Но находится ровно в своем месте.

Месте где ему вообще не место. А если еще методу надо будет проверять возраст? В одном месте ставим контаракт на возраст в другом не ставим? Тут играем, тут рыбу заворачиваем? Клёво, ага. Вместо типа, который сам по себе надёжный контракт.

Doc>Ну юли, это не тоже самое. Вот ты передаёшь другим разработчикам библиотеку. Там есть 2 метода:


Doc>
Doc>public void DoSomething1(..., int userAge) 
Doc>{
Doc>    ...
Doc>    Contract.Requires(_minAge < userAge);
Doc>    ...
Doc>}

Doc>public void DoSomething2(..., ValidatedUser user) 
Doc>{
Doc>    ...
Doc>}
Doc>


Doc>Если ты попробуешь не читая документации передать не валидный возраст в DoSomething1(), то получишь по рукам исключением (причем вполне конкретным).


Doc>Что сделает DoSomething2() если там будет не валидное состояние user — зависит исключительно от конкретной реализации. Может просто молча фигню сделает, или что выкинет ... неизвестно. Причем догадаться можно будет только или прочитав документацию или изучив исходники. И все твои рассказы что типизация тут мол спасет от ошибки тут не чем.

Ты так и не ответил на вопрос каким образом в ValidatedUser окажется невалидное состояние. Уже третий раз спрашиваю.
Я понимаю, что это привычное состояние когда хлоп в float age какая-то хрень. А вот тут как оно так может случится?

Doc>Как раз не специально. По ошибке. Не прочитал документацию, допустил ошибку где-то в коде и загрузил в user не то... Но типы то сошлись Твой метод работает только если за конкретное условие будет отвечать конкретный класс.

Давай вернемся к простому Adult<User>. Изобрази случай когда по ошибке ты передаешь в метод невалидный Adult<User>. Продемонстрируй как по ошибке ты туда загрузишь "не то".

Doc>Это просто два жестко связанных класса. И надо помнить, что их реализации связанны. Шикарно.

Что значит помнить? Ну забудь, компилятор напомнит. А вот забыть, что там какой-то контракт проверяет чего-то можно запросто.

Doc>Ага, тогда любой код с try {} catch () это такой дизайн. А сэр не использует catch вообще? :D

Как элемент своего дизайна? Нет, разумеется. Строить поведение на исключениях это

Doc>А вообще нормально когда дизайн предполагает что могут пытаться некорректно использовать, что могут пытаться ломать (особенно там где безопасность важна).

Oк. void DoSomething2(Adult<User> user){...};
Сломай. Покажи уже на примере, как его можно некорректно использовать.

Doc>Но как я понимаю для тебя — лучше неопределенное поведение DoSomething2() чем определенное DoSomething1().

У меня-то как раз определенной поведение DoSomething2, а в отличии от твоего DoSomething1, который может сработать, а может и исключение выкинуть.

Doc>Я тебе выше показал пример с библиотекой. Контракт вполне защищает от некорректного использования, а твой метод — нет. О чем еще говорить.

Ничего ты не показал. Вдруг тип по волшебству стал содержать неверные данные это фантазия. А вот забыли обновить контракт — реальность.

Doc>О них и речь. Пример опять же выше — другой программист использующий твой код. И ты предлагаешь довериться что другой программист все будет делать без ошибкой и карать его неопределенным поведением. По твоему получится это лучше предсказуемого контракта.

Ровно наоборот. С контрактами надо лазать по чужому коду и смотреть какие там контракты и чего он проверяет. А если метод принимает Adult<Age>, то тут ошибиться просто невозможно. Validated тебе не нравится? Ну так не надо называть так. Неудачное имя использованное в контексте одного примера.
Re[2]: Начать ли использовать Code Contracts?
От: Sinix  
Дата: 14.08.15 15:36
Оценка:
Здравствуйте, Poopy Joe, Вы писали:


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

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

Вот тут
Автор: Mamut
Дата: 05.02.15
это дело исчерпывающе обсуждалось, толкового решения емнип так и не привели.


Где-то в ветке приводили пример с Adult<Age>. Такие штуки работают до момента, пока все условия инвариантны, их мало и условия не зависят от контекста. Потом начинают вылезать грабли.

Самый простой пример: возраст совершеннолетия зависит от страны и не обязательно гарантирует все права (например, крепкое спиртное в Финляндии продаётся начиная с 20 лет, совершеннолетие — с 18). Попробуйте изобразить это с помощью типов

При этом по факту граница ещё более размыта. Получение определённых прав помимо возраста может зависеть от точности gps (Швейцария, в соседних кантонах разные правила продажи спиртного) или от вероисповедования (Пакистан, снова продажа спиртного). От согласия родителей/опекунов (несовершеннолетние). От места рождения и от судимости (право избираться президентом в отдельных странах). От места работы (неграждане в Латвии). Ну и так далее.

Я уж молчу про возраст как основание для получения пенсии — добавляем пол, календарную выслугу, тяжелые/вредные условия труда, состояние здоровья, получение пенсии в другой стране (при двойном гражданстве), дату рождения и тыды и тыпы.


В общем, лучше не пытаться натянуть типы туда, где они явно будут мешать.
Re[20]: Начать ли использовать Code Contracts?
От: Doc Россия http://andrey.moveax.ru
Дата: 14.08.15 15:46
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

PJ>Я про то и говорил, что кода с контрактами у тебя будет еще больше. О чем ты вообще?


Больше только в том случае, если ты будешь игнорировать проверки.

Doc>>С чего он размазанный? Но находится ровно в своем месте.

PJ>Месте где ему вообще не место. А если еще методу надо будет проверять возраст? В одном месте ставим контаракт на возраст в другом не ставим? Тут играем, тут рыбу заворачиваем? Клёво, ага. Вместо типа, который сам по себе надёжный контракт.

С чего это? Интерфейс (метод) диктует условия, условия в нем. Все логично.

PJ>Ты так и не ответил на вопрос каким образом в ValidatedUser окажется невалидное состояние. Уже третий раз спрашиваю.

PJ>Я понимаю, что это привычное состояние когда хлоп в float age какая-то хрень. А вот тут как оно так может случится?

Серьезно не понимаешь? Печаль. Ты писал
> Либо вообще просто изменю тип Validated<User> добавив в него какие угодно ограничения.

1) Создаем ValidatedUser у которого из ограничений, например, только вес < 100 кг. Остальные ограничения не заданы.
2) Записываем в него девушку, 60кг.
3) Предаем в DoSomething2(..., ValidatedUser user) который ждет только мужчин свыше 100кг.


Doc>>Как раз не специально. По ошибке. Не прочитал документацию, допустил ошибку где-то в коде и загрузил в user не то... Но типы то сошлись Твой метод работает только если за конкретное условие будет отвечать конкретный класс.

PJ>Давай вернемся к простому Adult<User>. Изобрази случай когда по ошибке ты передаешь в метод невалидный Adult<User>. Продемонстрируй как по ошибке ты туда загрузишь "не то".

Ну ты совсем уж... Я же написал "Твой метод работает только если за конкретное условие будет отвечать конкретный класс." Как только набираются разные условия, то или плоди по классу на условие и создавай кучу кода ну или как ты предложил ValidatedUser и нафиг все проверки :D

Doc>>Это просто два жестко связанных класса. И надо помнить, что их реализации связанны. Шикарно.

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

Ты точно понимаешь о чем говоришь?
Компилятор напомнит только о том, что надо передать один класс в другой. А что помешает потом поменять логику в одном так, что все поломается? Подчеркну, не специально. Пришел новый разработчик, он уведёт из кода только класс с кучей проверок ValidatedUser передается в метод. Как он угадает какая проверка нужна именно для этого класса

А контракт ты можешь забыть, и сразу получишь по рукам. В некоторых случаях еще при компиляции. Да и просто, если открыть метод и увидеть
Contract.Requires(_minAge < age);
что тут не ясного?

Doc>>Ага, тогда любой код с try {} catch () это такой дизайн. А сэр не использует catch вообще? :D

PJ>Как элемент своего дизайна? Нет, разумеется. Строить поведение на исключениях это

У тебя некрасивая манера общения — придумывать за оппонента. Поведение не строиться на исключениях. Исключения это как раз исключительная ситуация.
Кроме того, ты специально игнорируешь мои слова что после исключения приложение завершает работу.

Doc>>А вообще нормально когда дизайн предполагает что могут пытаться некорректно использовать, что могут пытаться ломать (особенно там где безопасность важна).

PJ>Oк. void DoSomething2(Adult<User> user){...};
PJ>Сломай. Покажи уже на примере, как его можно некорректно использовать.

Как ты быстро вернулся в 1 условию. Уже расписал тебе выше.

Doc>>Но как я понимаю для тебя — лучше неопределенное поведение DoSomething2() чем определенное DoSomething1().

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

С чего оно определённое? Ты ждал одно, получил другое. Пример выше.

Doc>>Я тебе выше показал пример с библиотекой. Контракт вполне защищает от некорректного использования, а твой метод — нет. О чем еще говорить.

PJ>Ничего ты не показал. Вдруг тип по волшебству стал содержать неверные данные это фантазия. А вот забыли обновить контракт — реальность.

Забыли обновить контракт? Обновление контракта вообще исключительная ситуация. Ты точно путаешь BL и контракты.

Предлагаю так, напиши кода для следующего
1) Есть тип User который содержит кучу инфы о юзере.
2) Напиши 3 метода (только сигнатуры и необходмый для пояснения код)
— IsAdult проверяет <= 18 лет
— DoSomething1 — ожидает что ему передадут email и возраст пользователя. По условиям BL вызывается только для пользователей <= 18
— DoSomething2 — ожидает мужчин младше 18
— DoSomething3 — ожидает женщин старше 18 и блондинки
— DoSomething4 — ожидает женщин старше 18 и вес которых больше 60 кг
— DoSomething5 — ожидает женщин старше 18 и младше 40

Вот и поглядим как выглядит твой подход. Я тоже самое на контрактах.
Согласен?
Re[21]: Начать ли использовать Code Contracts?
От: Poopy Joe Бельгия  
Дата: 14.08.15 21:08
Оценка:
Здравствуйте, Doc, Вы писали:

Doc>Больше только в том случае, если ты будешь игнорировать проверки.

У меня нет игнорируемых проверок. Все что не проверяется явно проверяется неявно компилятором.

Doc>С чего это? Интерфейс (метод) диктует условия, условия в нем. Все логично.

С того что это нарушает Single Responsibility Principle. Тут используем возраст, а тут его же и декларируем и проверем, и прочее.

Doc>Серьезно не понимаешь? Печаль. Ты писал

Ты вообще не понял, что я писал. Ощущение, что кто-то из нас разговаривает сам с собой.
Метод принимает не сферический Validated<User>, а тот кторый его удовлетворяет. Да имя не удачно, было выбрано только чтобы показать, что нет привязки к одному полю. Но сколько это можно пережевывать-то?

>> Либо вообще просто изменю тип Validated<User> добавив в него какие угодно ограничения.


Doc>1) Создаем ValidatedUser у которого из ограничений, например, только вес < 100 кг. Остальные ограничения не заданы.

Doc>2) Записываем в него девушку, 60кг.
Doc>3) Предаем в DoSomething2(..., ValidatedUser user) который ждет только мужчин свыше 100кг.
Это ровно обратное тому, что я объяснял. По моему из Adult<Age> все прекрасно понять, чтобы выдвать вот такое...
В первом же сообщении было написано, что ты может создать только валидный тип.

Doc>Как только набираются разные условия, то или плоди по классу на условие и создавай кучу кода ну или как ты предложил ValidatedUser и нафиг все проверки :D

Ни то, ни другое. По классу на "контракт".

Doc>Ты точно понимаешь о чем говоришь?

Хочешь уже скатить до уровня сам дурак?

Doc>А что помешает потом поменять логику в одном так, что все поломается?

А что помешает написать неверный контракт? Да ничего.

Doc>Пришел новый разработчик, он уведёт из кода только класс с кучей проверок ValidatedUser передается в метод. Как он угадает какая проверка нужна именно для этого класса

Ну если там экономили на типах, то наверно придется гадать. А в нормальном случае какой тип передается — такой и нужен.

Doc>А контракт ты можешь забыть, и сразу получишь по рукам. В некоторых случаях еще при компиляции. Да и просто, если открыть метод и увидеть

Doc>Contract.Requires(_minAge < age);
Doc>что тут не ясного?
Неясно кто именно возмущался, что надо открывать чужой код.
Именно что в некоторых случаях. Т.е. вместо проверки типа, работающей всегда, — костыли которые работают в некоторых случаях. А в некоторых случаях можно получить исключение в райнтайме, потому что про некоторые случаи забыли. Чего ты сам-то ограничился одним полем? Напиши сюда их с десяток и сразу будет понятно как их можно забыть и пропустить. Это соврешненно обычное дело.

Doc>У тебя некрасивая манера общения — придумывать за оппонента. Поведение не строиться на исключениях. Исключения это как раз исключительная ситуация.

Конечно строится. Ты заведомо планируешь, что программа может упасть, потому что в данных окажется мусор.

Doc>Кроме того, ты специально игнорируешь мои слова что после исключения приложение завершает работу.

И? Это самый худший случай. О чем ты тут хочешь поговорить?

Doc>Как ты быстро вернулся в 1 условию. Уже расписал тебе выше.

Ерунду ты расписал. Потому, что с двумя ты уже ничего не понял и сделал какие-то феерические выводы строго обратные тому, что я говорил.

Doc>С чего оно определённое? Ты ждал одно, получил другое. Пример выше.

Неверный пример. Вернемся к Adult<Age>. Сломай его.

Doc>Забыли обновить контракт? Обновление контракта вообще исключительная ситуация. Ты точно путаешь BL и контракты.

Да ну прям. Ты точно путаешь контракты и священные тексты. Контракты могут меняться при первом же рефакторинге.

Doc>Предлагаю так, напиши кода для следующего

Doc>1) Есть тип User который содержит кучу инфы о юзере.
Doc>2) Напиши 3 метода (только сигнатуры и необходмый для пояснения код)
Doc>- IsAdult проверяет <= 18 лет
Doc>- DoSomething1 — ожидает что ему передадут email и возраст пользователя. По условиям BL вызывается только для пользователей <= 18
Doc>- DoSomething2 — ожидает мужчин младше 18
Doc>- DoSomething3 — ожидает женщин старше 18 и блондинки
Doc>- DoSomething4 — ожидает женщин старше 18 и вес которых больше 60 кг
Doc>- DoSomething5 — ожидает женщин старше 18 и младше 40

Doc>Вот и поглядим как выглядит твой подход. Я тоже самое на контрактах.

Doc>Согласен?

  Пиши
   class IDCard
    {
        public string Gender { get; set; }
        public string HairColor { get; set; }
        public string Weight { get; set; }
        public string DateOfBirth { get; set; }
        public string Email { get; set; }
    }

    class HairColor { }
    class Weight { }
    class Email { }
    class Age : IComparable<Age>
    {
        public int CompareTo(Age other) {...}
    }

    struct Optional<T> /* Наивная реализация для примера */
    {
        public bool HasValue() {...}
        public T Value { get; set; }
    }

    class Person : IComparable<Age>
    {
        public HairColor HairColor { get; set; }
        public Weight Weight { get; set; }
        public Age Age { get; set; }
        public Email Email { get; set; }
        public int CompareTo(Age other) {...}
    }

    class Male : Person { }
    class Female : Person { }
    class Adult<T>  where T : IComparable<Age>
    {
        public T Value { get; private set; }
        public static Optional<Adult<T>> Create(T arg){...}
    }
    
    class UnderAge<T> where T : IComparable<Age>
    {
        public T Value { get; private set; }
        public static Optional<UnderAge<T>> Create(T arg) {...}
    }

    class Blondie { public Blondie(Adult<Female> woman) { } }
    class PlumpWoman { public PlumpWoman(Adult<Female> woman) { } }
    class SexyWoman { public SexyWoman(Adult<Female> woman) { } }
}

class Program
{
    static bool SendEmail(Email email, UnderAge<Age> age) => true;
    static bool PlayWith(UnderAge<Male> boy) => true;
    static bool AskMath(Blondie woman) => true;
    static bool AskRecipe(PlumpWoman woman) => true;
    static bool FindWife(SexyWoman woman) => true;

    static Optional<Person> Parser(IDCard card) => new Optional<Person>(/*...*/);

    static void Main(string[] args)
    {
        var rawData = new IDCard[10];
        var persons = rawData
            .Select(Parser)
            .Where(p => p.HasValue())
            .Select(p => p.Value)
            .ToArray();

        var children = persons.Select(UnderAge<Person>.Create)
            .Where(p => p.HasValue()).Select(p => p.Value)
            .ToArray();

        var q1 = children.Select(p => new { Email = p.Value.Email, Age = UnderAge<Age>.Create(p.Value.Age).Value })
            .Select(item => SendEmail(item.Email, item.Age));

        var q2 = children
            .OfType<UnderAge<Male>>()
            .Select(PlayWith)
            .ToArray();

        var women = persons.Select(Adult<Person>.Create)
             .Where(p => p.HasValue())
             .OfType<Adult<Female>>()
             .Select();

        var q3 = women.Select(Blondie.Create)
             .Where(p => p.HasValue())
             .Select(p => p.Value)
             .Select(AskMath)
             .ToArray();

        /* Остальные методы очевидны из q3 */  
    }
}
Re[3]: Начать ли использовать Code Contracts?
От: Poopy Joe Бельгия  
Дата: 14.08.15 21:26
Оценка:
Здравствуйте, Sinix, Вы писали:

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

S>Это не всегда возможно. Точнее, сделать можно, но по сложности оно не будет выигрывать у стандартных проверок.
Это возможно и никаких проблем в этом нет. На c# оно будет более многословно, чем на нормальных языках, но никаких сложностей в сравнении "со стандартными проверками" нет. Если использовать нормальные языки с паттерн матчинг, то "стандартные проверки" стыдливо курят в сторонке.

S>Вот тут
Автор: Mamut
Дата: 05.02.15
это дело исчерпывающе обсуждалось, толкового решения емнип так и не привели.

Почитал немного. Очень смешное обсуждение. Все функциональные языки используют как раз типы. Заявлять, что "Высокоуровневую логику на типах писать сложно и обычно нерентабельно" это сильно
Потом почитаю почему там "ничего не получилось". Скорее всего не хотели или как Doc экономили на типах.

S>Где-то в ветке приводили пример с Adult<Age>. Такие штуки работают до момента, пока все условия инвариантны, их мало и условия не зависят от контекста. Потом начинают вылезать грабли.

Если они начали вылезать, то дизайн уже кривой и его надо пересматривать до момента когда грабли исчезнут. Здорово, правда?

S>Самый простой пример: возраст совершеннолетия зависит от страны и не обязательно гарантирует все права (например, крепкое спиртное в Финляндии продаётся начиная с 20 лет, совершеннолетие — с 18). Попробуйте изобразить это с помощью типов

Я собственно это и предложил, в этой же ветке. В чем проблема изобразить это в типах?

S>При этом по факту граница ещё более размыта. Получение определённых прав помимо возраста может зависеть от точности gps (Швейцария, в соседних кантонах разные правила продажи спиртного) или от вероисповедования (Пакистан, снова продажа спиртного). От согласия родителей/опекунов (несовершеннолетние). От места рождения и от судимости (право избираться президентом в отдельных странах). От места работы (неграждане в Латвии). Ну и так далее.

И? А контракты тут каким местом тут чего изменят?

S>Я уж молчу про возраст как основание для получения пенсии — добавляем пол, календарную выслугу, тяжелые/вредные условия труда, состояние здоровья, получение пенсии в другой стране (при двойном гражданстве), дату рождения и тыды и тыпы.

Не молчи, расскажи.
Re[4]: Начать ли использовать Code Contracts?
От: Sinix  
Дата: 14.08.15 22:40
Оценка: 9 (1) +1
Здравствуйте, Poopy Joe, Вы писали:

PJ>Я собственно это и предложил, в этой же ветке. В чем проблема изобразить это в типах?


Кэп: в том, что большинство проверок имеет смысл внутри одного-двух конкретных методов, а данные надо протаскивать по всему коду. Т.е. на вход тебе приходит person, и твой каст к Adult<Person> с костылями в виде HasValue() от стандартңого BL.AssertIsAdult(person) отличается только количеством приседаний на ровном месте.

S>>При этом по факту граница ещё более размыта. Получение определённых прав помимо возраста может зависеть от точности gps (Швейцария, в соседних кантонах разные правила продажи спиртного) или от вероисповедования (Пакистан, снова продажа спиртного). От согласия родителей/опекунов (несовершеннолетние). От места рождения и от судимости (право избираться президентом в отдельных странах). От места работы (неграждане в Латвии). Ну и так далее.

PJ>И? А контракты тут каким местом тут чего изменят?
Кэп #2: будут гарантировать соблюдение всех предусловий значительно меньшими силами? Точнее даже не будут, а гарантируют, т.к. я всю эту радость на практике использую, а не теоретизирую


S>>Я уж молчу про возраст как основание для получения пенсии — добавляем пол, календарную выслугу, тяжелые/вредные условия труда, состояние здоровья, получение пенсии в другой стране (при двойном гражданстве), дату рождения и тыды и тыпы.

PJ>Не молчи, расскажи.
Открываем 400-ФЗ и читаем :P
Я из него самые простые моменты выбрал.
И да, автоматизация расчёта подобных штук _очень_ нуждается в проверке кода всеми возможными средствами, от тестов и до ассертов/контрактов. Если подход с типами на таких масштабах сливается — имеет ли смысл его использовать на чём-то меньшем?

P.S. у меня ещё пара похожих вещей в загашнике есть, можно начать с разбора PSD, о котором лучше всего говорит вот этот комментарий. А потом перейти к pdf-у
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.