Re[11]: Про типы и логику
От: enji  
Дата: 09.02.15 05:59
Оценка:
Здравствуйте, Mamut, Вы писали:

M>

M>But I discovered that in the presence of SelfTestingCode, most bugs that static types would have were found just as easily by the tests. Since the tests found much more than type errors, you needed them in either a static or dynamically typed language, so having the static typing gave you little gain.


Это все мило, вот только количество тестов разное. У тебя везде 100% покрытие тестами, причем не по строкам, а по логике? Если так — ты крут. Однако не всегда есть возможность так делать. И если мы на статически типизированном языке, часть ошибок выловит компилятор. Зачем от этого отказываться?

M>Нет. Я пытаюсь выбить из апологетов типизации хоть что-то реальное, а не последовательные сказки
Автор: Mamut
Дата: 07.02.15
про то, как типизация помогает, спасает, проверят и прочая и прочая и прочая. Любые наводящие вопросы разбиваются о стену новых «верь мне, компилятор все проверит» и т.п. Ну вот ярчайший пример
Автор: genre
Дата: 05.02.15
в соседней ветке.


Ты ставишь вопрос — как реализовать всю логику на типах. Тебе отвечают — типы не позволяют сложить километры с килограммами, вызвать отсутствующую функцию, позвать функцию с неверным количеством аргументов. Чего ты еще хочешь то?
Re[10]: Ах, да
От: enji  
Дата: 09.02.15 06:05
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Вот появилась задача с ad-hoc требованиям, основанная на реальной задаче из кода самого настоящего банка. Специально написал, чтобы проверить, как все ваши заявления работают при столкновении с реальной задачей.


Типы помогут, когда ты при изменении требований вдруг куда-нибудь передашь строку вместо числа или вызовешь функцию, в которой поменялось количество аргументов. И у тебя не будет юнит-теста, который при этом свалится. Но врядли ты с их помощью проверишь бизнес-логику, если конечно предварительно сильно не заморочиться, в духе того, что предлагал Кодт выше. Однако так врядли кто-то делает
Re[4]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 09.02.15 08:20
Оценка:
IT>Ты пытаешься сделать тоже самое. Показать на примитивной задаче ненужность типов. При этом делая акцент не на примитивности, а на ненужности.

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

Ведь jazzer же привел презентацию из банка, в которой утверждалось, что, мол, «типы не позволяют писать неправильный код», например. Я привел реальную задачу из банка Нет, задача не такая, я оказывается что-то доказать хочу и прочая и прочая.

Могу только повторить

Вот я не понимаю. Спрашиваешь вопрос про любой язык программирования — тебе и ответят, и примеры покажут, и ссылки подкинут — все, что угодно. Как только дело доходит до апологетов «типы везде, они рулят», все, тишина, одна демагогия на пять страниц ответов


Вот тут несколько человек в хором говорят
Автор: Mamut
Дата: 07.02.15
о разных преимуществах типов. Что мешает привести ну хоть мало-мальский пример типа задачи, что я привел?

Ну, показать, мол: вот у нас есть такие требования, мы их решили так и так. Потом требования поменялись, мы меняем так, а нам типы помогат это сделать вот эдак. Ну вот продемонстрировать все эти «картинки», «паззлы», «компилятор помогает с ad-hoc требованиями», «типы помгают реализовывать сложные условия» и прочая и прочая?


[тонны текста про картинки и паззлы скипнуты]

IT>Типы — это дополнительный уровень верификации кода на самых ранних этапах возникновения проблемы. Те же юнит-тесты ловят последствия, типы позволяют устранить причину. Мне вообще странно слышать подобные разговоры от людей с опытом. То, что вы у себя в конторе научились есть кактус и при этом не сильно колоться, говорит лишь о вашем упёрстве и пониженном болевом пороге. Это очень круто. Примерно так же круто, как в цирке глотать шпаги или совать голову в пасть хищнику. И если бы вы со своим кактусом выступали в цирке, то я бы аплодировал стоя. Но в жизни то это нафига нужно?


Опять — тонны текста, демагогия, аналогии и рассказы о том, каким мы тупые, с нашим кактусом. Извини. Это — не аргументация.


