Re[63]: Haskell нужен! (в Standard Chartered Bank)
От: AlexRK  
Дата: 26.02.15 16:38
Оценка: +1
Здравствуйте, Mamut, Вы писали:

M>Чем это принципиально отличается от одной точки входа, после которой идут условия? Простейший вопрос:


M>Было: copy-paste кода в 5 мест в виде if(X)->if(Y)->if(Z)->вызов_функции(). Раскорячились, написали «предусловия» на типах


M>Стало: перенесли if(X)->if(Y)->if(Z) в саму функцию. Теперь в пяти местах стоит только вызов_функции(). Все, «это действительно не имеет смысла»© и «То есть предусловий нет? О чём и речь»© ?


Между ифами может быть много кода, причем в разных местах — разного. Не всегда возможно перенести ифы в одну функцию.
То есть проверки условий могут быть разбросаны по разным местам системы. К примеру, проверили где-то наверху, что переменная не равна нулю, и дальше с помощью типов это знание растекается по всем функциям.
Re[63]: Haskell нужен! (в Standard Chartered Bank)
От: Evgeny.Panasyuk Россия  
Дата: 26.02.15 16:53
Оценка:
Здравствуйте, Mamut, Вы писали:

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

EP>>Что за мода такая пошла на экстраполяцию из каких-то частных случаев?
M>Какие к черту частные случаи? Ты говоришь про общий случай уже ниже:

Частный случай это твоя конкретная постановка задачи.

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

M>Чем это принципиально отличается от одной точки входа, после которой идут условия? Простейший вопрос:
M>Было: copy-paste кода в 5 мест в виде if(X)->if(Y)->if(Z)->вызов_функции(). Раскорячились, написали «предусловия» на типах
M>Стало: перенесли if(X)->if(Y)->if(Z) в саму функцию. Теперь в пяти местах стоит только вызов_функции(). Все, «это действительно не имеет смысла»© и «То есть предусловий нет? О чём и речь»© ?

Как во втором варианте функция реагирует на !X || !Y || !Z?
Re[64]: Haskell нужен! (в Standard Chartered Bank)
От: Mamut Швеция http://dmitriid.com
Дата: 26.02.15 18:17
Оценка: :)
M>>Чем это принципиально отличается от одной точки входа, после которой идут условия? Простейший вопрос:
M>>Было: copy-paste кода в 5 мест в виде if(X)->if(Y)->if(Z)->вызов_функции(). Раскорячились, написали «предусловия» на типах
M>>Стало: перенесли if(X)->if(Y)->if(Z) в саму функцию. Теперь в пяти местах стоит только вызов_функции(). Все, «это действительно не имеет смысла»© и «То есть предусловий нет? О чём и речь»© ?

EP>Как во втором варианте функция реагирует на !X || !Y || !Z?


Как это отвечает на мой вопрос? Никак.


dmitriid.comGitHubLinkedIn
Re[64]: Haskell нужен! (в Standard Chartered Bank)
От: Mamut Швеция http://dmitriid.com
Дата: 26.02.15 18:19
Оценка:
M>>Чем это принципиально отличается от одной точки входа, после которой идут условия? Простейший вопрос:

M>>Было: copy-paste кода в 5 мест в виде if(X)->if(Y)->if(Z)->вызов_функции(). Раскорячились, написали «предусловия» на типах


M>>Стало: перенесли if(X)->if(Y)->if(Z) в саму функцию. Теперь в пяти местах стоит только вызов_функции(). Все, «это действительно не имеет смысла»© и «То есть предусловий нет? О чём и речь»© ?


ARK>Между ифами может быть много кода, причем в разных местах — разного. Не всегда возможно перенести ифы в одну функцию.

ARK>То есть проверки условий могут быть разбросаны по разным местам системы. К примеру, проверили где-то наверху, что переменная не равна нулю, и дальше с помощью типов это знание растекается по всем функциям.


