Re[18]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 10.02.15 21:53
Оценка:
M>>Ага. При обновлении кода клиента. Ну вот мы обновили код клиента в насквозь динамическом Эрланге, и все заработало на ура.

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


Ни в одном. Ты просто не способен понимать, что твои оппоненты пишут.

WH>Если бы схема проверялась статически, то таких ошибок бы не было.


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

Более того. Вот это полностью статически типизированная, абсолютно правильная с точки зрения типов реализация:
to_json :: Object -> string
to_json(Object) ->
   "выплевываем правильно сформированный JSON."


dmitriid.comGitHubLinkedIn
Re[19]: Про типы и логику
От: WolfHound  
Дата: 11.02.15 09:44
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Ни в одном. Ты просто не способен понимать, что твои оппоненты пишут.

В одном сообщении ты говоришь, что всё работает на ура.
А в другом говоришь, что сыпятся ошибки типов.

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

Зато есть проблемы с отправкой. Ибо клиенты не делают статических проверок типов по схеме при генерации JSON.

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

И кто тут не понимает, что ему говорят?
Если в схеме прописаны типы, то мы можем статически проверить код, который генерирует JSON.

M>Более того. Вот это полностью статически типизированная, абсолютно правильная с точки зрения типов реализация:

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

Охохо.

Давай сначала.

Ты утверждаешь, что статическая проверка проверит все и все и не позволит допустить ошибок при смене протокола: «Если бы протокол был статически типизирован и компилятор бил бы по рукам разработчиков, которые пытаются сделать что-то не так, то данного класса проблем бы не было.»

Причем ты моментально вводишь вводишь два условия:
— Нормальные люди не забывают проверять версию протокола при соединении.
При обновлении кода клиента компилятор будет бить по рукам везде.

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

Два примера, что я приводил в развернутом виде выглядят так:

Пример первый

Наш код вызывает сторонний сервис через клиентскую библиотеку. Сторонний сервис написан на Java (!), клиентская библиотека — на Эрланге.

Клиентская библиотека — это, по сути, один API вызов, который принимает на вход объект X, который проверяется на валидность, и потом отсылается в сторонний сервис.

Пацаны из сервиса по какой-то причине подумали, что этим API-вызовом еще никто не пользуется и решили его улучшить (на самом деле) и заменить поле country_code с целого числа на ISO Alpha 2. И забыли обновить клиентскую библиотеку у нас.

С нашей стороны ничего не изменилось: передаваемый в API объект с точки зрения библиотеки был абсолютно валидным. Она формировала с ее точки зрения абсолютно валидный объект для передачи в сервис. Сервис падал с HTTP 500 и стектрейсом, включающим в себя что-то типа IllegalArgumentException.

Когда мы пришли к пацанам, реализующим сервис с вопросом «какого хрена», они слегка похватались за головы и быстренько выкатили для нас обновление своей библиотеки, которое добавляло конвертацию country_code:integer (который везде используется внутри нашей системы) в ISO Alpha 2 код (используемый сервисом). Код, вызывающий API этой библиотеки не надо было править нигде, от слова вообще. И наступило щастя.

— Каким образом помогла бы стат. типизация, учитывая, что разработчики этого сервиса оказались «ненормальными», и внесли ломающие изменения в протокол без изменения версии и обновления клиентского кода? Да никак, от слова вообще.
— Каким образом помогла бы стат. типизация нашему коду, если клиентская библиотека не обновлена? Да никак, от слова вообще. Да, она бы помогла при условии, если клиентская библиотека обновлена и ее интерфейс поменялся (и такие случаи бывают, и я про это говорил, что тогда стат. типизация весьма желанна).

Пример второй

На этот раз сервис предоставляем мы. На насквозь динамически типизированном эрланге. Но мы оказались, во-первых, «нормальными разработчиками»©™. Любые ломающие обратную совместимость изменения вводятся обязательно с изменением версии. Минимум две предыдущие версии продолжают поддерживаться.