dmitriid.comGitHubLinkedIn
Re[11]: Ах, да
От: Mamut Швеция http://dmitriid.com
Дата: 09.02.15 08:22
Оценка:
E>Типы помогут, когда ты при изменении требований вдруг куда-нибудь передашь строку вместо числа или вызовешь функцию, в которой поменялось количество аргументов. И у тебя не будет юнит-теста, который при этом свалится.

С этим я и не спорю: http://rsdn.ru/forum/philosophy/5946038.1
Автор: Mamut
Дата: 06.02.15


E>Но врядли ты с их помощью проверишь бизнес-логику, если конечно предварительно сильно не заморочиться, в духе того, что предлагал Кодт выше. Однако так врядли кто-то делает


И все? Это, имхо, идет сильно вразез с тем, что мне тут в сотне сообщений рассказывали


dmitriid.comGitHubLinkedIn
Re[12]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 09.02.15 08:25
Оценка:
E>Это все мило, вот только количество тестов разное. У тебя везде 100% покрытие тестами, причем не по строкам, а по логике? Если так — ты крут. Однако не всегда есть возможность так делать. И если мы на статически типизированном языке, часть ошибок выловит компилятор. Зачем от этого отказываться?

Количество тестов далеко не 100%, но при этом проблемы, связанные именно со «складыванием килограммов с километрами» вылезают очень и очень редко. Самые главные проблемы — это именно бизнес-логика.

M>>Нет. Я пытаюсь выбить из апологетов типизации хоть что-то реальное, а не последовательные сказки
Автор: Mamut
Дата: 07.02.15
про то, как типизация помогает, спасает, проверят и прочая и прочая и прочая. Любые наводящие вопросы разбиваются о стену новых «верь мне, компилятор все проверит» и т.п. Ну вот ярчайший пример
Автор: genre
Дата: 05.02.15
в соседней ветке.


E>Ты ставишь вопрос — как реализовать всю логику на типах. Тебе отвечают — типы не позволяют сложить километры с килограммами, вызвать отсутствующую функцию, позвать функцию с неверным количеством аргументов. Чего ты еще хочешь то?



Эээ нет. Мне отвечают в стиле «как можно логики переносить в типы» и «решают задачу бана неправильного кода, где правильность закодирована в определении. У тебя такого бана нету. Можно проверить is_forbidden и тут же дернуть update_amount, и компилятор и не почешется на эту тему, и останется только уповать на тесты» и прочие «паззлы».

Как только просишь привести конкретные примеры — в ответ тишина.

Если все сводится только к «типы не позволяют сложить километры с килограммами», то так и говорите Я проти этого вообще и слова не скажу


dmitriid.comGitHubLinkedIn
Re[12]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 09.02.15 08:47
Оценка:
EP>>>Повторюсь в очередной раз, для этой задачи это не имеет смысла.
M>>Предложи задачу, для которой имеет

EP>Для тех задач где есть какие-то предусловия:


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


EP>
EP>template<typename State>
EP>enable_if_t
EP><
EP>    State::prepared && State::risk_checked || State::approved_by_boss
>> change_amount_unconditionally(Order<State> x, Money amount)
EP>{
EP>    // ...
EP>}
EP>



Можно мне наконец увидеть полное решение задачи в корневом сообщении со всеми этими enable_if_t?

M>>Определи понятие «сложные условия» и почему условия в моей задачи, видимо, недостаточно сложные


EP>Runtime данные можно переводить в compile-time, причём данные любой сложности, об этом я неоднократно говорил в предыдущем топике, и даже приводил конкретный код. Вопрос упирается в code-bloat.


Можно ссылку на конкретный код? Потому что я помню только куски кода, которые разваливались от банального вопроса типа «а что будет, если у нас немного больше условий, чем проверка на одно состояние».

EP>Перевести несколько bool из runtime в compile-time — не проблема. А вот например перевод unsigned price — скорей всего будет непрактичным.


Можно увидеть это на примере задачи з корневого сообщения?

EP>Более сложный пример: на типах можно задать грамматику DSL, и разрешать только те выражения, которые проходят проверку. Пример — Boost.Proto.


Спасибо. Наконец-то, часть вторая

Да, про DSL'и я согласен. Хотя и тут есть свои «но» (опишу отдельным текстом в конце этого сообщения)

M>>Отлавливается первым же залетным тестом