Блин. Чем дальше, тем любопытсвеннее © Чем дальше, тем более идиотские странные условия должны выполниться, чтобы мы наконец-то увидели всю мощь и красоту типов

Отредактировано: И да, введение условия про «где-то там if-ы и прочая» не отменяет моего вопроса, от слова вообще. Даже в моей задаче «может быть много кода между if-ами» и т.п.


dmitriid.comGitHubLinkedIn
Отредактировано 26.02.2015 18:20 Mamut [ищите в других сетях] . Предыдущая версия .
Re[65]: Haskell нужен! (в Standard Chartered Bank)
От: AlexRK  
Дата: 26.02.15 20:30
Оценка:
Здравствуйте, Mamut, Вы писали:

ARK>>Между ифами может быть много кода, причем в разных местах — разного. Не всегда возможно перенести ифы в одну функцию.

ARK>>То есть проверки условий могут быть разбросаны по разным местам системы. К примеру, проверили где-то наверху, что переменная не равна нулю, и дальше с помощью типов это знание растекается по всем функциям.

M>Отредактировано: И да, введение условия про «где-то там if-ы и прочая» не отменяет моего вопроса, от слова вообще. Даже в моей задаче «может быть много кода между if-ами» и т.п.


Ну... не знаю, как еще объяснить. На мой взгляд, принципиальное различие очевидно — в случае с типами программист может возложить на компилятор дополнительные проверки, в случае без типов — такие проверки делаются тестами. О чем тут еще спорить... Нужны ли дополнительные проверки с помощью типизации? Всегда ли они нужны? Сложно их писать или просто? Где человек скорее ошибется — в описании типа или в коде теста? Все это бессмысленно обсуждать в отрыве от предметной области, цены ошибки, квалификации программиста, качества доступных инструментов разработки и т.п. Если брать сферического коня в вакууме, то лично мое мнение — чем больше можно проверить на этапе компиляции, тем лучше.
Re[66]: Haskell нужен! (в Standard Chartered Bank)
От: Mamut Швеция http://dmitriid.com
Дата: 26.02.15 21:05
Оценка:
M>>Отредактировано: И да, введение условия про «где-то там if-ы и прочая» не отменяет моего вопроса, от слова вообще. Даже в моей задаче «может быть много кода между if-ами» и т.п.

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


Хороша песня, начинай сначала


Вот есть код, пусть даже гипотетический. Есть вопрос по коду и/или работе с кодом. Мне в ответ говорят «нет, тут бессмысленно это». Спрашиваю, «в чем бессмысленность? в чем принципиальное различие от ситуации X?». «принципиальное различие очевидно — в случае с типами программист может возложить на компилятор дополнительные проверки». И так — по кругу.

ARK>Если брать сферического коня в вакууме, то лично мое мнение — чем больше можно проверить на этапе компиляции, тем лучше.


Выделенное — это ключевое во всех этих спорах. О чем я рядом уже говорил
Автор: Mamut
Дата: 26.02.15
.


dmitriid.comGitHubLinkedIn
Re[60]: Haskell нужен! (в Standard Chartered Bank)
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.02.15 21:33
Оценка: +1
Здравствуйте, jazzer, Вы писали:


J>Отличается тем, что проверки допустимых операций (вызов недопустимой операции — ошибка программиста) происходят во время компиляции.

Ну конечно же нет.
J>Таким образом, недопустимый код просто не компилируется и в продакшен не попадает физически.
J>А у тебя проверки допустимых операций (вызов недопустимой операции — ошибка программиста) происходят во время выполнения (в продакшене, да).
Простите, но у вас — тоже. Вот у вас при загрузке ордера для изменения amount оказалось, что флаг hasRisk установлен.
Что произойдёт в вашем коде?

J>А типы, вообще-то, не о том, чтоб улучшить поведение системы.

J>Корректно работающая система будет работать корректно независимо от того, написана она на на статической типизации или на рукопашном ассемблере по живой памяти.
J>Они о том, чтоб исключить ошибки при ее написании.
Это всё понятно. Осталось воплотить хоть что-то из громких лозунгов в жизнь.