И IllegalArgumentException или что-либо подобное у нас невозможно вообще. Не из-за того, что язык динамически типизированный, а из-за того, что мы:
— проверяем версии протокола
— проверяем соотвествие присылаемых данных заявленной версии

В случае несоответствия данные даже до собственно бизнес-кода не доходят, а возвращается предназначенная для этого ошибка HTTP 400 Bad Request с указанием, где именно проблемы. Еще раз. Это не ошибка из-за того, что в рантайме вместо типа X пришел тип Y, у нас вылетело исключение и мы трепыхаемся. Код, требующий тип X даже не увидит аргумент типа Y, потому что это дело отловит валидатор по схеме на самых ранних подступах.

Так как у нас нет никакого контроля над клиентским кодом, то клиенты будут присылать все, что им в голову взбредет, потому что никто не защищен от «ненормальных разработчиков», кривых рук да и банальной реализации (абсолютно математически выверенной и статически типизированной, и скомпилированной) типа «отсылаем заголовок Content-Type одной версии, а тело запроса — другой».


dmitriid.comGitHubLinkedIn
Re[21]: Про типы и логику
От: WolfHound  
Дата: 11.02.15 14:39
Оценка: +1
Здравствуйте, Mamut, Вы писали:

M>Причем ты моментально вводишь вводишь два условия:

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

M>- При обновлении кода клиента компилятор будет бить по рукам везде.

Это и есть статическая типизация протокола.
Если этого нет, то нет и статической типизации.

M>Пример первый

Неадекватность разработчиков.
Инструментами не решается.

M>Пример второй


M>Так как у нас нет никакого контроля над клиентским кодом, то клиенты будут присылать все, что им в голову взбредет, потому что никто не защищен от «ненормальных разработчиков», кривых рук да и банальной реализации (абсолютно математически выверенной и статически типизированной, и скомпилированной) типа «отсылаем заголовок Content-Type одной версии, а тело запроса — другой».

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

Если бы да кабы, да...

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


dmitriid.comGitHubLinkedIn
Re[23]: Про типы и логику
От: WolfHound  
Дата: 11.02.15 15:23
Оценка:
Здравствуйте, Mamut, Вы писали:

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

Я говорю всего про два:
1)Программисты должны быть адекватны. Иначе в любом случае всё будет плохо.
2)Статическая типизация должна быть.
Жаловаться на то, что статическая типизация не работает, если её нет весьма странно.
Твой второй пример именно про случай, когда её нет.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[24]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 11.02.15 16:11
Оценка: -1
WH>Я говорю всего про два:
WH>1)Программисты должны быть адекватны. Иначе в любом случае всё будет плохо.
WH>2)Статическая типизация должна быть.

И в случае с распределенными сервисами: клиенты должны быть обновлены одновременно с сервером (возможно, подпункт первого условия).

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

to_json :: Object -> string


И не прикопаешься, все условия выполнены

WH> Жаловаться на то, что статическая типизация не работает, если её нет весьма странно.


В первом случае статическая типизация была, она сильно помогла?

WH> Твой второй пример именно про случай, когда её нет.


Я не вижу, каким образом это «случай, когда ее нет». Ах да, мы упираемся в неизвестные критерии «адекватности программистов», ага


dmitriid.comGitHubLinkedIn
Re[25]: Про типы и логику
От: WolfHound  
Дата: 11.02.15 16:36
Оценка:
Здравствуйте, Mamut, Вы писали:

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

В каком месте он адекватный?
Где происходит статическая проверка схемы?

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

M>В первом случае статическая типизация была, она сильно помогла?

В первом случае был близкий аналог
(B*)(void*)(new A())
Те типы были выкинуты.
Такое можно делать, только если есть железная гарантия что A == B.
Разработчики её не обеспечили. Ессно код сломался.

WH>> Твой второй пример именно про случай, когда её нет.