EP>Mars Climate Orbiter тесты не спасли. Хотя, по всей видимости, тестировалось всё более пристрастно чем типичный опердень.
EP>Image: mars98orb.jpg

В зависимости от реализации, типы тоже могут нифига не спасти

Классический пример, у нас был, кстати. Идет общение со сторонним сервисом. Мы отдаем JSON, та сторона принимает JSON. Наша сторона банально пакует данные в JSON и отправляет. На той стороне JSON принимается, распаковывается и используется.

Ну, с нашей стороны приходит валидный объект, генерируется валидный JSON, но в какой-то момент все ломается Принимающая сторона решила, что теперь поле X должно быть не числом, а строкой

M>>Ну да, при рефакотринге будет приятно. В реальных задачах будет занимать мизерную часть проблем.


EP>И даже 100% покрытие строчек кода тестами не даёт гарантии что все ошибки этого класса найдены.


100% покрытие типами вообще не дает никакой гарантии, что код вообще правильный Могу только повторить. У нас самые главные проблемы — это бизнес-логика, а не несоответсвие килограммов с километрами

------

Про DSL. Ну, может не столько про DSL, но все же.

Банки общаются между собой так называемыми payment files. Это, по сути, — текстовые файлы с определенной структурой, где каждая строка (грубо говоря) — это указание кто кому сколько денег перевел на какой тип счета. По большому счету — это примитивный DSL, потому что там есть какие-то управляющие конструкции и контекстно зависимые поля, емнип.

На все это дело есть полтора международных стандарта, которым банки должны следовать.

АГАЩАЗБЛИН

У каждого первого банка есть свои мысли по поводу того, как реализовывать эти стандарты (благо там есть двусмысленные места), и каждые первые же расширяет эти стандарты своими нестандартными расширениями

Вот пишет команда весь их себя правильный парсер, не позволяющий никаких неправильных конструкций и при первом же прогоне на реальных файлах получает всякие TypeError'ы, потому что ожидалось целое, а пришел float и т.п. И все в рантайме

Но сам парсер правильный, да

В общем, интеграция каждого нового банка занимает почти неделю. Одна из причин — попытка выяснить, в каких именно местах они отходят от стандарта, и каким образом они его расширяют. А потом минимум раз в месяц банк присылает файл, который не соответсвует ни стандарту ни тому, что они рассказали про свои файлы catch TypeError -> log("банк снова офигел, см. файл такой-то")

В общем, этот рассказ не столько против типов, сколько про то, что типы наверняка помогут сделать правильный DSL. Но потом в этот DSL начинает приходить все, что угодно, и вылетать оно будет, как назло, в рантайме


dmitriid.comGitHubLinkedIn
Re[4]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 09.02.15 08:55
Оценка:
M>>Приведи другой пример
A>а что именно ты хочешь? полиморфизм?


Я хочу, чтобы мне пошагово, на примерах (желательно, приближенных к реальным задачам) показали хоть что-то из этих рассказов
Автор: Mamut
Дата: 07.02.15
.

Я многого прошу? Да вроде нет. Тут в соседних
Автор: x-code
Дата: 12.01.15
темах
Автор: x-code
Дата: 21.01.15
ни у кого нет никаких
Автор: AlexRK
Дата: 26.10.14
проблем
Автор: NeoCode
Дата: 10.12.14
продемонстрировать
Автор: _NN_
Дата: 02.12.14
что-либо
Автор: vsb
Дата: 04.11.14
на примерах
Автор: x-code
Дата: 26.10.14
. Доходит вопрос до статической типизации — тонны текста, ноль примеров.

A>или optional<T> и прочие паттерн-матчинги, монады и вот это всё


Да-да-да, вот это всё ©


dmitriid.comGitHubLinkedIn
Re[6]: Ах да, забыл
От: Кодт Россия  
Дата: 09.02.15 10:11
Оценка: 21 (1)
Здравствуйте, Mamut, Вы писали:

К>>Как видишь, тут и наглядность не страдает, и кастомизабельность — как следствие — достаточно высокая.


M>Ээээ, что? Я, конечно, дааавненько на C++ не смотрел, но разобраться во всех этих шаблонах и зависимостях для меня проблема. Скажем, я тут вообще не понимаю: и что же дальше