J>А юзеру покажем баннер: "Извините, у нас тут произошло исключение, похоже, программер накосячил и позвал не ту функцию, мы его высечем, баг пофиксим, зарелизим, через недельку приходите и попробуйте снова".

А вы что покажете юзеру? Ну вот у вас там после загрузки из базы "обычного Order, безо всяких свойств" проверили наличие флагов — оказазось, упс, отправлен уже этот ордер. Что делать?

J>Помогло, так как теперь компилятор следит, чтоб ты не вызвал то, что нельзя. А не ждал исключения в продакшене.

А по-моему мы просто удвоили количество строк кода, которые по-прежнему выбрасывают исключение.
J>>>ЗЫ Серьезно, складывается впечатление, что ты читаешь мои ответы через раз и по диагонали. Очень неприятно.
S>>А у меня наоборот — складывается впечатление, что ты отвечаешь не на те вопросы, которые я задаю.

J>он о том, зачем вообще нужна статическая типизация.

Нет. Вопрос как раз в этом — что вместо исключений предлагает нам статическая типизация. Пока что ответа как не было, так и нету.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[65]: Haskell нужен! (в Standard Chartered Bank)
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.02.15 21:42
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Блин. Чем дальше, тем любопытсвеннее © Чем дальше, тем более идиотские странные условия должны выполниться, чтобы мы наконец-то увидели всю мощь и красоту типов

Не, я нутром чую, что должен быть какой-то способ получить бенефиты. Но нащупать этот способ я пока до конца не могу.
В том смысле, что ведь и так в ассемблере никаких типов нету — тем не менее, компилятор таки следит за тем, чтобы "обращение к ячейкам памяти" не реинтерпретировало флоат как интегер.
Значит, по идее, можно родить какой-то такой язык описания workflow ордеров, при котором нам компилятор (или верификатор) статически скажет "у вас есть незаконный переход, сделайте с этим что-нибудь". И, грубо говоря, мы будем вынуждены в список отображения ордеров для модификации добавить фильтр вроде isShipped == false, или навесить валидатор на поле ввода размера пени, или ещё что там положено делать. Потому что если в контракте бизнес-операции сказано "не более 5%", то обеспечивать это надо предварительными проверками там, где они уместны. Т.е. ты должен будешь компилятору доказать, что у тебя все варианты покрыты.
А то, что в процессе этого workflow между отдельными шагами ордера персистятся в базу, или что между GUI и бэк-ендом ездит нетипизированный JSON, должно влиять не более, чем то, что в память пишутся нетипизированные байты (а в некоторых средах они ещё и читаться могут совсем другим процессом — и всё равно type safety на месте).

Должно, но вот как именно — я пока не вкуриваю
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[61]: Haskell нужен! (в Standard Chartered Bank)
От: jazzer Россия Skype: enerjazzer
Дата: 27.02.15 01:05
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

J>>Отличается тем, что проверки допустимых операций (вызов недопустимой операции — ошибка программиста) происходят во время компиляции.

S>Ну конечно же нет.

Ну конечно же да.

Компилятор в типизированных языках занимается ровно этим — не дает вызывать недопустимые операции. Как ты там сказал: "компилятор таки следит за тем, чтобы "обращение к ячейкам памяти" не реинтерпретировало флоат как интегер". Так вот он следит ровно потому, что есть типы флоат и интегер, и он проверяет соответствие операций типам и дает по рукам, если операция несовместима с типом. А если ячейка памяти никаким типом не помечена, то компилятор, очевидно, не сможет проверить ровно ничего. В асме ты говоришь: загрузи данные из этого адреса в целочисленный регистр, а из того — в плавучий. И компилятор асма все это делает, как ты написал, и ничего проверить не может: адрес — это просто набор цифр. Ты можешь тупо поменять адреса местами, и компилятор не почешется — для него все адреса на одно лицо, если нет типов.

J>>Таким образом, недопустимый код просто не компилируется и в продакшен не попадает физически.

