Здравствуйте, Erop, Вы писали:
P>>Тип Age отвечает вообще за возраст. Допустим от 0 до 200 (ну мало ли, главное слишком большой не допустить). P>>А дальше, можно делать либо более требовательные типы, либо проверку внутри (если проверка одноразовая). Не вижу никаких проблем. E>А я вот вижу проблемы. Мафусуил, например, прожил 997 лет, что ли, а Адам 600 с чем-то, а число 200 ты взял с потолка, нагородил вокруг целый тип, и навёл кучу тени на плетень... Заметь, на пустом месте. E>Абстракции они того, трудно делаются, особенно если ты хочешь их из пальца высасывать и при этом ещё и не ошибаться
шутник
я думал мы об range ограничении говорим.
P>>и при этом, внутри, возюканья в любом случае меньше. допустим подходят только старше 20 — не вопрос, просто проверка на >20, проверку на верхнюю границу делать не надо E>А зачем вообще делать проверку на верхнюю, если она не нужна?
это был пример, зачем лезть в бутылку?
E>А если уж нужна, то что хорошего в том, что одна проверка записана в функции, а другая где-то в недрах возраста?
функция принимает возраст.
если у функции могут быть дополнительные требования к возрасту, если это требование нужно один раз — можно проверять внутри
E>>>Давай, покажи нам на примере возраста P>>я уже показал E>Пока показал лишь то, что ты некомпатибл с Библией...
сказками не интересуюсь
P>>
P>>Salary getEstimaedSalary(Age);
P>>
P>>Принимает возраст, возвращает зарплату P>>а что у тебя что P>>
P>>int getEstimaedSalary(int);
P>>
P>>? P>>и ассерты внутри?? E>В С/С++ принято давать понятные имена параметрам функций, как и самим функциям E>
money getEstimaedSalary(int age)
ох ты какой чёткий, даже возвращаемому параметру имя дал
или это таки тип?
P>>>>я это и хотел услышать, то есть сумма сама по себе не нужна, а нужно усреднение, так? E>>>нет не так. Ещё дисперсия бывает, или скидка молодой семье, суммарный возраст которой меньше 45 лет P>>ну и считай — в чём проблема-то? вроде умеешь E>тип какой у всех этих выражений будет?
какой хочешь — хочешь целое, хочешь Age E>>>И разность возрастов не забывай пожалуйста P>>ага, ещё умножение до-кучи — возраст в квадрате E>возраст в квадрате концепт небанальный, хотя в какой-нибудь медицинский индекс запросто может входить, а вот на сколько Петя старше своей жены Маши вопрос весьма жизненный
да, я понимаю, что требования можно вводить и убирать во время дискуссии, поэтому всё это пустой трёп.
Здравствуйте, Piko, Вы писали:
P>шутник P>я думал мы об range ограничении говорим.
Я вообще плохо понимаю, как ты собираешься выбрать адекватные границы для "возраста вообще"? А для какой-то конкретной ситуации?
Вот возраст -- хороший очень пример. Т сам его предложил, наверное он адекватен твоей идее.
Я бы для возраста юзал бы int не парился, а в функциях писал бы asserts, да и всё.
Но у тебя какой-то иной подход. Я так понял, что ты хочешь что-то автоматизировать, что бы не страдать "вознёй с assert'ами". Ну покажи же, как автоматизировать-то будем? Вот на примере возраста покажи.
P>>>и при этом, внутри, возюканья в любом случае меньше. допустим подходят только старше 20 — не вопрос, просто проверка на >20, проверку на верхнюю границу делать не надо E>>А зачем вообще делать проверку на верхнюю, если она не нужна?
P>это был пример, зачем лезть в бутылку?
Про бутылку я тоже не понял. Прводи понятные актуальные примеры.
А то я вижу такой сценарий, что мы в какой-то функции посмотрели, что возраст гарантирует, что он до 100 ну и заложились на этот факт, а ассерт не написали. Потом кто-то где-то найдёт, что возраст бывает и 123, ну подправит класс Age. Думаешь он проверит, что там у нас в функции написано, или, хотя бы, потестирует её?
P>функция принимает возраст. P>если у функции могут быть дополнительные требования к возрасту, если это требование нужно один раз — можно проверять внутри
Как в этом сценарии будет выявлена ошибка?
P>>>и ассерты внутри?? E>>В С/С++ принято давать понятные имена параметрам функций, как и самим функциям E>>
money getEstimaedSalary(int age)
P>ох ты какой чёткий, даже возвращаемому параметру имя дал P>или это таки тип?
Это тип, или псевдоним типа. так как в каком типе хранить суммы денег -- вопрос очень непростой. Но тут проблема именно с бинарным представлением, а не с логикой программы. Если это поделка на коленке для домашней бухгалтерии, то можно так:
typedef double money;
Но лучше, конечно же, 64-битное с фиксированной десятичной точкой.
P>какой хочешь — хочешь целое, хочешь Age
Я вообще считаю, что Age -- лишнй, что он не нужен и что все Age надо заменить на int.
Но ты отстаиваешь иной взгляд. Так какой тип, по твоему должны иметь:
Age + Age
Age + int
Age — Age // пусть этот тип имеет псевдонм age_diff
Age + age_diff
Age + int // если это не то же, что и выше
Age / Age
Age * 0.5
P>да, я понимаю, что требования можно вводить и убирать во время дискуссии, поэтому всё это пустой трёп.
IMHO, это принципиальна проблема подхода, когда для яблок используются одни натуральные числа, а для морковок -- другие...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
P>>шутник P>>я думал мы об range ограничении говорим. E>Я вообще плохо понимаю, как ты собираешься выбрать адекватные границы для "возраста вообще"? А для какой-то конкретной ситуации?
адекватный границы, это когда всякий хлам типа 1001230 не пройдёт.
ну конечно если тебя интересуют говно мамонта то ...
E>Вот возраст -- хороший очень пример. Т сам его предложил, наверное он адекватен твоей идее. E>Я бы для возраста юзал бы int не парился, а в функциях писал бы asserts, да и всё.
одинаковые asserts? или разные?
ты же сам писал:
assert( IsValidAge( age ) );
а теперь сам же говоришь, что требования другие.
ок, зачем всё время писать IsValidAge( age ), если Age сам может позаботится.
E>Но у тебя какой-то иной подход. Я так понял, что ты хочешь что-то автоматизировать, что бы не страдать "вознёй с assert'ами". Ну покажи же, как автоматизировать-то будем? Вот на примере возраста покажи.
я хз, вроде понятно объяснил всё
E>А то я вижу такой сценарий, что мы в какой-то функции посмотрели, что возраст гарантирует, что он до 100 ну и заложились на этот факт, а ассерт не написали. Потом кто-то где-то найдёт, что возраст бывает и 123, ну подправит класс Age. Думаешь он проверит, что там у нас в функции написано, или, хотя бы, потестирует её?
а твой IsValidAge что делает???
P>>функция принимает возраст. P>>если у функции могут быть дополнительные требования к возрасту, если это требование нужно один раз — можно проверять внутри E>Как в этом сценарии будет выявлена ошибка?
какая именно? exception, etc, меню богатое
P>>>>и ассерты внутри?? E>>>В С/С++ принято давать понятные имена параметрам функций, как и самим функциям E>>>
money getEstimaedSalary(int age)
P>>ох ты какой чёткий, даже возвращаемому параметру имя дал P>>или это таки тип?
E>Это тип, или псевдоним типа. так как в каком типе хранить суммы денег -- вопрос очень непростой. Но тут проблема именно с бинарным представлением, а не с логикой программы. Если это поделка на коленке для домашней бухгалтерии, то можно так:
typedef double money;
E>Но лучше, конечно же, 64-битное с фиксированной десятичной точкой.
а лучше нормальный класс
P>>какой хочешь — хочешь целое, хочешь Age E>Я вообще считаю, что Age -- лишнй, что он не нужен и что все Age надо заменить на int. E>Но ты отстаиваешь иной взгляд. Так какой тип, по твоему должны иметь:
E>Age + Age E>Age + int E>Age — Age // пусть этот тип имеет псевдонм age_diff E>Age + age_diff E>Age + int // если это не то же, что и выше E>Age / Age E>Age * 0.5
ну и?
делаешь шаблон/макрос для всех этих операций: нужен новый тип с определённым операций, просто делаешь trairs, tag, и всё..
P>>да, я понимаю, что требования можно вводить и убирать во время дискуссии, поэтому всё это пустой трёп. E>IMHO, это принципиальна проблема подхода, когда для яблок используются одни натуральные числа, а для морковок -- другие...
кэп мод: как бы от задачи зависит.
есть задачи где складывать колличество морковок и яблок, не нужно, и лишь является ошибкой — почему бы не обезапасить себя системой типов от ошибок?
Здравствуйте, Piko, Вы писали:
E>>Я вообще плохо понимаю, как ты собираешься выбрать адекватные границы для "возраста вообще"?
P>адекватный границы, это когда всякий хлам типа 1001230 не пройдёт.
Ты конкретный код покажи.
P>одинаковые asserts? или разные?
Осмысленные. Каждый раз смотрим, чего для функции надо, и пишем такой assert...
P>ок, зачем всё время писать IsValidAge( age ), если Age сам может позаботится.
А не надо всё время, надо там где надо, а там где не надо, не писать...
P>я хз, вроде понятно объяснил всё
Пока что никакой конкретики вообще...
E>>А то я вижу такой сценарий, что мы в какой-то функции посмотрели, что возраст гарантирует, что он до 100 ну и заложились на этот факт, а ассерт не написали. Потом кто-то где-то найдёт, что возраст бывает и 123, ну подправит класс Age. Думаешь он проверит, что там у нас в функции написано, или, хотя бы, потестирует её?
P>а твой IsValidAge что делает???
Я не знаю, что он делает. Его же ты придумал
Но в той функции, где мы закладываемся на 100, так и напишем "возраст меньше 100" и всё.
P>какая именно? exception, etc, меню богатое
Я имею в виду не технический, а административный аспект. Вот поддержали мы в новой версии возрастА больше 100 лет. Как нам выявить все возникшие ошибки? Какой АДМИНИСТРАТИВНОЙ процедурой?
P>а лучше нормальный класс
Что такое "нормальный класс"?
E>>Age + Age E>>Age + int E>>Age — Age // пусть этот тип имеет псевдонм age_diff E>>Age + age_diff E>>Age + int // если это не то же, что и выше E>>Age / Age E>>Age * 0.5
P>делаешь шаблон/макрос для всех этих операций: нужен новый тип с определённым операций, просто делаешь trairs, tag, и всё..
Какой должен быть? Ты вопрос понимаешь? Напиши в каждой строчке этой таблицы тип...
P>кэп мод: как бы от задачи зависит.
Как бы наличие трудности от задачи не зависит...
От задачи может зависеть, выгодно ли с этой трудностью мириться...
P>есть задачи где складывать колличество морковок и яблок, не нужно, и лишь является ошибкой — почему бы не обезапасить себя системой типов от ошибок?
Потому, что это дорого, сложно и чревато другими ошибками...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>>>Я вообще плохо понимаю, как ты собираешься выбрать адекватные границы для "возраста вообще"? P>>адекватный границы, это когда всякий хлам типа 1001230 не пройдёт. E>Ты конкретный код покажи.
код чего? класса с инвариантами?
P>>одинаковые asserts? или разные? E>Осмысленные. Каждый раз смотрим, чего для функции надо, и пишем такой assert...
ну вот у тебя 20 функций к одному параметру одинаковое требование. будешь копипастить?
P>>ок, зачем всё время писать IsValidAge( age ), если Age сам может позаботится. E>А не надо всё время, надо там где надо, а там где не надо, не писать...
ну вот надо допустим в 20 местах, и чё?
P>>я хз, вроде понятно объяснил всё E>Пока что никакой конкретики вообще...
ну печально
E>>>А то я вижу такой сценарий, что мы в какой-то функции посмотрели, что возраст гарантирует, что он до 100 ну и заложились на этот факт, а ассерт не написали. Потом кто-то где-то найдёт, что возраст бывает и 123, ну подправит класс Age. Думаешь он проверит, что там у нас в функции написано, или, хотя бы, потестирует её? P>>а твой IsValidAge что делает??? E>Я не знаю, что он делает. Его же ты придумал
В С, как и в "С++ для не слишком умных" можно просто написать
int IsValidAge( int );
и потом писать везде на входе в функции
assert( IsValidAge( age ) );
P>>какая именно? exception, etc, меню богатое E>Я имею в виду не технический, а административный аспект. Вот поддержали мы в новой версии возрастА больше 100 лет. Как нам выявить все возникшие ошибки? Какой АДМИНИСТРАТИВНОЙ процедурой?
в смысле изменили требование внутри класса?
если кому-то из старых пользователей это требование не подойдёт — то придётся изменять. точно также как в твоём случае с
assert( IsValidAge( age ) );
E>>>Но лучше, конечно же, 64-битное с фиксированной десятичной точкой. P>>а лучше нормальный класс E>Что такое "нормальный класс"?
у тебя в C, есть встроенный тип "64-битное с фиксированной десятичной точкой"?
да так чтобы ничего не сломалось при изменении представления??
E>>>Age + Age E>>>Age + int E>>>Age — Age // пусть этот тип имеет псевдонм age_diff E>>>Age + age_diff E>>>Age + int // если это не то же, что и выше E>>>Age / Age E>>>Age * 0.5 P>>делаешь шаблон/макрос для всех этих операций: нужен новый тип с определённым операций, просто делаешь trairs, tag, и всё.. E>Какой должен быть? Ты вопрос понимаешь? Напиши в каждой строчке этой таблицы тип...
в смысле тип результата, или чего? я не телепат
P>>кэп мод: как бы от задачи зависит. E>Как бы наличие трудности от задачи не зависит... E>От задачи может зависеть, выгодно ли с этой трудностью мириться...
ага, с assert'ами труднее
P>>есть задачи где складывать колличество морковок и яблок, не нужно, и лишь является ошибкой — почему бы не обезапасить себя системой типов от ошибок? E>Потому, что это дорого, сложно и чревато другими ошибками...
Здравствуйте, Piko, Вы писали:
P>код чего? класса с инвариантами?
типа Age, что бы за этим выражением ты не скрывал...
E>>Осмысленные. Каждый раз смотрим, чего для функции надо, и пишем такой assert... P>ну вот у тебя 20 функций к одному параметру одинаковое требование. будешь копипастить?
Это совпадение или какой-то математический факт? Если первое, то напишу все 20 независимо, если второе -- то введу функцию, проверки этого факта. Но тоже не всегда. Скажем > 0 буду писать везде независимо...
P>ну вот надо допустим в 20 местах, и чё?
И надо во всех посмотреть и решить, что тут вот надо, а тут вот не надо, а тут надо, но другое условие...
типа работа программиста такая -- писать код функций.
E>>Я не знаю, что он делает. Его же ты придумал
P>
P>В С, как и в "С++ для не слишком умных" можно просто написать
P>int IsValidAge( int );
P>и потом писать везде на входе в функции
P>assert( IsValidAge( age ) );
Так задача же не ясна. В некоторых может и бывает валидный и невалидный возраст...
Но если мы о класса Age "общего назначения", то тут с валидным и невалидным возрастом сложнее определиться...
Я пока что так и не понял, о чём конкретно ты говоришь.
P>в смысле изменили требование внутри класса? P>если кому-то из старых пользователей это требование не подойдёт — то придётся
Так и как кто-то узнает, что ту, ту и вон ту функции надо переписать?
P>у тебя в C, есть встроенный тип "64-битное с фиксированной десятичной точкой"?
Есть, это "число центов"...
P>да так чтобы ничего не сломалось при изменении представления??
E>>>>Age + Age E>>>>Age + int E>>>>Age — Age // пусть этот тип имеет псевдонм age_diff E>>>>Age + age_diff E>>>>Age + int // если это не то же, что и выше E>>>>Age / Age E>>>>Age * 0.5 P>>>делаешь шаблон/макрос для всех этих операций: нужен новый тип с определённым операций, просто делаешь trairs, tag, и всё.. E>>Какой должен быть? Ты вопрос понимаешь? Напиши в каждой строчке этой таблицы тип...
P>в смысле тип результата, или чего? я не телепат
Да результата.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
P>>код чего? класса с инвариантами? E>типа Age, что бы за этим выражением ты не скрывал...
его реализация зависит от условий задачи. от того будут ли в проекте похожие типы, и т.п.
E>>>Осмысленные. Каждый раз смотрим, чего для функции надо, и пишем такой assert... P>>ну вот у тебя 20 функций к одному параметру одинаковое требование. будешь копипастить? E>Это совпадение или какой-то математический факт? Если первое, то напишу все 20 независимо, если второе -- то введу функцию, проверки этого факта. Но тоже не всегда. Скажем > 0 буду писать везде независимо...
ох как ты вертишься, как уж на сковородке.
да, математический факт — у 20 функций одинаковые условия.
P>>ну вот надо допустим в 20 местах, и чё? E>И надо во всех посмотреть и решить, что тут вот надо, а тут вот не надо, а тут надо, но другое условие... E>типа работа программиста такая -- писать код функций.
ога. как ещё оправдаешь копипасту?
E>Так задача же не ясна. В некоторых может и бывает валидный и невалидный возраст... E>Но если мы о класса Age "общего назначения", то тут с валидным и невалидным возрастом сложнее определиться... E>Я пока что так и не понял, о чём конкретно ты говоришь.
вот например, параметром функции является возраст, в случае с С, в каждой функции принимающей возраст нужно делать проверку. В случае C++ будет просто класс Age, и внутри функции не о чём не нужно парится. (можно даже использовать различные трюки, чтобы ловить конструкцию Age с неправильным возрастом compile time, но не об этом речь). И как тут поможет статический анализатор кода??
у меня в голове было конкретное Т.З. на проект, где этот тип будет применяться, со всеми требованиями?
Что вообще за бред, коллега?
А главное, как тебе тут поможет статический анализатор кода???
P>>в смысле изменили требование внутри класса? P>>если кому-то из старых пользователей это требование не подойдёт — то придётся E>Так и как кто-то узнает, что ту, ту и вон ту функции надо переписать?
я тебя понял. ты даже знаешь что, можешь функции не использовать, точнее только одну, и в неё копипастить весь код. а то вдруг мы поменяем реализацию функции makeTea с готовки чая, на запуск ядерной бомбы
брееед
P>>у тебя в C, есть встроенный тип "64-битное с фиксированной десятичной точкой"? E>Есть, это "число центов"...
ога, как ты там говоришь, поменяем ограничение? сегодня это число центов, завтра сотые доли центов. И что, менять весь код?
P>>>>делаешь шаблон/макрос для всех этих операций: нужен новый тип с определённым операций, просто делаешь trairs, tag, и всё.. E>>>Какой должен быть? Ты вопрос понимаешь? Напиши в каждой строчке этой таблицы тип... P>>в смысле тип результата, или чего? я не телепат E>Да результата.
зависит от задачи
например:
Age + Age — недоступная операция, Age
Age + int — недоступная операция, Age,
Age — Age — недоступная операция, AgeDiff, Age
Age + age_diff — недоступная операция, Age
Age / Age — недоступная операция, floating point
Age * 0.5 — недоступная операция, Age
Age + int
Age + int // если это не то же, что и выше
сорри, на курсы телепата ещё не пошёл, и пока не собираюсь
Здравствуйте, Piko, Вы писали:
E>>типа Age, что бы за этим выражением ты не скрывал...
P>его реализация зависит от условий задачи. от того будут ли в проекте похожие типы, и т.п.
Блин!
ох как ты вертишься, как уж на сковородке.[-q]Конкретика какая-нибудь будет?
P>да, математический факт — у 20 функций одинаковые условия.
Пример мат. факта -- три числа могут быть сторонами прямоугольного треугольника. А если у меня в программе 100500 функций и аргумент 20 из них не должен превышать 65, то это случайное совпадение просто...
P>ога. как ещё оправдаешь копипасту?
За копи-пасту -- штраф. Писать всегда надо с чистого листа.
Вообще, если у тебя есть семейство функций, с одинаковыми условиями вызова, например семейство аллокаторов, то решать проблему того, что всем надо дать одни и те же параметры, надо архитектурно. Должен быть промежуточный слой, который гарантирует корректность вызова
P>у меня в голове было конкретное Т.З. на проект, где этот тип будет применяться, со всеми требованиями?
Я тебя вообще плохо понимаю. Я так подозреваю, что класс Age какой-то простой довольно, может ты его приведёшь, хотя бы на псевдокоде?
P>А главное, как тебе тут поможет статический анализатор кода???
Он поможет от другого. От того, что передают бинарно несовместимые данные.
P>брееед
Что конкретно бред? То, что взятую с потолка верхнюю границу возраста придётся пододвинуть?
P>ога, как ты там говоришь, поменяем ограничение? сегодня это число центов, завтра сотые доли центов. И что, менять весь код?
Нет, одну константу...
P>например:
P>Age + Age — недоступная операция, Age
а как быть с верхней границей?..
P>Age + int — недоступная операция, Age,
Это логично, если int -- разница возрастов, иначе не понятно
P>Age — Age — недоступная операция, AgeDiff, Age
чем AgeDiff отличается от int? Может ли Age быть отрицательным?
P>Age + age_diff — недоступная операция, Age
P>Age / Age — недоступная операция, floating point
P>Age * 0.5 — недоступная операция, Age
P>[q]
P>Age + int
P>Age + age_diff// если это не то же, что и выше
P>сорри, на курсы телепата ещё не пошёл, и пока не собираюсь
а что значит "недоступная операция"?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>>>типа Age, что бы за этим выражением ты не скрывал... P>>его реализация зависит от условий задачи. от того будут ли в проекте похожие типы, и т.п. E>Блин!
ох как ты вертишься, как уж на сковородке.
Конкретика какая-нибудь будет?
надо чётко поставить задачу, не хочу тратить время впустую
P>>да, математический факт — у 20 функций одинаковые условия. E>Пример мат. факта -- три числа могут быть сторонами прямоугольного треугольника. А если у меня в программе 100500 функций и аргумент 20 из них не должен превышать 65, то это случайное совпадение просто...
охх...
P>>ога. как ещё оправдаешь копипасту? E>За копи-пасту -- штраф. Писать всегда надо с чистого листа.
чего, чего?
E>Вообще, если у тебя есть семейство функций, с одинаковыми условиями вызова, например семейство аллокаторов, то решать проблему того, что всем надо дать одни и те же параметры, надо архитектурно. Должен быть промежуточный слой, который гарантирует корректность вызова
ээ, а чем специальный тип параметра не промежуточный слой?
P>>у меня в голове было конкретное Т.З. на проект, где этот тип будет применяться, со всеми требованиями? E>Я тебя вообще плохо понимаю. Я так подозреваю, что класс Age какой-то простой довольно, может ты его приведёшь, хотя бы на псевдокоде?
для разных ситуаций могут быть разные реализации. я могу привести один пример, на что ты скажешь что там нет X и Y.
в самом простом приближении, Age это:
class Age
{
int age;
public:
struct WrongAgeRange{};
explicit Age(int x)
{
if( x>0 && x<200 )
age=x;
else
throw WrongAgeRange();
}
int value()
{
return age;
}
};
P>>А главное, как тебе тут поможет статический анализатор кода??? E>Он поможет от другого. От того, что передают бинарно несовместимые данные.
эхх, то есть не поможет, то есть зря весь разговор...
P>>ога, как ты там говоришь, поменяем ограничение? сегодня это число центов, завтра сотые доли центов. И что, менять весь код? E>Нет, одну константу...
ога, и все пользователи должны не забывать использовать некую константу
P>>сорри, на курсы телепата ещё не пошёл, и пока не собираюсь E>а что значит "недоступная операция"?
значит что не реализована, и не нужна по семантике задачи.