Там две части.
Первая — это фреймворк для создания функтора "фантомный тип".
Вторая — это, собственно, программа. Начиная с "// признаки, которые нам нужны на первом шаге — пока что свалю в кучу"

Дальше получается так
auto good_1 = Start::action( phantom_type<Good,void>(1) ); // положили товар в корзину; тип - phantom_type<Good,just_started>
auto good_2 = Pay::action( good_1 ); // оплатили: phantom_type<Good, {just_started, is_checked=true, is_paid=true} >
auto good_3 = Increase::action( good_2 ); // добавили: phantom_type<Good, {just_started, is_checked=false, is_paid=true} >
auto good_4 = Pay::action( good_3 ); // оплатили добавку
auto good_5 = Send::action( good_4 ); // отправили


M>По-моему, чтобы такое написать, надо быть семи пядей во лбу


Не семи пядей. Просто мне было лень тащить буст (там в mpl можно много чего сделать), и я руками минимум-миниморум наколбасил.


К>>И несложно растащить функции (XXX::work) и метафункции (XXX::precondition, XXX::transform)

M>Я за 10 минут растащил все это без шаблонов

Так, небось, всё в рантайме сделал на эрланге. В рантайме-то любой дурак сделает.

К>>Возможно, что в бусте уже всё придумано за нас. А если не придумано, допилю и выложу в продакшен


M>Да, хотел бы посмотреть на результат Надо не забывать, из всего этого еще внятные ошибки хотелось бы возвращать


Статик ассерты наше всё. Но над этим надо поработать.
Перекуём баги на фичи!
Re[7]: Ах да, забыл
От: Mamut Швеция http://dmitriid.com
Дата: 09.02.15 10:20
Оценка:
К>Дальше получается так

Ага. Все, понял.

Ну и да, без auto это действительно могла выглядеть страшно и многословно

К>Так, небось, всё в рантайме сделал на эрланге. В рантайме-то любой дурак сделает.


Ну дык


dmitriid.comGitHubLinkedIn
Re[4]: Про типы и логику
От: Кодт Россия  
Дата: 09.02.15 10:25
Оценка: +2
Здравствуйте, Abyx, Вы писали:

A>а что именно ты хочешь? полиморфизм?


Полиморфизм можно или в рантайм вытащить — вариантные типы, кортежи с признаками, старое доброе ООП (GADT для любителей хаскелла), наконец; или вывернуть красную шапочку мясом наружу, сделать всё на продолжениях.
Тут — кому что эстетичнее. И какой язык подо что заточен.


A>или тебе надо статическую проверку типов?


В конце концов, достаточно мощный статический анализатор может бить по пальцам за assertion failed, если рантаймовый код достаточно прозрачен.
Перекуём баги на фичи!
Re[13]: Про типы и логику
От: WolfHound  
Дата: 09.02.15 15:26
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Классический пример, у нас был, кстати. Идет общение со сторонним сервисом. Мы отдаем JSON, та сторона принимает JSON. Наша сторона банально пакует данные в JSON и отправляет. На той стороне JSON принимается, распаковывается и используется.

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

Если бы протокол был статически типизирован и компилятор бил бы по рукам разработчиков, которые пытаются сделать что-то не так, то данного класса проблем бы не было.
О чем тебе и говорят.

Но ты продолжаешь твердить, что типы не нужны.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[14]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 09.02.15 15:44
Оценка:
WH>JSON динамически типизированный. Из-за этого все те проблемы, о которых ты тут плачешь.

Я не плачу про проблемы.

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


Если бы да кабы, да во рту росли грибы. «Статически типизированный протокол» может быть хоть четырежды статически типизированным, но это не спасет от банальнейшей ситуации:

Сервер. Начинает принимать протокол версии 2.0, который меняет тип поля.
Клиент. Продолжает отсылать протокол версии 1.2, в котором тип поля старый.

WH>О чем тебе и говорят.

WH>Но ты продолжаешь твердить, что типы не нужны.

Я не твержу, что типы не нужны.


dmitriid.comGitHubLinkedIn
Re[5]: Про типы и логику
От: IT Россия linq2db.com
Дата: 09.02.15 23:19
Оценка: +2
Здравствуйте, Mamut, Вы писали:

IT>>Ты пытаешься сделать тоже самое. Показать на примитивной задаче ненужность типов. При этом делая акцент не на примитивности, а на ненужности.