J>>А у тебя проверки допустимых операций (вызов недопустимой операции — ошибка программиста) происходят во время выполнения (в продакшене, да).
S>Простите, но у вас — тоже. Вот у вас при загрузке ордера для изменения amount оказалось, что флаг hasRisk установлен.
S>Что произойдёт в вашем коде?

В моем коде для него будет невозможно вызвать increase_amount.
В твоем — возможно все, потому что все отдано на откуп исключениям.

J>>А типы, вообще-то, не о том, чтоб улучшить поведение системы.

J>>Корректно работающая система будет работать корректно независимо от того, написана она на на статической типизации или на рукопашном ассемблере по живой памяти.
J>>Они о том, чтоб исключить ошибки при ее написании.
S>Это всё понятно. Осталось воплотить хоть что-то из громких лозунгов в жизнь.

Второе предложение противоречит первому.
Особенно в свете откровений типа "ведь и так в ассемблере никаких типов нету — тем не менее, компилятор таки следит за тем, чтобы "обращение к ячейкам памяти" не реинтерпретировало флоат как интегер"

S>А вы что покажете юзеру? Ну вот у вас там после загрузки из базы "обычного Order, безо всяких свойств" проверили наличие флагов — оказазось, упс, отправлен уже этот ордер. Что делать?


Покажем "Мы тут проверили ордер, он уже отправлен".
А в твоем случае "Мы тут проверили ордер, он уже отправлен, но #$%#$-программер все равно с какого-то бодуна позвал increase_amount, сорри, мы его обязательно высечем".

J>>он о том, зачем вообще нужна статическая типизация.

S>Нет. Вопрос как раз в этом — что вместо исключений предлагает нам статическая типизация. Пока что ответа как не было, так и нету.

Не передергивай. Статическая типизация предлагается не вместо исключений вообще, а вместо исключений, отлавливающих ошибки программиста. "Нормальные" исключения (типа "файл с указанным именем не найден") никуда не делись и их никто менять на статическую типизацию не предлагает.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[66]: Haskell нужен! (в Standard Chartered Bank)
От: jazzer Россия Skype: enerjazzer
Дата: 27.02.15 01:18
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>В том смысле, что ведь и так в ассемблере никаких типов нету — тем не менее, компилятор таки следит за тем, чтобы "обращение к ячейкам памяти" не реинтерпретировало флоат как интегер.


жжешь

S>Значит, по идее, можно родить какой-то такой язык описания workflow ордеров, при котором нам компилятор (или верификатор) статически скажет "у вас есть незаконный переход, сделайте с этим что-нибудь". И, грубо говоря, мы будем вынуждены в список отображения ордеров для модификации добавить фильтр вроде isShipped == false, или навесить валидатор на поле ввода размера пени, или ещё что там положено делать. Потому что если в контракте бизнес-операции сказано "не более 5%", то обеспечивать это надо предварительными проверками там, где они уместны. Т.е. ты должен будешь компилятору доказать, что у тебя все варианты покрыты.


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

S>А то, что в процессе этого workflow между отдельными шагами ордера персистятся в базу, или что между GUI и бэк-ендом ездит нетипизированный JSON, должно влиять не более, чем то, что в память пишутся нетипизированные байты (а в некоторых средах они ещё и читаться могут совсем другим процессом — и всё равно type safety на месте).


S>Должно, но вот как именно — я пока не вкуриваю


Я же показал на примере. Вот мы в одном месте провели долгую проверку риска для ордера, по результатам взвели соответствуюший флажок в ордере, что проверка проведена и результат такой-то, заперсистили ордер в БД (в нетипизированный JSON, если угодно).
На следующий день (или на другом хосте, если это JSON по сети) мы достаем ордер (уже с обновленным флажком) из БД и ограничиваемся просто проверкой этого флажка, чтобы определить типизированное свойство HasRisk — и только после такой проверки компилятор разрешит тебе позвать функцию, статически требующую HasRisk.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[62]: Haskell нужен! (в Standard Chartered Bank)
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.02.15 05:36
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Ну конечно же да.