M>Я не вижу, каким образом это «случай, когда ее нет». Ах да, мы упираемся в неизвестные критерии «адекватности программистов», ага
Где происходит статическая проверка схемы?
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[14]: Про типы и логику
От: genre Россия  
Дата: 11.02.15 17:53
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>JSON динамически типизированный.

WH>Если бы протокол был статически типизирован

А это как вообще?
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[15]: Про типы и логику
От: WolfHound  
Дата: 11.02.15 18:03
Оценка:
Здравствуйте, genre, Вы писали:

WH>>JSON динамически типизированный.

WH>>Если бы протокол был статически типизирован
G>А это как вообще?
Примерно так: http://en.wikipedia.org/wiki/Interface_description_language
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[16]: Про типы и логику
От: genre Россия  
Дата: 12.02.15 09:18
Оценка: +1
Здравствуйте, WolfHound, Вы писали:

WH>>>JSON динамически типизированный.

WH>>>Если бы протокол был статически типизирован
G>>А это как вообще?
WH>Примерно так: http://en.wikipedia.org/wiki/Interface_description_language

И какое же отношение это имеет к статической типизации(там json кстати в списке есть, см выше)? Ты говоришь про статическую типизацию реализации протокола, но чем она поможет если клиент на с++, а сервер на, например, java, непонятно
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[26]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 12.02.15 21:21
Оценка:
M>>В первом случае статическая типизация была, она сильно помогла?
WH>В первом случае был близкий аналог
WH>(B*)(void*)(new A())
WH>Те типы были выкинуты.

С какого перепугу они были выкинуты? Ты придумываешь себе какие-то фантазии и упорно с ними борешься

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

WH>>> Твой второй пример именно про случай, когда её нет.

M>>Я не вижу, каким образом это «случай, когда ее нет». Ах да, мы упираемся в неизвестные критерии «адекватности программистов», ага
WH>Где происходит статическая проверка схемы?

Происходит проверка где?


ЗЫ.

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

— программисты должны написать абсолютно корректный генератор кода по схеме
— программисты должны привязать этот абсолютно корректный генератор кода по схеме к своей абсолютно корректной схеме данных
— это должно произойти как на сервере, так и на клиенте
— любые изменения, проводимые на сервере, должны моментально изменяться и обновляться на клиенте

И только в этих тепличных условиях «компилятор бил бы по рукам разработчиков, которые пытаются сделать что-то не так, и данного класса проблем бы не было».

Но в таких тепличных условиях не будет особых проблем с какой-либо типизацией


dmitriid.comGitHubLinkedIn
Re: Про типы и логику
От: GreenTea  
Дата: 25.02.15 12:32
Оценка: 21 (1)
Здравствуйте, Mamut, Вы писали:

M>Выношу из соседнего обсуждения
Автор: Mamut
Дата: 02.02.15
, так как там много флейма и отсутсвие конструктива.


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


Всю ветку не читал. Лично для меня напрашивается решение с применением rule engine типа drools.
Каждое правило (дальше рул) проверяет одну ошибку. Из рула можно вызвать внешний код которые будет лезть куда-то на внешний сервис, если нужно.
На вход подается объект заказа и новое значение суммы.
Плюсы такого подхода:
+ декларативное определение рулов в виде: список условий -> результат
+ по умолчанию ситнтаксис выражений похож на java, но есть возможность для рулов задать свой DSL, так что он будет понятен человеку из бизнеса, и далекого от IT. Хотя это не всегда может быть просто.
+ возможность подключить внешний веб редактор для рулов и менять их хоть даже на лету.
Минусы:
— поморочиться придется чуть больше чем написать всю логику в коде.

Каждый из рулов можно покрыть юнит тестами.
Отредактировано 25.02.2015 12:42 GreenTea . Предыдущая версия . Еще …
Отредактировано 25.02.2015 12:33 GreenTea . Предыдущая версия .
Re: Про типы и логику
От: alex_public  
Дата: 03.03.15 10:27
Оценка: 21 (1)
Здравствуйте, Mamut, Вы писали:

Эх, что-то я со своим новым проектом так ушёл в дела, что совсем забыл про rsdn. А тут такие забавные вещи обсуждаются... Ну попробую влить новую кровь в затухающую дискуссию. )))

Значит тебе хочется увидеть пример работы статической типизации в бизнес-логике. Такое встречается не так уж часто и на это есть вполне очевидная причина — подобные проверки в большинстве случаев будут идти не вместо рантайм проверок, а в дополнение к ним (проверяя условия на другом логическом уровне), так что получается увеличение кода без казалось бы существенного увеличения надёжности. Ну а программистская лень общеизвестна... ))) Однако для простенького форумного случая можно и написать демонстрацию. Причём твой "Шаг1" отлично для этого подходит (на следующие шаги естественно это легко экстраполируется, но уже лень). Вот полный компилируемый код примера:

#include <stdexcept>
#include <iostream>
using namespace std;

enum class OrderType {Unknown, OnlyDecrease, Constant};
template<OrderType Type>
struct Order{
    const int amount;
    const bool sent;
    const bool risk;
};

template<OrderType Type> auto RiskOrder(const Order<Type>& o) {return Order<OrderType::Constant>{o.amount, o.sent, true};}
template<OrderType Type> auto SendOrder(const Order<Type>& o) {return Order<Type==OrderType::Unknown?OrderType::OnlyDecrease:Type>{o.amount, true, o.risk};}
template<OrderType Type> auto Increase(const Order<Type>& o, int v)
{
    static_assert(Type==OrderType::Unknown, "You can not increase this order");
    if(o.sent||o.risk) throw invalid_argument("You can not increase this order");
    else return Order<Type>{o.amount+v, o.sent, o.risk};
}
template<OrderType Type> auto Decrease(const Order<Type>& o, int v)
{
    static_assert(Type!=OrderType::Constant, "You can not decrease this order");
    if(Type==OrderType::Unknown&&o.risk) throw invalid_argument("You can not decrease this order");
    else return Order<Type>{o.amount-v, o.sent, o.risk};
}
template<OrderType Type, typename F> void ProcessOrder(const Order<Type>& o, F f)
{
    cout<<"Process order:\t"<<o.amount<<'\t'<<o.sent<<'\t'<<o.risk<<endl;
    try{
        auto r=f(o);
        cout<<"Result order:\t"<<r.amount<<'\t'<<r.sent<<'\t'<<r.risk<<endl;
    }catch(const exception& e) {cout<<e.what()<<endl;}
}

int main()
{
    ProcessOrder(Order<OrderType::Unknown>{100, false, false}, [](auto o){//нормально отрабатывает
        auto o1=Increase(o, 10);
        auto o2=SendOrder(o1);
        return Decrease(o2, 20);
    });
    ProcessOrder(Order<OrderType::Unknown>{100, true, false}, [](auto o){//вылетает с исключением в рантайме - плохой входящий ордер для такого алгоритма
        auto o1=Increase(o, 10);
        auto o2=SendOrder(o1);
        return Decrease(o2, 20);
    });
    ProcessOrder(Order<OrderType::Unknown>{100, false, false}, [](auto o){//некомпилируется - компилятор видит ошибку в бизнес логике алгоритма
        auto o1=Decrease(o, 20);
        auto o2=SendOrder(o1);
        return Increase(o2, 10);
    });
}


P.S. В случае использования только известных на момент компиляции (т.е. не загружаемых из БД, а скажем создаваемых в коде) order'ов, все рантайм проверки можно полностью выкинуть из кода и тогда данный подход соответственно превращается из "необязательной дополнительной фичи" в наиболее оптимальное решение со всех точек зрения.
Re[2]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 04.03.15 04:33
Оценка:
Здравствуйте, alex_public, Вы писали:

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


_>Эх, что-то я со своим новым проектом так ушёл в дела, что совсем забыл про rsdn. А тут такие забавные вещи обсуждаются... Ну попробую влить новую кровь в затухающую дискуссию. )))