M>Нет, не пытаюсь. Я пытаюсь выбить из апологетов типов что-то большее,

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

M>Не нравится эта задача — предложи/покажи другую задача. В чем проблема-то?


Такой пример тебя устроит?

t.FirstName++;


M>Опять — тонны текста, демагогия, аналогии и рассказы о том, каким мы тупые, с нашим кактусом. Извини. Это — не аргументация.


Мамут, ты уже задолбал подобными аргументами. Тебе в каждом сообщении мерещатся только тонны текста, демагогия, жалобы и рассказы. Давай уже меняй пластинку. И ещё сходи почитай хотя бы в туже википедию определение демагогии.

По поводу типов повторюсь ещё раз. Мне очень странно слыашать подобные разговоры от человека с опытом. Ты споришь с основами мироздания в программировании. С аксиомами. Это даже доказывать не надо. Ты пойми, как параллельные прямые не пересекаются, так и типизация устраняет причины возникновения ошибок, связанных с типами. Ты бы ещё начал доказывать, что если "Hello, world" можно написать в notepad, то всякие вижуал студии и решарперы овно, никому не нужны и даже вредны.
Если нам не помогут, то мы тоже никого не пощадим.
Re[13]: Про типы и логику
От: Evgeny.Panasyuk Россия  
Дата: 10.02.15 06:24
Оценка: 21 (1)
Здравствуйте, Mamut, Вы писали:

M>>>Предложи задачу, для которой имеет

EP>>Для тех задач где есть какие-то предусловия:
M>В первом же сообщении этой темы есть задача, где эти предусловия есть. То есть до того, как мы собственно меняем amount, у нас идет толпа предусловий

Вот если бы это изменение amount, с предусловиями, многократно использовалось в разных местах — то какой-то смысл был бы.
А так получится явно более громоздко чем твой вариант

EP>>
EP>>template<typename State>
EP>>enable_if_t
EP>><
EP>>    State::prepared && State::risk_checked || State::approved_by_boss
>>> change_amount_unconditionally(Order<State> x, Money amount)
EP>>{
EP>>    // ...
EP>>}
EP>>

M>Можно мне наконец увидеть полное решение задачи в корневом сообщении

В n-ый раз повторю — для неё не имеет смысла. Ведь ты же хочешь сравнить два решения, так?
Не вижу смысла сравнивать "кодирование логики на типах" против варианта без этого на задаче где эта самая логика на типах не имеет смысла.
Если же тебе нужен просто сферический пример предусловий на типах — смотри пример кода выше. Если же нужны пояснения/дополнения по коду — то спрашивай.

M>со всеми этими enable_if_t?


enable_if_t — это вообще стандартная утилита.
http://en.cppreference.com/w/cpp/types/enable_if

EP>>Runtime данные можно переводить в compile-time, причём данные любой сложности, об этом я неоднократно говорил в предыдущем топике, и даже приводил конкретный код. Вопрос упирается в code-bloat.

M>Можно ссылку на конкретный код? Потому что я помню только куски кода, которые разваливались от банального вопроса типа «а что будет, если у нас немного больше условий, чем проверка на одно состояние».

Уже многократно приводил: http://rsdn.ru/forum/cpp/5824553.flat
Автор: Кодт
Дата: 20.10.14

Вкратце есть два основных варианта.
Первый это continuation-passing style, например:
template<typename F>
void read_order(F f)
{
    bool is_prepared = read_bool();
    if(is_prepared)
        f(Order<true>{});
    else
        f(Order<false>{});
}
// Example of usage:
{
    read_order([](auto order)
    {
        use(order)
    });
}

Второй это varaint либо аналоги:
variant<Order<true>, Order<false>> read_order()
{
    bool is_prepared = read_bool();
    if(is_prepared)
        return Order<true>{};
    else
        return Order<false>{};
}
// Example of usage:
{
    auto x= read_order();
    // ...
    apply(x, [](auto order)
    {
        use(order)
    });
}

Если в этих примерах функция use принимает только конкретный Order<true>, то на этапе компиляции появится ошибка при передачи Order<false>, и в этом случае пользователь функции use будет вынужден отфильтровать типы order'ов, например через pattern matching перегрузкой.

Причём всю эту десериализацию из runtime в compile-time можно автоматизировать посредством мета-программирования.

