SYG>Отсечка неправильных данных должна произойти на входе данных в систему. То есть, пользователь ввел неправильные данные, а они раз, и не ввелись, а выскочило диалоговое окно — "Введенные данные не правильные." Внутри системы неправильных данных быть не должно.
Это некое благое пожелание, не более, потому что непонятно, что такое правильность данных.
Допустим, у нас есть int-овая переменная x. Допустимо ли в ней хранить значение 0, или отрицательные значения?
По идее, допустимо. Допустимо ли где-то в отдельном модуле делить на эту переменную? По идее, тоже допустимо.
Но как тогда быть, если в какой-то конкретный момент x все-таки оказался равным нулю, и данную переменную необходимо передать в модуль, который содержит операцию делению.
приведу, простой пример, поясняющий данную ситуацию:
int x = Input();
if (внешнее условие)
x = 1/x;
Внимание, вопрос: допустимо ли хранить в переменной x значение равное нулю? И что делать, если в x был 0, и мы дошли до операции деления на ноль?
SYG>Точно не отвечу. Система BlackBox (эмулятор ОС Оберон под Виндос), кажется, переходит к выполнению следующей итерации своего главного цикла. Если есть исходный код модуля, то выскакиевает диалоговое окно со списком стека вызовов последних нескольких процедур со всеми значениями локальных переменных.
Что будет происходить, если система работает в автономной режиме? Когда никакого внешнего пользователя нет?
Система будет тупо ждать, когда кто-нибудь придет и закроет диалоговое окно?
Re[22]: Недопустимая операция = Исключительная ситуация
SYG>Отсечка неправильных данных должна произойти на входе данных в систему. То есть, пользователь ввел неправильные данные, а они раз, и не ввелись, а выскочило диалоговое окно — "Введенные данные не правильные." Внутри системы неправильных данных быть не должно.
Как быть, если мы соединяем две разных системы, т.е. никакого пользователя нет, вместо пользователя используется некая другая система, и данные с одной системы передаются в другую систему, с помощью какого механизма будет происходить отсечка данных?
через возращения кода ошибки?
SYG>Какие проблемы-то? Я позволил себе сказать, что в Оберонах нет механизма "исключительных ситуаций" и объяснил почему он там излишен. Если Вы видите проблему, то объясните в чем состоит ее суть?
Суть проблемы в том, что оберон не предназначен для задач, в которых возможны динамические ошибки, т.е. для тех ситуаций, когда мы заранее не можем предсказать будет ошибка или нет, т.е. для тех задач, которые, например, описываются алгоритмом: попробовать вот так, если не получится, то попробовать вот так.
т.е. оберон предназначен только для тех ситуаций, в которых мы заранее можем предусмотреть все варианты. Но такие задачи — или очень малы по объему, или требуют колосальных материальных затрат, т.к. необходимо на этапе разработке рассматривать все, даже исключительные варианты. Причем опыт показывает, что даже в этих случаях, обеспечить стопроцентный разбор вариантов не представляется возможным, и все равно получаются ситуации, которые не были предусмотрены разработчиком.
SYG>>Точно не отвечу. Система BlackBox (эмулятор ОС Оберон под Виндос), кажется, переходит к выполнению следующей итерации своего главного цикла. Если есть исходный код модуля, то выскакиевает диалоговое окно со списком стека вызовов последних нескольких процедур со всеми значениями локальных переменных.
DG>Что будет происходить, если система работает в автономной режиме? Когда никакого внешнего пользователя нет? DG>Система будет тупо ждать, когда кто-нибудь придет и закроет диалоговое окно?
Если система автономная, то в ней, обычно, нет исходников — только бинарники. Кроме того в ней, обычно, нет подсистемы компилятора.
Re[23]: Недопустимая операция = Исключительная ситуация
Здравствуйте, DarkGray, Вы писали:
DG>Внимание, вопрос: допустимо ли хранить в переменной x значение равное нулю? И что делать, если в x был 0, и мы дошли до операции деления на ноль?
В общем случае ответом на этот вопрос является правильное проектирование, чтобы никогда не приходилось делить на ноль. А в каждом конкретном примере это нужно уточнять.
Конкретный пример:
Vx := x1 - x0;
Vy := y1 - y0;
V := Math.Sqrt(Vx*Vx + Vy*Vy);
IF V > 0 THEN
Vx := Vx/V;
Vy := Vy/V;
END;
Re[23]: Недопустимая операция = Исключительная ситуация
Здравствуйте, DarkGray, Вы писали:
SYG>>Отсечка неправильных данных должна произойти на входе данных в систему. То есть, пользователь ввел неправильные данные, а они раз, и не ввелись, а выскочило диалоговое окно — "Введенные данные не правильные." Внутри системы неправильных данных быть не должно.
DG>Как быть, если мы соединяем две разных системы, т.е. никакого пользователя нет, вместо пользователя используется некая другая система, и данные с одной системы передаются в другую систему, с помощью какого механизма будет происходить отсечка данных? DG>через возращения кода ошибки?
SYG>>>Во-первых, если Вам обязательно надо что-то возвращать, то ни кто не заставляет Вас возвращать именно номер_кода_ошибки. Возвращайте пожалуйста полиморфную переменную внутри которой инкапсулирована информация о причине отказа выполнить операцию — то есть все так же как и при механизме исключений — "фиолетово". Сборщик мусора поможет Вам не беспокоится о возможной растрате памяти на эти полиморфные переменные. SYG>>>Во-вторых, Вы не обязаны что-то возвращать. Если Вам известно что какая-то операция потенциально опасна, то прежде чем ее выполнять, Вы "морально обязаны" проверить правильность параметров (проверить индекс массива на попадание в нужный диапазон, проверить указатель на неравенство NIL, проверить динамический тип полиморфной переменной, проверить не получится ли у Вас арифметическое переполнение, деление на ноль и т.д.) и только после того как Вы убедились в том, что данные правильные, вот только после этого приступать к выполнению потенциально опасной операции. Если в этом случае эта операция все-равно провалится, то поскольку согласно логике программы данные правильные и никакой ошибки быть не должно — это означает, что причина ошибки находится вне логики программы (кто-то отцепил жесткий диск, повредил молотком процессор и т.п.), следовательно дальнейшее выполнение программы не имеет смысла.
Если никакого пользователя нет, а данные поставляются из одной программы внутрь другой, то все очень просто. У программы принимающей данные есть задокументированный интерфейс по которому она должна работать. Если программа-поставщих-данных нарушает этот интерфейс поставляя некорректные данные, то она сама виновата. Реакция программы-приемника на некорректные данные будет такой как оговорено в ее интерфейсе. Если в интерфейсе ничего не оговорено, то есть вариант по умолчанию — модуль аварийно завершает свою работу. Именно такое поведение системы по умолчанию превращает "моральную обязанность" (вначале данные проверять прежде чем заставлять с ними кого-то работать) из простого пожелания в материальное жесткое требование, то есть это уже не моральная обязанность, а самая настоящая обычная обязанность. А это уже является главной основой построения сверхнадежных систем. Таким образом сам язык программирования заставляет писать надежный код.
Здравствуйте, eugals, Вы писали:
E>Здравствуйте, S.Yu.Gubanov, Вы писали:
E>А почему нужно выгружать именно модуль (в том значении этого слова, в котором ты его понимаешь)? Почему не группу модулей? Или наоборот — один только класс из "модуля"? Или Метод? Или, даже, секцию кода внутри метода (расположенную в блоке try)?
Выгружать можно только то что в принципе можно выгружать/загружать — то что является единицей исполнения — только модуль — это наименьшая единица исполнения. Класс, метод, секция кода — не единицы исполнения. Кстати, гипотетически, ничто не запрещает Вам писать модули состоящие всего из одной процедуры.
E>И (DarkGray про это уже рядом сказал), как мне описать процедуру выгрузки (в смысле разрешения конфликтов с другими модулями), чтобы указать что вот этот вот модуль нужно перечитать, а вот эти не трогать, а вместо этого, в случае чего, можно взять вон тот и т.п.? Для этого нужно какой-то параллельный код держать (в котором, кстати, в свою очередь, тоже возможны ошибки) и постоянно следить за его релевантностью.
Это уже детали. Не для раздела "Философия программирования".
E>И вообще, почему обязательно "выгружать"? Может программисту в данных обстоятельствах проще только прервать выполнение проблемной секции, для чего (в частности) собственно и существуют эти самые исключения...
Выгружать, например, чтобы загрузить другой модуль. А секцию кода Вы другой не сделаете — она в exe-шникие жестко прописана. Наверное, всяко лучше когда система состоит из большого количества динамически загружаемых/выгружаемых модулей, чем когда она представляет собой один громадный монолитный exe-шник.
Здравствуйте, S.Yu.Gubanov, Вы писали:
_O_>>Какие серьезные продукты созданы на базе этого языка ?
SYG>Недавно была конференция где об этом все друг другу хвастались SYG>http://cern.ch/oberon.day
SYG>Там в разделе Presentations среди прочих презентаций есть презентация
SYG>C. Pfister (Oberon microsystems) SYG>BlackBox: An Industrial-Strength Oberon Implementation
SYG>там хвастаются как они для электростанции написали ПО.
Хм.. Сложилось впечатление, что сей язык больше для научных расчетов подходит.
Здравствуйте, DarkGray, Вы писали:
SYG>>Какие проблемы-то? Я позволил себе сказать, что в Оберонах нет механизма "исключительных ситуаций" и объяснил почему он там излишен. Если Вы видите проблему, то объясните в чем состоит ее суть?
DG>Суть проблемы в том, что оберон не предназначен для задач, в которых возможны динамические ошибки, т.е. для тех ситуаций, когда мы заранее не можем предсказать будет ошибка или нет, т.е. для тех задач, которые, например, описываются алгоритмом: попробовать вот так, если не получится, то попробовать вот так.
Вот и слава богу, что для такого способа решения задач он не предназначен!
DG>т.е. оберон предназначен только для тех ситуаций, в которых мы заранее можем предусмотреть все варианты. Но такие задачи — или очень малы по объему, или требуют колосальных материальных затрат, т.к. необходимо на этапе разработке рассматривать все, даже исключительные варианты.
Думаю, что ПО для электростанции под эту категорию подходит в самый раз.
DG> Причем опыт показывает, что даже в этих случаях, обеспечить стопроцентный разбор вариантов не представляется возможным, и все равно получаются ситуации, которые не были предусмотрены разработчиком.
Опыт опыту — рознь, Я, благодаря интернету, знаю одного человека, который с Вами бы в этом вопросе сильно не согласился. В форуме на progz.ru он известен под ником ASU: ASU>Три года назад одна зарубежная компания пригласила меня в качестве консультанта. Цель, которую поставила перед собой эта компания, — создание сложной системы. Знакомство с их проектом показало, что необходимо порядка 200-300 разработчиков и лет десять для его реализации. Говоря Вашим языком, было необходимо создать “конвейер" под этот проект, сделав разработчиков “винтиками" данного “механизма". Но я предложил им иной путь. Проект был в корне пересмотрен, и мы постарались, дабы каждая сущность обрела свой настоящий смысл. В результате проект был сделан 13-15 разработчиками за полгода. Но дело даже не в сроках, а в том, что каждый разработчик был со-Творцом системы. Не потребовалось никаких “конвейеров", ни методик a-la CMM, ни извращений UML. А я получал искреннее удовольствие от светящих глаз разработчиков. Это была лучшая награда. http://progz.ru/forum/viewtopic.php?t=9356&postdays=0&postorder=asc&start=15
А метода у него "простая": проектировать все сразу и, по возможности, без ошибок.
Re[24]: Недопустимая операция = Исключительная ситуация
SYG> Если в интерфейсе ничего не оговорено, то есть вариант по умолчанию — модуль аварийно завершает свою работу. Именно такое поведение системы по умолчанию превращает "моральную обязанность" (вначале данные проверять прежде чем заставлять с ними кого-то работать) из простого пожелания в материальное жесткое требование, то есть это уже не моральная обязанность, а самая настоящая обычная обязанность. А это уже является главной основой построения сверхнадежных систем. Таким образом сам язык программирования заставляет писать надежный код.
Но пользователям от такой "надежности" никакой пользы нет, а есть только одни убытки.
Получается, что у нас есть четкая граница между теми вариантами, что программист предусмотрел, и что не предусмотрел.
Пока программа работает в предусмотренных ситуациях — все хорошо, все надежно, никаких ошибок,
но как-то только появляется незапланированная ситуация — так сразу, вся система накрывается, т.к. в саму систему не заложена работа в плохих ситуациях.
Но еще раз повторю, что реальные системы полностью заранее описать нельзя, либо это превращается в очень дорогое удовольствие.
Т.е. при тестовых должны караться любые, даже мелкие неточности, но при работе в реальных условиях — мелкие ошибки лучше "проглатывать", чтобы повысить общую надежность системы.
Здравствуйте, DarkGray, Вы писали:
DG>Пока программа работает в предусмотренных ситуациях — все хорошо, все надежно, никаких ошибок, DG>но как-то только появляется незапланированная ситуация — так сразу, вся система накрывается, т.к. в саму систему не заложена работа в плохих ситуациях.
Во-первых, откуда такой вывод?
А, во-вторых, что такое "незапланированная ситуация"?
Досих пор в качестве "незапланированной ситуации" предлагались следующие варианты:
1) Дискета не читается (и т.п. про файлы и файловую систему)
2) Сеть упала (и т.п. с сетью)
3) Данные не правильные (все что касается обмена данными)
Не знаю как Вам, а мне эти ситуации не кажутся "незапланированными". Все эти ситуации любая нормальная программа вполне в состоянии учесть, причем не используя для этого механизм исключительных ситуаций.
DG>>Пока программа работает в предусмотренных ситуациях — все хорошо, все надежно, никаких ошибок, DG>>но как-то только появляется незапланированная ситуация — так сразу, вся система накрывается, т.к. в саму систему не заложена работа в плохих ситуациях.
SYG>Во-первых, откуда такой вывод? SYG>А, во-вторых, что такое "незапланированная ситуация"?
Незапланированная ситуация — это состояние нашего модуля или поведение внешних модулей, которое не рассматривалось при проектировании, и программировании.
SYG>Досих пор в качестве "незапланированной ситуации" предлагались следующие варианты: SYG>1) Дискета не читается (и т.п. про файлы и файловую систему) SYG>2) Сеть упала (и т.п. с сетью) SYG>3) Данные не правильные (все что касается обмена данными) SYG>Не знаю как Вам, а мне эти ситуации не кажутся "незапланированными". Все эти ситуации любая нормальная программа вполне в состоянии учесть, причем не используя для этого механизм исключительных ситуаций.
Стандартный пример.
есть вот такой интерфейс:
interface IUser
{
string Name {get;}
int Age {get;}
//и т.д.
}
стандартная реализация:
class User:IUser
{
public string Name {get {return"Вася Иванов";}}
public int Age {get {return 12;}}
}
Код, который использует данный интерфейс, на ошибки не закладывается, т.к. в таком простом интерфейсе ошибок просто нет.
Но, допустим, через некоторое время принимается решение, что юзер выносится или в другое адресное пространство, или, например, кэшируется на винт.
т.е. что такое:
class CachedUser:IUser
{
public string Name
{
get
{
using (StreamReader reader = new StreamReader("cached.txt"))
{
return reader.ReadLine();
}
}
}
}
Получается, что класс User-а уже может генерить ошибку, хотя изначально никаких ошибок не предполагалось
Здравствуйте, DarkGray, Вы писали:
DG>Стандартный пример.
... DG>Получается, что класс User-а уже может генерить ошибку, хотя изначально никаких ошибок не предполагалось
Вы привели самый что ни на есть "Стандартный пример" не правильного проектирования. Если есть вероятность того, что возвращаемые данные могут быть не валидными, то стандартный паттерн проектирования интерфейса такой:
TYPE
Name = POINTER TO ARRAY OF CHAR;
User = POINTER TO ABSTRACT RECORD
done-: BOOLEAN;
(u: User) GetAge (OUT age: INTEGER), NEW, ABSTRACT;
(u: User) GetName (OUT name: Name), NEW, ABSTRACT
END;
Булевская переменная done доступная только для чтения (-) содержит в себе информацию о том удалось ли выполнить последнюю операцию.
VAR u: User;
x: INTEGER;
...
u.GetAge(x);
IF u.done THEN ... END;
Никакая ошибка нигде не генерится. Можно пойти дальше и, например, узнать почему последняя операция провалилась. Например, так:
TYPE
User = POINTER TO ABSTRACT RECORD
done- : BOOLEAN;
Error-: Error;
...
Error — полиморфная переменная типа список "абстрактных ошибок".
TYPE
Error = POINTER TO ABSTRACT RECORD
...информация об ошибке
Next-: Error; предыдущая ошибка
END;
это лишь один из бесчисленного количества возможных вариантов.
Re[22]: Недопустимая операция = Исключительная ситуация
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Отсечка неправильных данных должна произойти на входе данных в систему. То есть, пользователь ввел неправильные данные, а они раз, и не ввелись, а выскочило диалоговое окно — "Введенные данные не правильные." Внутри системы неправильных данных быть не должно.
Вот хотим мы сохранить файл. А откуда ядро графического редактора (к примеру) знает, какие имена файлов недопустимы? А если оно используется не под Win, а под Unix или Mac? Все ошибки проверки работы с файлами и все ошибки на этой почве должен генерировать модуль работы с файлами. Тогда мы легко заменим его на аналогичный другого производителя (под Mac, например), а ядро редактора подмены и не заметит.
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Никакая ошибка нигде не генерится. Можно пойти дальше и, например, узнать почему последняя операция провалилась. Например, так: SYG>
SYG>TYPE
SYG> User = POINTER TO ABSTRACT RECORD
SYG> done- : BOOLEAN;
SYG> Error-: Error;
SYG> ...
SYG>
SYG>Error — полиморфная переменная типа список "абстрактных ошибок". SYG>
SYG>TYPE
SYG> Error = POINTER TO ABSTRACT RECORD
SYG> ...информация об ошибке
SYG> Next-: Error; предыдущая ошибка
SYG> END;
SYG>
SYG>это лишь один из бесчисленного количества возможных вариантов.
И чем ЭТО страшилище лучше механизма исключений? Он и есть, только ты сам должен поддерживать всю инфраструктуру, а так за тебя это делает компилятор. ИМХО так.
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Что же Вы о создателях Оберон систем так плохо думаете? Разумеется будет остановлена работа только того модуля, который выполнил недопустимую операцию. Модуль будет динамически выгружен из системы. Когда другие модули запросят доступ к нему, он автоматически загрузится в память обратно. Так сказать — горячая перезагрузка — на лету. Вместо этого модуля, если угодно, может быть загружен модуль от другого производителя. Или, гипотетически, этот модуль будет "на лету" перекомпилирован заново, ошибка в нем исправлена, а его новый скомпилированный вариант динамически загружен в память. Что может быть устойчивее и надежнее? Вы бы, извините конечно, прежде чем глупые фантазии излагать вспомнили бы в каких областях Обероны используются: для случаев требующих особой безопасности — космос, электростанции, беспилотные летательные (военные) аппараты.
Вот оно откуда ноги растут — апологет Оберона объявился и готов (как миссионер ), обратить всех в истинную веру. Походу доказывая, что все ваши боги суть демоны и помощь их суть проклятие, а что его Бог никому не помогает, так ему и не положено . Кошмар
Здравствуйте, Larm, Вы писали:
L>И чем ЭТО страшилище лучше механизма исключений? Он и есть, только ты сам должен поддерживать всю инфраструктуру, а так за тебя это делает компилятор. ИМХО так.
А я и не говорил что без механизма исключений будет проще или удобнее. Я всего лишь говорил только то, что при наличии в системе сборщика мусора и "автостопа" при совершении "недопустимых операций" механизм возбуждения (кустарных, самодельных, пользовательских) исключений в принципе излишний. А мне пытались "впарить" что без механизма исключений ничего серьезного сделать вообще нельзя. Без него можно, но проектировать все нужно по другому.
Да, насколько мне известно (могу ошибаться), что в Black Box Oberon если не компилирировать в код Java VM, то память освобождается сразу же после того, как объект становитсья ненужным. Т. е. это не сборщик мусора в понимании .NET, это скорее подсчет ссылок как в интерфейсах в Delphi.