_>Причём твой "Шаг1" отлично для этого подходит (на следующие шаги естественно это легко экстраполируется, но уже лень).



Ну, начинается Вот не вижу я, чтобы он «естественно легко экстраполируется»


Ну а по коду видно, что проверок стало в два раза больше, а простор для ошибок — точно такой же, как и без них

_>P.S. В случае использования только известных на момент компиляции (т.е. не загружаемых из БД, а скажем создаваемых в коде) order'ов, все рантайм проверки можно полностью выкинуть из кода и тогда данный подход соответственно превращается из "необязательной дополнительной фичи" в наиболее оптимальное решение со всех точек зрения.


За пределами теоретических изысканий таких Order'ов в природе не существует


dmitriid.comGitHubLinkedIn
Re[3]: Про типы и логику
От: alex_public  
Дата: 04.03.15 15:39
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Ну, начинается Вот не вижу я, чтобы он «естественно легко экстраполируется»


Ну смотри, у тебя же классический конечный автомат из 3+1 состояний (3 реальных и 1 (Unknown) нужное для статической типизации), которые я все уже описал в коде. Ну точнее я не ввёл формально состояние Increase&Decrease, но только потому что там не было функции переводящей в него (мы же не можем сделать Unsend ордера). Соответственно какие бы сложные условия ты не добавлял на своих следующих шагах, это просто приведёт к усложнению кода перехода между состояними (грубо говоря твой "код в лоб" будет переноситься в некую сложную функцию типа CanDecrease, вызываемую в точке if(Type==OrderType::Unknown&&CanDecrease()) throw ... функции Decrease).

Ты действительно видишь здесь что-то сложное? )

M>Ну а по коду видно, что проверок стало в два раза больше, а простор для ошибок — точно такой же, как и без них


Ну для начала статическая типизация не устраняет сами ошибки, а переводит их возникновение из времени исполнения во время компиляции. Что мы и видим в моём примере. Естественно переводятся во время компиляции только те проверки, для которых достаточно знаний на момент компиляции. Если в коде используется очень много рантайм данных, то никакая статическая типизация не позволит вынести много проверок во время компиляции. Но какие-то выносятся и в таком случае, что и демонстрирует мой пример. А вот если рантайм данных не много (ну в смысле не самих данных, а грубо говоря типов определяемых динамически), то подобный подход становится суперэффективным. С экстремум в виде 100% гарантии безошибочности кода при полном отсутствие динамически определяемых типов.

Что касается количества проверок... Ты про что, про размер исходника или про нагрузку процессора в рантайме? ) Если про первое, то да, действительно размер исходника возрастает. Но это цена за перевод ошибок из времени исполнения во время компиляции. Если же говорить о втором, то там как раз количество рантайм проверок снижается (думаю же для тебе не откровения, что весь код после "if(X&&", где X — это false времени компиляции, компилятор полностью выкидывает? Кстати, в том же D это значительно нагляднее выглядит, благодаря наличию static if, но результат тот же самый), так что этот самый "разросшийся" код по быстродействию эффективнее твоего варианта "в лоб".

_>>P.S. В случае использования только известных на момент компиляции (т.е. не загружаемых из БД, а скажем создаваемых в коде) order'ов, все рантайм проверки можно полностью выкинуть из кода и тогда данный подход соответственно превращается из "необязательной дополнительной фичи" в наиболее оптимальное решение со всех точек зрения.

M>За пределами теоретических изысканий таких Order'ов в природе не существует

Вообще то как раз существует и даже прямо в твоём случае. Например при создание нового ордера мы можем точно указать его тип и т.д. Проблема в том, что полностью уйти от рантайм данных в твоём случае нельзя и соответственно нельзя полностью убрать рантайм проверки. Но и частичный перевод ошибок во время компиляции тоже может быть полезен. )
Отредактировано 04.03.2015 16:00 alex_public (нафиг оффтопик)) . Предыдущая версия .
Re[4]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 04.03.15 16:12
Оценка: -1
M>>Ну, начинается Вот не вижу я, чтобы он «естественно легко экстраполируется»