M>>>Отлавливается первым же залетным тестом

EP>>Mars Climate Orbiter тесты не спасли. Хотя, по всей видимости, тестировалось всё более пристрастно чем типичный опердень.
EP>>Image: mars98orb.jpg
M>В зависимости от реализации, типы тоже могут нифига не спасти

Отчего же? Если бы в интерфейсе у них было не просто float/double, а конкретные единицы измерения — то проблему можно было бы избежать.

M>Классический пример, у нас был, кстати. Идет общение со сторонним сервисом. Мы отдаем JSON, та сторона принимает JSON. Наша сторона банально пакует данные в JSON и отправляет. На той стороне JSON принимается, распаковывается и используется.

M>Ну, с нашей стороны приходит валидный объект, генерируется валидный JSON, но в какой-то момент все ломается Принимающая сторона решила, что теперь поле X должно быть не числом, а строкой

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

M>>>Ну да, при рефакотринге будет приятно. В реальных задачах будет занимать мизерную часть проблем.

EP>>И даже 100% покрытие строчек кода тестами не даёт гарантии что все ошибки этого класса найдены.
M>100% покрытие типами вообще не дает никакой гарантии, что код вообще правильный

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

M>Могу только повторить. У нас самые главные проблемы — это бизнес-логика, а не несоответсвие килограммов с километрами


Я не знаю что конкретно ты называешь бизнес-логикой, но для меня несоответствие килограммов с километрами это проблема из предметной области.

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


Я говорил не просто про DSL, а про Embedded Domain Specific Language, Boost.Proto как раз про это.
То есть в C++ встраивается под-язык какой-то предметной области. И система типов помогает отлавливать грамматические ошибки в этом самом EDSL на этапе компиляции.
Re[6]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 10.02.15 09:12
Оценка:
IT>Выбивают обычно показания, причём желательно устраивающие выбивающего. Впрочем, именно этим ты тут и занимаешься. Тебя же ведь не интересует истина, правда? Тебе же нужно по любому отстоять своё мнение.


Нет. Мне не надо отстоять свое мнение. Свое мнение я высказывал несколько раз:

M>>Опять — тонны текста, демагогия, аналогии и рассказы о том, каким мы тупые, с нашим кактусом. Извини. Это — не аргументация.


IT>По поводу типов повторюсь ещё раз. Мне очень странно слыашать подобные разговоры от человека с опытом. Ты споришь с основами мироздания в программировании. С аксиомами. Это даже доказывать не надо. Ты пойми, как параллельные прямые не пересекаются, так и типизация устраняет причины возникновения ошибок, связанных с типами. Ты бы ещё начал доказывать, что если "Hello, world" можно написать в notepad, то всякие вижуал студии и решарперы овно, никому не нужны и даже вредны.


Тебе в каждом сообщении мерещатся только тонны текста


Говорит мне человек и продолжает писать тонны текста.


«типизация устраняет причины возникновения ошибок, связанных с типами» — с этим утверждением я нигде не спорю Я последовательно прошу привести примеры утверждений, которые начинаются от «типы не позволят написать неверный код» до прочих многословных пафосных заявлений
Автор: Mamut
Дата: 07.02.15
.

Я могу только повторить http://rsdn.ru/forum/philosophy/5948529.1
Автор: Mamut
Дата: 09.02.15


Ты почему-то видишь какие-то «подгонки под мое видение мира» и «тебе не нужна истина»


dmitriid.comGitHubLinkedIn
Re[14]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 10.02.15 09:28
Оценка:
EP>Вот если бы это изменение amount, с предусловиями, многократно использовалось в разных местах — то какой-то смысл был бы.
EP>А так получится явно более громоздко чем твой вариант

Ну то есть типы помогают только при copy-paste based programming'е? Как только одинаковые «предусловия» из ста мест переносятся в один вызов API, они сразу становятся ненужны и «более громоздки»?

EP>В n-ый раз повторю — для неё не имеет смысла. Ведь ты же хочешь сравнить два решения, так?

EP>Не вижу смысла сравнивать "кодирование логики на типах" против варианта без этого на задаче где эта самая логика на типах не имеет смысла.

Я тогда совсем плохо начинаю понимать смысл всех этих пафосных заявлений
Автор: Mamut
Дата: 07.02.15