Пруф? Код — в студию. Бла-бла — не надо, я его сам прекрасно могу написать.
S>>Простите, но у вас — тоже. Вот у вас при загрузке ордера для изменения amount оказалось, что флаг hasRisk установлен.
S>>Что произойдёт в вашем коде?
J>В моем коде для него будет невозможно вызвать increase_amount.
Ну и что? increase_amount вызывается ровно в одном месте — я показал вам код.
J>В твоем — возможно все, потому что все отдано на откуп исключениям.
Мало ли что "возможно". Я-то говорю о том, что есть.


J>Покажем "Мы тут проверили ордер, он уже отправлен".

J>А в твоем случае "Мы тут проверили ордер, он уже отправлен, но #$%#$-программер все равно с какого-то бодуна позвал increase_amount, сорри, мы его обязательно высечем".
Откуда такие фантазии? В обоих случаях показываем один и тот же текст, вылетает одно и то же исключение. Т.е., что и требовалось доказать — вы написали в два раза больше кода (не считая бойлерплейта на поддержку типов — только прикладной код), чтобы получить систему с тем же поведением, что и раньше. И ровно с той же надёжностью.

J>Не передергивай. Статическая типизация предлагается не вместо исключений вообще, а вместо исключений, отлавливающих ошибки программиста. "Нормальные" исключения (типа "файл с указанным именем не найден") никуда не делись и их никто менять на статическую типизацию не предлагает.

Мы говорим не про исключения вообще, а про конкретную задачу процессинга ордеров.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[67]: Haskell нужен! (в Standard Chartered Bank)
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.02.15 05:39
Оценка:
Здравствуйте, jazzer, Вы писали:

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

Осталось показать практический пример.


J>Я же показал на примере. Вот мы в одном месте провели долгую проверку риска для ордера, по результатам взвели соответствуюший флажок в ордере, что проверка проведена и результат такой-то, заперсистили ордер в БД (в нетипизированный JSON, если угодно).

J>На следующий день (или на другом хосте, если это JSON по сети) мы достаем ордер (уже с обновленным флажком) из БД и ограничиваемся просто проверкой этого флажка, чтобы определить типизированное свойство HasRisk — и только после такой проверки компилятор разрешит тебе позвать функцию, статически требующую HasRisk.
Да ничего вы не показали!!!!! Вы всего лишь перенесли проверку изнутри функции наружу — а программа как падала, так и продолжает падать.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[67]: Haskell нужен! (в Standard Chartered Bank)
От: AlexRK  
Дата: 27.02.15 07:02
Оценка: +1
Здравствуйте, Mamut, Вы писали:

M>Вот есть код, пусть даже гипотетический. Есть вопрос по коду и/или работе с кодом. Мне в ответ говорят «нет, тут бессмысленно это». Спрашиваю, «в чем бессмысленность? в чем принципиальное различие от ситуации X?». «принципиальное различие очевидно — в случае с типами программист может возложить на компилятор дополнительные проверки». И так — по кругу.


Без типов:
int BadIncrease(object number)
{
  return ((int)number + 1);
}

Console.WriteLine(BadIncrease(33));  // выводит 33
Console.WriteLine(BadIncrease("qwerty"));  // ошибка в рантайме


С типами:
int GoodIncrease(int number)
{
  return (number + 1);
}

Console.WriteLine(GoodIncrease(33));  // выводит 33
Console.WriteLine(GoodIncrease("qwerty"));  // ошибка времени компиляции


Зачем нам типы, давайте сунем в функцию ИФ и отличий не будет:
int MamutFunction1(object number)
{
  if (number is int)
    BadIncrease(number);
}

Console.WriteLine(MamutFunction1(33));  // выводит 33
Console.WriteLine(MamutFunction1("qwerty"));  // все ОК, просто значение не печатается