_>грубо говоря твой "код в лоб" будет переноситься в некую сложную функцию типа CanDecrease, вызываемую в точке if(Type==OrderType::Unknown&&CanDecrease()) throw ... функции Decrease).


_>Ты действительно видишь здесь что-то сложное? )


Так. Мой код будет перерастать во что-то сложное, а твой не будет? Можно это продемонстрировать? Да, я лично не вижу, как это экстраполируется


M>>Ну а по коду видно, что проверок стало в два раза больше, а простор для ошибок — точно такой же, как и без них


_>Ну для начала статическая типизация не устраняет сами ошибки, а переводит их возникновение из времени исполнения во время компиляции. Что мы и видим в моём примере. Естественно переводятся во время компиляции только те проверки, для которых достаточно знаний на момент компиляции.


Ну, я имею в виду, что в твоем примере все равно все упирается в то, расставил ли кто-нибудь static_assert'ы по коду. Если по коду есть хотя бы минимальное тестирование (а логику проверять надо), то их полезность по сравнению с динамической типизацией падает экспоненциально. И как показывает твой пример, нам все равно надо отлавливать рантайм-ошибки в зависимости от того, как эти ассерты расставлены. В итоге ответсвенность за логику размыта и стало сложнее проследить, а не забыли ли мы что-либо и правильно ли мы реализовали логику.

_>Что касается количества проверок... Ты про что, про размер исходника или про нагрузку процессора в рантайме? )


Нет. Я имел в виду, что вижу по два if'а (грубо говоря) на каждую функцию

_>>>P.S. В случае использования только известных на момент компиляции (т.е. не загружаемых из БД, а скажем создаваемых в коде) order'ов, все рантайм проверки можно полностью выкинуть из кода и тогда данный подход соответственно превращается из "необязательной дополнительной фичи" в наиболее оптимальное решение со всех точек зрения.

M>>За пределами теоретических изысканий таких Order'ов в природе не существует

_>Вообще то как раз существует и даже прямо в твоём случае. Например при создание нового ордера мы можем точно указать его тип и т.д.


Теоретики такие теоретики. Новый заказ создается из 100% рантайм-данных. И, соотвественно, наделяется всеми свойствами исключительно в рантайме.

_>P.S. Да, а вообще вся эта ваша архитектура выглядит вообще очень сомнительно и криво. Т.к. по нормальному надо не отлавливать запрещённые пользователю действия и выводить сообщение об ошибке, а просто не позволять их пользователю инициировать. _>Т.е. должна быть функция типа CanIncrease(order), которая вызывается из интерфейса пользователя и соответственно ему не отображается никаких кнопок, которые могут инициировать Increase.


Боже, какие вы все теоретики. /o\ Кнопочки. В GUI. Не выводить. О чем вы все?

У меня может прийти 15 000 автоматических запросов на изменение суммы заказа. Просто потому что магазин так решил. Мы должны вернуть этому магазину внятные сообщения, что «нет, дядя, для таких-то и таких-то заказов это нельзя потому что
Автор: Mamut
Дата: 06.02.15
».

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


dmitriid.comGitHubLinkedIn
Re[5]: Про типы и логику
От: alex_public  
Дата: 04.03.15 16:51
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Так. Мой код будет перерастать во что-то сложное, а твой не будет? Можно это продемонстрировать? Да, я лично не вижу, как это экстраполируется


Ты не понял мою мысль. Вот смотри, у меня сейчас есть пример для простейшей бизнес-логики. Дальше, берём относительно сложный случай (твой шаг3 скажем) и берём твой сложный код "в лоб" для этого случая. Так вот нам понадобится просто вставить этот твой сложный код прямо в определённую точку моего простого примера. Понятная идея? ) Т.е. грубо говоря при усложнение задачи объём дополнительного кода (возникающего ради статического отлова ошибок) не будет возрастать (относительного моего примера).