EP>Если в этих примерах функция use принимает только конкретный Order<true>, то на этапе компиляции появится ошибка при передачи Order<false>, и в этом случае пользователь функции use будет вынужден отфильтровать типы order'ов, например через pattern matching перегрузкой.

EP>Причём всю эту десериализацию из runtime в compile-time можно автоматизировать посредством мета-программирования.

Эээ. Как? (Я просто не знаю)


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


Это да. Но это вопрос не к типизации, а культуре программирования. В нашей команде, несмотря на динамическую типизацию, с этим (ну,с проникновением неправильных типов) проблем нет, потому что для каждого вызова есть описание в виде JSON Schema, с проверками входных и выходных данных на соответствие этой схеме. Плюс все (обратно несовместимые) изменения обязательно меняют номер версии.

В итоге доходит до смешного. Абсолютно все пользователи нашего API имеют такую же JSON Schema, как и мы (все получают их из одного центрального места). Но потом приходит письмо типа «пацаны, мы вам все присылаем правильно, а оно не работает, посмотрите, в чем ошибка». А ошибка, которую они получают, выглядит типа так:

HTTP 400 Bad Request
Content-Type  application/vnd.klarna.com.error-v2+json

{
  "message": "An error has occured. Please try again later",
  "developer_message": "Field order.billing_address.zip must be a string",
  "error_location": "/order/0/billing_address/zip"
}


Потому что запрос не прошел валидацию по схеме. Сидишь и думаешь: ну ведь не мы же идиоты, да? А все таки программисты у клиента


M>>Могу только повторить. У нас самые главные проблемы — это бизнес-логика, а не несоответсвие килограммов с километрами

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

Ну бизнес-логикой я называю, например, тот же пример из корневого сообщения.


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

EP>Я говорил не просто про DSL, а про Embedded Domain Specific Language, Boost.Proto как раз про это.
EP>То есть в C++ встраивается под-язык какой-то предметной области. И система типов помогает отлавливать грамматические ошибки в этом самом EDSL на этапе компиляции.

Ну, в этих случаях это понятно, тут да. Так как все известно и доступно на момент компиляции, то каких-либо возражений против этого не имею


dmitriid.comGitHubLinkedIn
Re[15]: Про типы и логику
От: Evgeny.Panasyuk Россия  
Дата: 10.02.15 10:21
Оценка: 21 (1)
Здравствуйте, Mamut, Вы писали:

M>Ну то есть типы помогают только при copy-paste based programming'е? Как только одинаковые «предусловия» из ста мест переносятся в один вызов API, они сразу становятся ненужны и «более громоздки»?


Опять таки, считай что при каждом вызове типизированной функции в статических языках расставляются "виртуальные" assert'ы. У тебя вряд ли получится написать код так, что все эти assert'ы собирутся в одном месте
Вот те же единицы измерения — попробуй переписать свой код так, чтобы все виртуальные assert'ы а-ля assert(typeof(x) == money) собрались в одном месте.

EP>>В n-ый раз повторю — для неё не имеет смысла. Ведь ты же хочешь сравнить два решения, так?

EP>>Не вижу смысла сравнивать "кодирование логики на типах" против варианта без этого на задаче где эта самая логика на типах не имеет смысла.
M>Я тогда совсем плохо начинаю понимать смысл всех этих пафосных заявлений
Автор: Mamut
Дата: 07.02.15


В очередной раз — то что в какой-то твоей конкретной под-задаче, нет смысла кодировать логику на типах, не означает что типы не помогают отловить логические ошибки. Это также не означает что type-rich programming, не помогает отловить больше ошибок чем type-poor programming.

EP>>Если в этих примерах функция use принимает только конкретный Order<true>, то на этапе компиляции появится ошибка при передачи Order<false>, и в этом случае пользователь функции use будет вынужден отфильтровать типы order'ов, например через pattern matching перегрузкой.

EP>>Причём всю эту десериализацию из runtime в compile-time можно автоматизировать посредством мета-программирования.
M>Эээ. Как? (Я просто не знаю)

Вот пример атомизации конвертации N значений типа bool из runtime в compile-time.
Здесь read_compile_time_bools считывает заданное количество bool, складывает их в compile-time массив, и после передаёт этот массив в пользовательский функциональный объект (конкретно здесь в лямбду).
Естественно можно автоматизировать конвертирование и более сложных структур.
LIVE DEMO
  пример
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/at.hpp>

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;
using namespace boost;