Но вот беда, в другом месте мы забыли поставить этот ИФ и компилятор нам ничего не сказал:
void MamutFunction2()
{
  // ... прорва кода...

  object number = RetrieveValueFromConfig();

  // ... прорва кода...

  BadIncrease(number);  // БУМ

  // ... прорва кода...
}



Теперь преимущество видно? В случае с GoodIncrease мы физически не можем передать невалидный аргумент. Да, мы можем ошибиться в заголовке или теле функции GoodIncrease, но эта ошибка будет ровно в одном месте.
Вы скажете: "но это же просто статическая типизация, это совсем другое!". Нет, это абсолютно то же самое.
Может быть, такой пример будет нагляднее.
Re[68]: Haskell нужен! (в Standard Chartered Bank)
От: jazzer Россия Skype: enerjazzer
Дата: 27.02.15 07:14
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, jazzer, Вы писали:


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

S>Осталось показать практический пример.

Я же показал, чем тебя не устраивает try_to_change_amount?

J>>Я же показал на примере. Вот мы в одном месте провели долгую проверку риска для ордера, по результатам взвели соответствуюший флажок в ордере, что проверка проведена и результат такой-то, заперсистили ордер в БД (в нетипизированный JSON, если угодно).

J>>На следующий день (или на другом хосте, если это JSON по сети) мы достаем ордер (уже с обновленным флажком) из БД и ограничиваемся просто проверкой этого флажка, чтобы определить типизированное свойство HasRisk — и только после такой проверки компилятор разрешит тебе позвать функцию, статически требующую HasRisk.
S>Да ничего вы не показали!!!!! Вы всего лишь перенесли проверку изнутри функции наружу — а программа как падала, так и продолжает падать.

Где она падает, сорри? У меня такое чувство, что мы говорим о разных вещах.
И проверку чего? Проверку данных или проверку кода на предмет неправильных вызовов? У тебя и то и другое в общей куче, у меня только первое, потому что второе невозможно.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[63]: Haskell нужен! (в Standard Chartered Bank)
От: AlexRK  
Дата: 27.02.15 07:21
Оценка:
Здравствуйте, Sinclair, Вы писали:

J>>Ну конечно же да.

S>Пруф? Код — в студию. Бла-бла — не надо, я его сам прекрасно могу написать.
S>Мало ли что "возможно". Я-то говорю о том, что есть.

А что в коде jazzer'а непонятно-то? Даже я понял.

J>>Покажем "Мы тут проверили ордер, он уже отправлен".

J>>А в твоем случае "Мы тут проверили ордер, он уже отправлен, но #$%#$-программер все равно с какого-то бодуна позвал increase_amount, сорри, мы его обязательно высечем".
S>Откуда такие фантазии? В обоих случаях показываем один и тот же текст, вылетает одно и то же исключение. Т.е., что и требовалось доказать — вы написали в два раза больше кода (не считая бойлерплейта на поддержку типов — только прикладной код), чтобы получить систему с тем же поведением, что и раньше. И ровно с той же надёжностью.

Э... какие фантазии? Исключения там не вылетает, проверок в рантайме нет. Поведение и надежность двух вариантов совершенно разные.
Re[63]: Haskell нужен! (в Standard Chartered Bank)
От: jazzer Россия Skype: enerjazzer
Дата: 27.02.15 07:59
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, jazzer, Вы писали:


J>>Ну конечно же да.

S>Пруф? Код — в студию. Бла-бла — не надо, я его сам прекрасно могу написать.
S>>>Простите, но у вас — тоже. Вот у вас при загрузке ордера для изменения amount оказалось, что флаг hasRisk установлен.
S>>>Что произойдёт в вашем коде?
J>>В моем коде для него будет невозможно вызвать increase_amount.
S>Ну и что? increase_amount вызывается ровно в одном месте — я показал вам код.

