Re[15]: Вот еще, или я, кажется, читать разучился
От: alex_public  
Дата: 23.02.13 04:01
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>В нормальной ситуации, когда конструктор не может установить нужные инварианты объекта, не может нормально создать объект — он кидает исключение.

EP>При таком подходе нету места "частично созданным" объектам, так как по правилам языка если из конструктора вылетает исключение, то нет возможности что-либо с ним сделать (не будем рассматривать патологические случаи ковыряния в raw bytes of dead object).

EP>Например, что ты будешь делать без исключений в следующем случае?:

EP>
EP>{
EP>    vector<int> v(16); // may fail on allocation
EP>    cout << v[0];
EP>}
EP>

EP>Приведи аналогичный код(клиентскую часть), но без использования исключений.

Ну так это как раз редкий пример оправданного применения исключений, т.к. в большинстве случаев при ошибке выделения памяти остаётся только корректно самоуничтожиться. ))) Но это у нас исключение из стандартной библиотеки, а не в нашем коде. Речь то шла о своих... )
Re[16]: Вот еще, или я, кажется, читать разучился
От: Evgeny.Panasyuk Россия  
Дата: 23.02.13 04:29
Оценка:
Здравствуйте, alex_public, Вы писали:

EP>>Например, что ты будешь делать без исключений в следующем случае?:

EP>>
EP>>{
EP>>    vector<int> v(16); // may fail on allocation
EP>>    cout << v[0];
EP>>}
EP>>

EP>>Приведи аналогичный код(клиентскую часть), но без использования исключений.
_>Ну так это как раз редкий пример оправданного применения исключений, т.к. в большинстве случаев при ошибке выделения памяти остаётся только корректно самоуничтожиться. )))

Редкий?
Выделение памяти в приложении, внутри структур данных — это редкость?

_>Но это у нас исключение из стандартной библиотеки, а не в нашем коде. Речь то шла о своих... )


struct MyStruct
{
    vector<int> v;
    // ...
    MyStruct()
        : v(16)
    {}
};
// ...
{
    MyStruct m;
}



или например:
class Percent
{
    double p;
public:
    explicit Percent(double p_)
        : p(p_)
    {
        if( (p > 100.0) || (p<0.0) )
            throw domain_error("Wrong Percent");
    }
    double value() const
    {
        return p;
    }
};
// ...
{
    Percent p(user_input_from_upper_layers);
}

Re[16]: Вот еще, или я, кажется, читать разучился
От: jazzer Россия Skype: enerjazzer
Дата: 23.02.13 07:50
Оценка: 11 (2) +1
Здравствуйте, alex_public, Вы писали:

_>Тогда действительно сомнительный код у них там. Что впрочем никак не влияет на нашу основную дискуссию. )


Не влияет? Тут народ прямиком забивает на обработку ошибок, и это называется — не влияет? Это как раз отличная демонстрация безопасности так называемой "обработки" ошибок через коды возврата.
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[17]: Вот еще, или я, кажется, читать разучился
От: alex_public  
Дата: 23.02.13 18:21
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Редкий?

EP>Выделение памяти в приложении, внутри структур данных — это редкость?

Редким является не выделения памяти, а ситуация когда оно даёт сбой. И из факта особенности этой ситуации следуют соответствующие выводы насчёт её обработки...
Re[17]: Вот еще, или я, кажется, читать разучился
От: alex_public  
Дата: 23.02.13 18:24
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Не влияет? Тут народ прямиком забивает на обработку ошибок, и это называется — не влияет? Это как раз отличная демонстрация безопасности так называемой "обработки" ошибок через коды возврата.


Ну так для правильности таких выводов надо всего лишь показать что вариант этого кода через исключения намного короче и удобнее...
Re[15]: Вот еще, или я, кажется, читать разучился
От: landerhigh Пират  
Дата: 23.02.13 19:18
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Например, что ты будешь делать без исключений в следующем случае?:

<skip>
EP>Приведи аналогичный код(клиентскую часть), но без использования исключений.

Меня больше интересует, как разработчики Tizen собираются сообщать о том, что конструктор копирования обломался? Похоже, этот фреймворк, как говорится, fundamentaly flawed.
www.blinnov.com
Re[16]: Вот еще, или я, кажется, читать разучился
От: Evgeny.Panasyuk Россия  
Дата: 23.02.13 21:02
Оценка:
Здравствуйте, landerhigh, Вы писали:

EP>>Например, что ты будешь делать без исключений в следующем случае?:

L><skip>
EP>>Приведи аналогичный код(клиентскую часть), но без использования исключений.
L>Меня больше интересует, как разработчики Tizen собираются сообщать о том, что конструктор копирования обломался? Похоже, этот фреймворк, как говорится, fundamentaly flawed.

Видимо вот так:
result     HashMap::Construct (const IMap &map, float loadFactor=0.75)

Вот только я по докам не вижу чтобы у них обычный copy constructor был забанен(либо как-то реализован).
У всемогущего Object'а он protected, но вот реализован он или нет —
Tizen::Base::Object::Object (const Object &obj) [protected]
//This is the copy constructor for the Object class.

Раз protected — то по-идеи реализован, иначе было бы просто private (compiler error лучше чем linker error).
Если у кого-нибудь есть .h — что там за layout у HashMap?
Re[18]: Вот еще, или я, кажется, читать разучился
От: jazzer Россия Skype: enerjazzer
Дата: 24.02.13 05:36
Оценка:
Здравствуйте, alex_public, Вы писали:

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


J>>Не влияет? Тут народ прямиком забивает на обработку ошибок, и это называется — не влияет? Это как раз отличная демонстрация безопасности так называемой "обработки" ошибок через коды возврата.


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


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

Ну и да, с исключениями игнорировать ошибки "короче и удобнее" не получится, вот ведь незадача.
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[19]: Вот еще, или я, кажется, читать разучился
От: alex_public  
Дата: 24.02.13 10:55
Оценка:
Здравствуйте, jazzer, Вы писали:

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


Кривой код можно найти под любую идею/технологию/платформу. Но это ничего не доказывает.

J>Ну и да, с исключениями игнорировать ошибки "короче и удобнее" не получится, вот ведь незадача.


Я правильно понял, что вы считаете нормальным использовать исключения для обработки всех видов ошибок?
Re[20]: Вот еще, или я, кажется, читать разучился
От: jazzer Россия Skype: enerjazzer
Дата: 24.02.13 12:55
Оценка: +3
Здравствуйте, alex_public, Вы писали:

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


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


_>Кривой код можно найти под любую идею/технологию/платформу. Но это ничего не доказывает.


Еще как доказывает. Есть такое понятие — error-prone. Не знаю, как правильно перевести, но смысл такой: приглашение совершить ошибку, легкость совершения ошибки.
Например, ручное управление памятью — error-prone.
Голые указатели — error-prone.
И обработка ошибок, построенная на кодах возврата — тоже error-prone, и обсуждаемый пример — замечательная тому иллюстрация.

J>>Ну и да, с исключениями игнорировать ошибки "короче и удобнее" не получится, вот ведь незадача.


_>Я правильно понял, что вы считаете нормальным использовать исключения для обработки всех видов ошибок?

Ошибок — да. Дальше можно порассуждать о том, что считать ошибкой.
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[17]: Вот еще, или я, кажется, читать разучился
От: landerhigh Пират  
Дата: 24.02.13 15:07
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

L>>Меня больше интересует, как разработчики Tizen собираются сообщать о том, что конструктор копирования обломался? Похоже, этот фреймворк, как говорится, fundamentaly flawed.


EP>Видимо вот так:

EP>
EP>result     HashMap::Construct (const IMap &map, float loadFactor=0.75)
EP>

EP>Вот только я по докам не вижу чтобы у них обычный copy constructor был забанен(либо как-то реализован).

Хех. Забавно:

Дока от Base::String.

Copying of objects using this copy constructor is allowed.


Кажется, мы имеем дело с т.н. epic fail.
www.blinnov.com
Re[21]: Вот еще, или я, кажется, читать разучился
От: ioj Ниоткуда  
Дата: 24.02.13 15:55
Оценка: -2
Здравствуйте, jazzer, Вы писали:

Вы ( не вы лично, а все сторонники исключений в этом треде) вообще читаете что в гугловском документе написано?

When you add a throw statement to an existing function, you must examine all of its transitive callers. Either they must make at least the basic exception safety guarantee, or they must never catch the exception and be happy with the program terminating as a result. For instance, if f() calls g() calls h(), and h throws an exception that f catches, g has to be careful or it may not clean up properly.

Весь код должен обеспечивать basic exception safety, иначе любое исключение, брошенное например в середине метода, легко и непринуждённо может оставить объект в inconsistent состоянии, и я думаю обеспечить эту exception safety гораздо сложнее чем обеспечить проверку всех возвращаемых значений. Далее:

More generally, exceptions make the control flow of programs difficult to evaluate by looking at code: functions may return in places you don't expect. This causes maintainability and debugging difficulties. You can minimize this cost via some rules on how and where exceptions can be used, but at the cost of more that a developer needs to know and understand.


это проблема номер два ( хотя может и номер один по важности ) с исключениями — сторонний execution flow создаваемый исключениями, я уже не могу сказать глядя на код что между вот этими двумя строками не произошло исключение и мы не пошли вообще по другому call graph. К тому же в С++ нет finally, поэтому ту же basic exception safety обеспечивать весьма геморройно, даже если тотально всё заворачивать в raii обвёртки, и даже если бы finally таки было, всё равно you're forced to obfuscate code to isolate the commit:

Exception safety requires both RAII and different coding practices. Lots of supporting machinery is needed to make writing correct exception-safe code easy. Further, to avoid requiring readers to understand the entire call graph, exception-safe code must isolate logic that writes to persistent state into a "commit" phase. This will have both benefits and costs (perhaps where you're forced to obfuscate code to isolate the commit). Allowing exceptions would force us to always pay those costs even when they're not worth it.
нормально делай — нормально будет
Re[22]: Вот еще, или я, кажется, читать разучился
От: jazzer Россия Skype: enerjazzer
Дата: 24.02.13 16:55
Оценка: 19 (5) +3
Здравствуйте, ioj, Вы писали:

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


ioj>Вы ( не вы лично, а все сторонники исключений в этом треде) вообще читаете что в гугловском документе написано?


ioj>When you add a throw statement to an existing function, you must examine all of its transitive callers. Either they must make at least the basic exception safety guarantee, or they must never catch the exception and be happy with the program terminating as a result. For instance, if f() calls g() calls h(), and h throws an exception that f catches, g has to be careful or it may not clean up properly.


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

ioj>Весь код должен обеспечивать basic exception safety, иначе любое исключение, брошенное например в середине метода, легко и непринуждённо может оставить объект в inconsistent состоянии, и я думаю обеспечить эту exception safety гораздо сложнее чем обеспечить проверку всех возвращаемых значений.


Это противоречит моему опыту. Basic exception safety достигается элементарно.

ioj>Далее:

ioj>More generally, exceptions make the control flow of programs difficult to evaluate by looking at code: functions may return in places you don't expect. This causes maintainability and debugging difficulties. You can minimize this cost via some rules on how and where exceptions can be used, but at the cost of more that a developer needs to know and understand.
ioj>


Это все не нужно. "control flow of programs", написанных на исключениях (т.е. обеспечивающих по крайней мере базовую безопасность), анализировать как раз проще всего — они выполняются до конца или пока не вылетит исключение, причем не важно откуда (кроме nothrow-функций, естественно — они никогда ничего не должны бросать).
Причем и в том, и в другом случае нам не нужно совершать дополнительных телодвижений по очистке и прочему, так как RAIIза всем проследит автоматически.
Разница будет, только если мы хотим обеспечивать сильную безопасность, а у нас на руках только базовая.

ioj>это проблема номер два ( хотя может и номер один по важности ) с исключениями — сторонний execution flow создаваемый исключениями, я уже не могу сказать глядя на код что между вот этими двумя строками не произошло исключение и мы не пошли вообще по другому call graph.

И не надо. Код надо писать, имея в виду, что почти любая функция может бросить исключение. Т.е. тотальный RAII.

ioj>К тому же в С++ нет finally

И очень хорошо, что нету. Оставим finally недоязыкам типа Java, у которых нет RAII.

ioj>поэтому ту же basic exception safety обеспечивать весьма геморройно, даже если тотально всё заворачивать в raii обвёртки

Не имею никакого геморроя с RAII-обертками, что я делаю не так?

ioj>и даже если бы finally таки было, всё равно you're forced to obfuscate code to isolate the commit:

ioj>Exception safety requires both RAII and different coding practices. Lots of supporting machinery is needed to make writing correct exception-safe code easy. Further, to avoid requiring readers to understand the entire call graph, exception-safe code must isolate logic that writes to persistent state into a "commit" phase. This will have both benefits and costs (perhaps where you're forced to obfuscate code to isolate the commit). Allowing exceptions would force us to always pay those costs even when they're not worth it.

А тут мы плавно подменили basic exception safety на strong exception safety и сделали вид, что говорим об одном и том же — молодца!

"avoid requiring readers to understand the entire call graph" — нафиг никому не нужен the entire call graph. Потому что функция либо играет до конца, либо вылетает по ислючению. Всё.

Опять же, утверждение про obfuscate противоречит моему опыту. Классический пример реализации сильной безопасности, как раз с изолированием коммита, выглядит вот так:
A& A::operator=(A rhs) // временный объект (т.к. по значению)
{
  swap( rhs );         // коммит (nothrow)
  return this;
}

Где ты тут видишь obfuscate?
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[22]: Вот еще, или я, кажется, читать разучился
От: enji  
Дата: 24.02.13 16:59
Оценка: 7 (1) +1
Здравствуйте, ioj, Вы писали:

ioj>Вы ( не вы лично, а все сторонники исключений в этом треде) вообще читаете что в гугловском документе написано?


ioj>When you add a throw statement to an existing function, you must examine all of its transitive callers. Either they must make at least the basic exception safety guarantee, or they must never catch the exception and be happy with the program terminating as a result. For instance, if f() calls g() calls h(), and h throws an exception that f catches, g has to be careful or it may not clean up properly.


ioj>Весь код должен обеспечивать basic exception safety, иначе любое исключение, брошенное например в середине метода, легко и непринуждённо может оставить объект в inconsistent состоянии, и я думаю обеспечить эту exception safety гораздо сложнее чем обеспечить проверку всех возвращаемых значений.


Думаешь? Ну так возвращаемые значения надо не только проверить, но и выполнить очистку, причем иногда очистка разная в зависимости от того, на каком именно этапе облом Собственно это ровно то же самое, что и с исключениями. Единственное — при ручной проверке кодов возврата ты видишь в коде места, где у тебя может случиться облом. А при исключениях — считаешь что он может случиться в любом месте. Поэтому когда пишут с "поддержкой" исключений, обычно используют автоматические техники — типа RAII или BOOST_SCOPED_EXIT. А вот когда пишут на кодах возврата — обычно делают вручную, что и приводит к багам, как в коде выше...

ioj>More generally, exceptions make the control flow of programs difficult to evaluate by looking at code: functions may return in places you don't expect. This causes maintainability and debugging difficulties. You can minimize this cost via some rules on how and where exceptions can be used, but at the cost of more that a developer needs to know and understand.

ioj>


ioj>это проблема номер два ( хотя может и номер один по важности ) с исключениями — сторонний execution flow создаваемый исключениями, я уже не могу сказать глядя на код что между вот этими двумя строками не произошло исключение и мы не пошли вообще по другому call graph.

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

ioj>К тому же в С++ нет finally, поэтому ту же basic exception safety обеспечивать весьма геморройно, даже если тотально всё заворачивать в raii обвёртки,

об отсутствии finally иногда жалею, но есть SCOPED_EXIT, а в частых случаях — готовые raii-обертки. Так что насчет геморройности не согласен.

ioj>и даже если бы finally таки было, всё равно you're forced to obfuscate code to isolate the commit:

Ты так говоришь, как будто с кодами возврата нет такой проблемы. Если ты сделал что-то изменяющее мир, а потом случилась ошибка — какая разница, код возврата это или исключение? Тебе надо или вернуть все назад или переработать метод, чтобы мир изменялся после всех потенциально-ошибочных операций...
Re[3]: это не Tizen 2.0!!!!
От: dr. Acula Украина  
Дата: 24.02.13 18:15
Оценка:
J>В Самсунге сидят такие быдлокодеры — вам и не снились.. (инсайдерская инфа).

А где не быдлокодеры сидят?
Можно списочек в студию?
Re[4]: это не Tizen 2.0!!!!
От: Vzhyk  
Дата: 24.02.13 18:29
Оценка: 1 (1)
On 24.02.2013 21:15, dr. Acula wrote:

> А где не быдлокодеры сидят?

> Можно списочек в студию?
Это секретная информация и никто ею с тобой не поделится. Откуда сидящие
там знают, что ты не "быдлокодер".
Posted via RSDN NNTP Server 2.1 beta
Re[21]: Вот еще, или я, кажется, читать разучился
От: alex_public  
Дата: 24.02.13 22:17
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Еще как доказывает. Есть такое понятие — error-prone. Не знаю, как правильно перевести, но смысл такой: приглашение совершить ошибку, легкость совершения ошибки.

J>Например, ручное управление памятью — error-prone.
J>Голые указатели — error-prone.
J>И обработка ошибок, построенная на кодах возврата — тоже error-prone, и обсуждаемый пример — замечательная тому иллюстрация.

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

Да, и кстати как раз под этот конкретный пример... Не исключено что обработка ошибок через исключения в данном случае заняла бы больший объём кода, чем даже корректная (а не как в примере) обработка через возвращаемое значение. Потому как там такая логика, что при возникновение ошибок главная функция не прерывается, а просто не выполняет какую-то команду там дальше. Т.е. тут не работает главная фишка исключений с раскруткой стека и обработкой снаружи главной функции и надо ставить try catch чуть ли не вокруг каждого вызова внутренних функций. И это как раз то, о чём я писал в той темке когда-то, что в отличие от теории, применение исключений на практике часто неудобнее старых методов...

_>>Я правильно понял, что вы считаете нормальным использовать исключения для обработки всех видов ошибок?

J>Ошибок — да. Дальше можно порассуждать о том, что считать ошибкой.

Нуу вот есть классический пример. Пользователь даёт команду сохранить данные в файл, а он оказывается заблокирован. Это как у нас считается?
Re[22]: Вот еще, или я, кажется, читать разучился
От: landerhigh Пират  
Дата: 25.02.13 01:37
Оценка: +2
Здравствуйте, alex_public, Вы писали:


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


Мое HO — данный конкретный пример как раз показывает, что такое исключительная ситуация. Плагин добавляет контролы. Если добавление какого-то контрола обламывается, то это именно исключительная ситуация без разговоров и самая правильная стратегия в данном случае — прекратить инициализацию вообще и не пытаться умничать. Никогда не встречали программы, которые при каких-либо сценариях выдавали по полторы сотни мессаджбоксов друг за другом, каждый с многозначительным сообщением типа "ошибка инициализации"?
Здесь исключение — наиболее натуральный вариант. Выход по первому error, в принципе, тоже сработает, но получился лес if-ов.

Кстати, из кода очевидно, что код этот никак не тестировался для негативного случая.
www.blinnov.com
Re[22]: Вот еще, или я, кажется, читать разучился
От: landerhigh Пират  
Дата: 25.02.13 01:39
Оценка: +2 :)
Здравствуйте, ioj, Вы писали:

ioj>Вы ( не вы лично, а все сторонники исключений в этом треде) вообще читаете что в гугловском документе написано?


Читали. Мое мнение — хорошо, что гугловских инженеров к Боингам подпускают только в качестве пассажиров.
www.blinnov.com
Re[23]: Вот еще, или я, кажется, читать разучился
От: Erop Россия  
Дата: 25.02.13 02:14
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Это противоречит моему опыту. Basic exception safety достигается элементарно.

Это говорит о том, что либо твоё "элементарно" -- это малодостижимый уровнь для типичного программиста, либо о том, что мы с тобой как-то по-разному, понимаем что такое "basic exception safety", либо ты не имеешь дела никогда со сложными структурами данных, либо ты лукавишь...

Я верно же понимаю, что под "basic exception safety" понимают гарантию того, что при вылете исключения, могут быть сторонние эффекты, но не могут нарушаться инварианты и не случится утечек?..

Если так, то в качестве примера, нарисуй нам горантирующий basic exception safety метод std::vector, который переаллоцирует буфер, и при этом поддерживает move-семантику соержимого...
Пусть у move-конструктора элемента тоже будет "basic exception safety", а у деструктора гарантия невылета...

J>Это все не нужно. "control flow of programs", написанных на исключениях (т.е. обеспечивающих по крайней мере базовую безопасность), анализировать как раз проще всего — они выполняются до конца или пока не вылетит исключение, причем не важно откуда (кроме nothrow-функций, естественно — они никогда ничего не должны бросать).

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

J>И не надо. Код надо писать, имея в виду, что почти любая функция может бросить исключение. Т.е. тотальный RAII.


Это вообще никак не гарантирует "basic exception safety"...
J>Не имею никакого геморроя с RAII-обертками, что я делаю не так?
Ты всё делаешь так.
Покажи нам мастер-класс, пожалуйста. На примере переаллокации буфера вектора, например

J>Опять же, утверждение про obfuscate противоречит моему опыту. Классический пример реализации сильной безопасности, как раз с изолированием коммита, выглядит вот так:

J>
J>A& A::operator=(A rhs) // временный объект (т.к. по значению)
J>{
J>  swap( rhs );         // коммит (nothrow)
J>  return this;
J>}
J>

J>Где ты тут видишь obfuscate?

Теперь давай напишем структуру, поля которой -- A.
Для неё как будем сильную безопасность обеспечивать?..

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