bool read_runtime_bool()
{
    return rand() % 2 == 1;
}

template<typename State=mpl::vector<>, int Count, typename F>
void read_compile_time_bools(mpl::int_<Count>, F f)
{
    if(read_runtime_bool() == true)
        read_compile_time_bools<typename mpl::push_back<State, mpl::true_>::type>(mpl::int_<Count-1>{}, f);
    else
        read_compile_time_bools<typename mpl::push_back<State, mpl::false_>::type>(mpl::int_<Count-1>{}, f);
        
}

template<typename State, typename F>
void read_compile_time_bools(mpl::int_<0>, F f)
{
    f(State{});
}

int main()
{
    srand(time(0));

    read_compile_time_bools(mpl::int_<5>{}, [](auto bools)
    {
        mpl::for_each<decltype(bools)>([](auto flag)
        {
            constexpr bool compile_time_bool = decltype(flag)::value;
            static_assert(compile_time_bool == true || compile_time_bool == false, "");
            cout << compile_time_bool << endl;
        });
    });
}
Re[15]: Про типы и логику
От: WolfHound  
Дата: 10.02.15 13:00
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Если бы да кабы, да во рту росли грибы.

Аргументов как обычно нет...

M>Сервер. Начинает принимать протокол версии 2.0, который меняет тип поля.

M>Клиент. Продолжает отсылать протокол версии 1.2, в котором тип поля старый.
Спасает. Нормальные люди не забывают проверять версию протокола при соединении.
И вместо мутных багов будет понятное сообщение о том, что нужно протокол обновить.
При обновлении кода клиента компилятор будет бить по рукам везде, где программист забудет исправить типы.

M>Я не твержу, что типы не нужны.

А чем ты тут занимаешься?
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[16]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 10.02.15 19:56
Оценка:
M>>Сервер. Начинает принимать протокол версии 2.0, который меняет тип поля.
M>>Клиент. Продолжает отсылать протокол версии 1.2, в котором тип поля старый.
WH>Спасает. Нормальные люди не забывают проверять версию протокола при соединении.

Спасает при условии нормальных людей

WH>И вместо мутных багов будет понятное сообщение о том, что нужно протокол обновить.


Ой. Ты не поверишь, в нашей команде у нас такое прекрасно происходит с вовсю динамическим Эрлангом.

WH>При обновлении кода клиента компилятор будет бить по рукам везде, где программист забудет исправить типы.


Ага. При обновлении кода клиента. Ну вот мы обновили код клиента в насквозь динамическом Эрланге, и все заработало на ура.


Смешно, как ты утверждаешь, что «данного класса проблем бы не было.», но потом тут же повторяешь ровно то, что я говорю: что нифига она не спасает, если
— Нормальные люди не забывают проверять версию протокола
— Клиент не обновлен



M>>Я не твержу, что типы не нужны.

WH>А чем ты тут занимаешься?

Я на этот вопрос ответил уже много раз


dmitriid.comGitHubLinkedIn
Отредактировано 10.02.2015 20:10 Mamut [ищите в других сетях] . Предыдущая версия .
Re[17]: Про типы и логику
От: WolfHound  
Дата: 10.02.15 20:22
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Ага. При обновлении кода клиента. Ну вот мы обновили код клиента в насквозь динамическом Эрланге, и все заработало на ура.

В итоге доходит до смешного. Абсолютно все пользователи нашего API имеют такую же JSON Schema, как и мы (все получают их из одного центрального места). Но потом приходит письмо типа «пацаны, мы вам все присылаем правильно, а оно не работает, посмотрите, в чем ошибка». А ошибка, которую они получают, выглядит типа так:

HTTP 400 Bad Request
Content-Type  application/vnd.klarna.com.error-v2+json

{
  "message": "An error has occured. Please try again later",
  "developer_message": "Field order.billing_address.zip must be a string",
  "error_location": "/order/0/billing_address/zip"
}

(С)
Автор: Mamut
Дата: 10.02.15

Ты в каком из двух сообщений врёшь?

Если бы схема проверялась статически, то таких ошибок бы не было.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.