В твоем случае increase_amount можно вызвать (в смысле, программист может неосторожным/злонамеренным движением вкопипастить вызов) откуда угодно, из любого кода, из любой ветки, для любого ордера в любом состоянии.
В моем — только в одном месте, только для ордера, которому разрешено поднимать amount. Все остальные места вызовут ошибку компиляции.
Собственно, ради этого все и делается.
У тебя ошибка программиста — исключение в рантайме, если не отловилось тестами — ушло в продакшен.
У меня ошибка программиста — ошибка компиляции, в продакшен уйти не может в принципе.

J>>В твоем — возможно все, потому что все отдано на откуп исключениям.

S>Мало ли что "возможно". Я-то говорю о том, что есть.

Что есть? есть _уже_ корректно работающая система? так ей ничего не надо уже, она уже написана и уже работает, типы ей никак не помогут и не помешают. А вот при внесении изменений типы могу помочь не допустить ошибок при кодировании. Именно потому, что increase_amount можно вызвать только в одном месте.

J>>Покажем "Мы тут проверили ордер, он уже отправлен".

J>>А в твоем случае "Мы тут проверили ордер, он уже отправлен, но #$%#$-программер все равно с какого-то бодуна позвал increase_amount, сорри, мы его обязательно высечем".
S>Откуда такие фантазии? В обоих случаях показываем один и тот же текст, вылетает одно и то же исключение. Т.е., что и требовалось доказать — вы написали в два раза больше кода (не считая бойлерплейта на поддержку типов — только прикладной код), чтобы получить систему с тем же поведением, что и раньше. И ровно с той же надёжностью.

Надежностью чего?
Если что — типы не о надежности работы кода (типа код не валится на неправильных данных — потому что это вопросы верификации данных), а о надежности процесса разработки (уменьшения вероятности ошибок кодирования).
Есть сомнения в том, что программирование с int и float более безопасно в плане ошибок кодирования, чем программирование по нетипизированным адресам?
Есть сомнения, что программирование с нормальными типами в интерфейсах (f(Class1, Class2)->Class3) более безопасно в плане ошибок кодирования, чем программирование в терминах общего класса Object (f(Object, Object)->Object)?
Если нет (ведь нет же, я надеюсь?), то почему есть тут?

J>>Не передергивай. Статическая типизация предлагается не вместо исключений вообще, а вместо исключений, отлавливающих ошибки программиста. "Нормальные" исключения (типа "файл с указанным именем не найден") никуда не делись и их никто менять на статическую типизацию не предлагает.

S>Мы говорим не про исключения вообще, а про конкретную задачу процессинга ордеров.

Где в твоей конкретной задаче место ошибкам программиста? Ответ — везде, потому что отлов оных происходит в рантайме, а не на этапе компиляции.

На всякий случай еще раз повторю главное, потому что ты валишь все в кучу — и обработку данных, и обработку ошибок программиста, и непринужденно перескакиваешь с одного на другое.
Типизация позволяет сделать процесс программирования более безопасным, предохраняя программиста от написания неправильного кода (думай про int/float вместо void*, или Class1/2/3 вместо Object, если Java тебе ближе). Всё. Пожалуйста, отталкивайся от этого, не вали все в кучу.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[64]: Haskell нужен! (в Standard Chartered Bank)
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.02.15 10:35
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>А что в коде jazzer'а непонятно-то? Даже я понял.

Я все вопросы задал. В ответ — опять букварные истины и булшит, а также "смотри в другой пример, там всё есть".

ARK>Э... какие фантазии? Исключения там не вылетает, проверок в рантайме нет. Поведение и надежность двух вариантов совершенно разные.

"Там" — это где? Код про Load jazzer так и не показал. Единственный код, где есть Load — мой, и в нём рантайм проверки присутствуют независимо от наличия типизации.
Если вам понятна идея jazzer, то, наверное, легко будет подправить мой код так, чтобы в нём исчезли рантайм проверки, или написать новый код LoadOrder.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[69]: Haskell нужен! (в Standard Chartered Bank)
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.02.15 10:45
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Я же показал, чем тебя не устраивает try_to_change_amount?