M>Ну, я имею в виду, что в твоем примере все равно все упирается в то, расставил ли кто-нибудь static_assert'ы по коду. Если по коду есть хотя бы минимальное тестирование (а логику проверять надо), то их полезность по сравнению с динамической типизацией падает экспоненциально. И как показывает твой пример, нам все равно надо отлавливать рантайм-ошибки в зависимости от того, как эти ассерты расставлены. В итоге ответсвенность за логику размыта и стало сложнее проследить, а не забыли ли мы что-либо и правильно ли мы реализовали логику.


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

_>>Что касается количества проверок... Ты про что, про размер исходника или про нагрузку процессора в рантайме? )

M>Нет. Я имел в виду, что вижу по два if'а (грубо говоря) на каждую функцию

Ну в исполняемый файл в итоге попадает или один или ноль if'ов. А в исходнике да, разрастаемся... )))

_>>Вообще то как раз существует и даже прямо в твоём случае. Например при создание нового ордера мы можем точно указать его тип и т.д.

M>Теоретики такие теоретики. Новый заказ создается из 100% рантайм-данных. И, соотвественно, наделяется всеми свойствами исключительно в рантайме.

Ничего подобного. В коде ты легко можешь создать пустой экземпляр ордера (и у него уже не будет тип Unknown, а будет скажем IncreaseDecrease), а потом заполнить его своими рантайм данными с помощью тех же самых функций перевода состояния. И при этом будут автоматически производиться все проверки.
Re[6]: Про типы и логику
От: Mamut Швеция http://dmitriid.com
Дата: 04.03.15 18:21
Оценка:
M>>Так. Мой код будет перерастать во что-то сложное, а твой не будет? Можно это продемонстрировать? Да, я лично не вижу, как это экстраполируется

_>Ты не понял мою мысль.


Я ее понял

_>Вот смотри, у меня сейчас есть пример для простейшей бизнес-логики. Дальше, берём относительно сложный случай (твой шаг3 скажем) и берём твой сложный код "в лоб" для этого случая. Так вот нам понадобится просто вставить этот твой сложный код прямо в определённую точку моего простого примера. Понятная идея? ) Т.е. грубо говоря при усложнение задачи объём дополнительного кода (возникающего ради статического отлова ошибок) не будет возрастать (относительного моего примера).


Можно это увидеть на полноценном примере? Там всего-то несколько усложнений по сравнению с реальностью

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


_>Ты похоже тут уже пытаешься решить совсем другую задачу.


Да нет. Все ту же Я просто говорю, что твой пример показывает, что с точки зрения программиста все стало сложнее. Где мы проверяем условия статически? А где — в рантайме? Не маскирует ли стат. типизация необходимую проверку в рантайме? В нужном ли месте я поставил стат. типизацию, и правильно ли, что во втором твоем примере происходит рантайм проверка? С ростом количества условий это превратится в непонятный никому звиздец, имхо.

А как только для разруливания и проверки этого звиздеца мы вставляем тесты, как ценность стат. проверок начинает падать экспоненциально.

_>Максимум, что могут наши современные средства, это свести введение правил до действительно одной точки, с автоматическим расползанием их по всему коду. И как раз в таком статическая типизация очень помогает.


Не понял этой фразы и утверждения

_>>>Что касается количества проверок... Ты про что, про размер исходника или про нагрузку процессора в рантайме? )

M>>Нет. Я имел в виду, что вижу по два if'а (грубо говоря) на каждую функцию

_>Ну в исполняемый файл в итоге попадает или один или ноль if'ов. А в исходнике да, разрастаемся... )))


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

_>>>Вообще то как раз существует и даже прямо в твоём случае. Например при создание нового ордера мы можем точно указать его тип и т.д.

M>>Теоретики такие теоретики. Новый заказ создается из 100% рантайм-данных. И, соотвественно, наделяется всеми свойствами исключительно в рантайме.

_>Ничего подобного. В коде ты легко можешь создать пустой экземпляр ордера (и у него уже не будет тип Unknown, а будет скажем IncreaseDecrease), а потом заполнить его своими рантайм данными с помощью тех же самых функций перевода состояния. И при этом будут автоматически производиться все проверки.


Так. Я про это и говорю: данные приходят строго из рантайма. Про «функции перевода состояния» я слышу уже скоро месяц, как, но никто так и не осилил описать эти «функции состояния» до уровня полноценного примера

И вообще. Что значит «функции состояния»? У нас нет никаких «функций перехода состояния». Изменение суммы заказа может происходить через неделю после того, как заказ создан. При чем тут «функции состояния»? Перед тем, как изменить сумму заказа, заказ будет загружен из базы данных в любом из четырех (из примера) или полутора десятков (в реальности) состояний.

Тут рядом Sinclair недаром просил показать функцию load_order для примера jazzer'а


dmitriid.comGitHubLinkedIn
Re[7]: Про типы и логику
От: alex_public  
Дата: 04.03.15 19:22
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Можно это увидеть на полноценном примере? Там всего-то несколько усложнений по сравнению с реальностью


Да просто добавляешь свои обычные рантайм проверки в функции Decrease и Increase. Ничего касающегося статической типизации там больше не видно. К сожалению. ))) Потому как чем больше можно перевести в статику, тем лучше.

M>Да нет. Все ту же Я просто говорю, что твой пример показывает, что с точки зрения программиста все стало сложнее. Где мы проверяем условия статически? А где — в рантайме? Не маскирует ли стат. типизация необходимую проверку в рантайме? В нужном ли месте я поставил стат. типизацию, и правильно ли, что во втором твоем примере происходит рантайм проверка? С ростом количества условий это превратится в непонятный никому звиздец, имхо.


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

M>А как только для разруливания и проверки этого звиздеца мы вставляем тесты, как ценность стат. проверок начинает падать экспоненциально.


Ну у тестов имеются горы своих специфических проблем... )

_>>Максимум, что могут наши современные средства, это свести введение правил до действительно одной точки, с автоматическим расползанием их по всему коду. И как раз в таком статическая типизация очень помогает.

M>Не понял этой фразы и утверждения

Если у нас есть какие-то ограничения на бизнес-логику (например как в твоей задачке — "отправленное нельзя увеличивать"), то очевидно лучше чтобы сам код проверки был написан ровно в одной точке программы, вызываясь из всех нужных мест. Статическая типизация отлично подходит для таких стратегий. Более того, она может ещё проконтролировать, чтобы не было мест без вызова проверки. Хотя это естественно не единственный способ реализации.

_>>Ну в исполняемый файл в итоге попадает или один или ноль if'ов. А в исходнике да, разрастаемся... )))

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

В твоей задаче — конечно. А в других вполне бывает что всё наоборот.

M>Так. Я про это и говорю: данные приходят строго из рантайма. Про «функции перевода состояния» я слышу уже скоро месяц, как, но никто так и не осилил описать эти «функции состояния» до уровня полноценного примера


Ну вот прямо в моём примере видны эти функции. Например функция SendOrder переводит из состояния Unknown (ну и не заданного мною Increase&Decrease) в состояние OnlyDecrease.

M>И вообще. Что значит «функции состояния»? У нас нет никаких «функций перехода состояния». Изменение суммы заказа может происходить через неделю после того, как заказ создан. При чем тут «функции состояния»? Перед тем, как изменить сумму заказа, заказ будет загружен из базы данных в любом из четырех (из примера) или полутора десятков (в реальности) состояний.


И? ) Не пойму с чем ты споришь то? ) Я разве утверждал, что весь твой пример можно покрыть статикой? ) Естественно там останется куча рантайм проверок. Я просто поясняю, что статические тоже будут встречаться и не так редко, как ты думаешь. Но всё же наверное недостаточно часто, чтобы делать подобное в твоём случая. А вот в других задачах, где процент повыше, это уже явно имеет смысл.

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