Вы что, шутите?
Ок, давайте внимательно посмотрим на ваш try_to_change_amount:
void try_to_change_amount(Order& o)
{
  PROP_IF(o, has_risk(o), HasRisk) { // что это мы тут имеем? А! Это же... РАНТАЙМ ПРОВЕРКА!!! Которых у вас якобы нету!
    // а тут??? Мы что, тупо проигнорировали команду - и типа делаем вид, что всё нормально??? 
    // на самом деле тут, конечно же, будет throw - потому что ничего больше сделать нельзя.
  }
  PROP_ELSE(o) {
    increase_amount(o, 2.71);
  };
}

J>Где она падает, сорри? У меня такое чувство, что мы говорим о разных вещах.
См. код выше. Вы ловко замели проблему "попытка увеличить amount для рискового ордера" под ковёр, ничего не скажешь. Просто сделаем вид, что такой попытки не было.

Вашему двухслойному коду вполне эквивалентен вот такой:
increase_amount(Order& o, Money amt)
{
  if(o.HasRisk)
  {  // doing nothing 
  }
  else
  {
    o.Amount += amt;
  }
}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[68]: Haskell нужен! (в Standard Chartered Bank)
От: Mamut Швеция http://dmitriid.com
Дата: 27.02.15 12:27
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, Mamut, Вы писали:


M>>Вот есть код, пусть даже гипотетический. Есть вопрос по коду и/или работе с кодом. Мне в ответ говорят «нет, тут бессмысленно это». Спрашиваю, «в чем бессмысленность? в чем принципиальное различие от ситуации X?». «принципиальное различие очевидно — в случае с типами программист может возложить на компилятор дополнительные проверки». И так — по кругу.


ARK>Без типов:

ARK>С типами:

Ну, как всегда, «hello, world» во все поля. И опять же ноль ответов на вопрос: вот мы перенесли все эти «толпа кода» в одну функцию. Согласно Евгению, «все это не имеет смысла».

ARK>Но вот беда, в другом месте мы забыли поставить этот ИФ и компилятор нам ничего не сказал:

ARK>Теперь преимущество видно? В случае с GoodIncrease мы физически не можем передать невалидный аргумент. Да, мы можем ошибиться в заголовке или теле функции GoodIncrease, но эта ошибка будет ровно в одном месте.
ARK>Вы скажете: "но это же просто статическая типизация, это совсем другое!". Нет, это абсолютно то же самое.
ARK>Может быть, такой пример будет нагляднее.

Только таких «примеров» у нас появляется хорошо, если два раза в год. И, не устану повторять: много сказок и удивительных историй
Автор: Mamut
Дата: 07.02.15
про типы, а на практике все упирается в простейшие «hello, world»ы и «как бы нам не сложить апельсины с огурцами»


dmitriid.comGitHubLinkedIn
Re[70]: Haskell нужен! (в Standard Chartered Bank)
От: AlexRK  
Дата: 27.02.15 12:29
Оценка:
Здравствуйте, Sinclair, Вы писали:

void try_to_change_amount(Order& o)
{
  PROP_IF(o, has_risk(o), HasRisk) { // что это мы тут имеем? А! Это же... РАНТАЙМ ПРОВЕРКА!!! Которых у вас якобы нету!
    // а тут??? Мы что, тупо проигнорировали команду - и типа делаем вид, что всё нормально??? 
    // на самом деле тут, конечно же, будет throw - потому что ничего больше сделать нельзя.

    // на самом деле тут НЕЛЬЗЯ вызвать increase_amount (компилятор запрещает) и никакого throw не будет
  }
  PROP_ELSE(o) {
    increase_amount(o, 2.71);
  };
}


S>Вашему двухслойному коду вполне эквивалентен вот такой:

increase_amount(Order& o, Money amt)
{
  if(o.HasRisk)
  {  // doing nothing 

     // а вот здесь, в отличие от предыдущего примера, нам компилятор не мешает делать что угодно, и будет throw
  }
  else
  {
    o.Amount += amt;
  }
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.